             [clojure.walk :refer [postwalk]]
             [cheshire.core :as json]
             [abracad.avro.util :refer [returning mangle unmangle]])
-  (:import [java.io ByteArrayOutputStream InputStream EOFException]
+  (:import [java.io
+             ByteArrayOutputStream EOFException File InputStream OutputStream]
            [clojure.lang Named]
            [org.apache.avro Schema Schema$Parser Schema$Type]
-           [org.apache.avro.file CodecFactory DataFileWriter DataFileReader]
+           [org.apache.avro.file
+             CodecFactory DataFileWriter DataFileReader SeekableInput
+             SeekableFileInput]
            [org.apache.avro.io
              DatumReader DatumWriter Decoder DecoderFactory
              Encoder EncoderFactory]

(defn binary-decoder
  "Return a binary-encoding decoder for `source`.  The `source` may be
an input stream, a byte array, or a vector of `[bytes off len]`."
  {:tag 'org.apache.avro.io.Decoder}
  [source]
  (if-not (vector? source)
    (decoder-factory binaryDecoder source nil)
    (let [[source off len] source]
      (decoder-factory binaryDecoder source off len nil))))

(defn direct-binary-decoder
  "Return a non-buffered binary-encoding decoder for `source`."
  {:tag 'org.apache.avro.io.Decoder}
  [source] (decoder-factory directBinaryDecoder source nil))

(defn json-decoder
  "Return a JSON-encoding decoder for `source` using `schema`."
  {:tag 'org.apache.avro.io.Decoder}
  [schema source] (decoder-factory jsonDecoder schema source))

(defn ^:private coerce
  "Coerce `x` to be of class `c` by applying `f` to it iff `x` isn't


(defn datum-writer
  "Return an Avro DatumWriter which consumes Clojure data structures."
  {:tag `ClojureDatumWriter}
  ([] (ClojureDatumWriter.))
  ([schema] (ClojureDatumWriter. schema)))

(defn data-file-writer
  "Return an Avro DataFileWriter which consumes Clojure data structures."
  {:tag `DataFileWriter}
  ([] (DataFileWriter. (datum-writer)))
  ([sink]
     (let [^DataFileWriter dfw (data-file-writer)]
       (doto dfw (.appendTo (io/file sink)))))
  ([schema sink]
     (data-file-writer nil schema sink))
  ([codec schema sink]
     (let [^DataFileWriter writer (data-file-writer)]
       (when codec (.setCodec writer (codec-for codec)))
       (if (instance? OutputStream)
         (.create writer ^Schema schema ^OutputStream sink)
         (.create writer ^Schema schema (io/file sink)))
       writer)))

(defmacro ^:private encoder-factory
