     (wrap/wrap-header codec)
     (throw (ex-info (str "Multiplexer does not contain codec for key "
                          (pr-str codec-key) " " (pr-str (keys (:codecs mux))))
-                    {:codec-keys (keys (:codecs mux))
+                    {:codecs (keys (:codecs mux))
                      :key codec-key}))))
 
 
 (defn mux-codec
   "Creates a new multiplexing codec which delegates to the given collection of
-  codecs by reading and writing multicodec headers when coding.
+  codecs by reading and writing multicodec headers when serializing values.
 
-  By default, the first codec given is used for all encoding. The codec's
-  `:header` is written first, then the codec is used to write the value.
+  When encoding a value, the multiplexer will look for the first codec which
+  reports it is `encodable?`. The selected codec's header is written first,
+  then the codec is used to write the value.
 
-  When decoding, the multiplexer tries to read a multicodec header and looks up
-  the corresponding codec in the `codecs` map. The codec is used to read a
-  value from the remaining data.
+  When decoding, the multiplexer tries to read a multicodec header and looks
+  for the first codec which reports the header is `decodable?`. The selected
+  codec is then used to read a value from the remaining data.
 
-  As a consequence, the delegated codecs _must not_ write or expect to consume
-  their own headers!"
+  As a consequence, the delegated codecs _must_ implement the codec predicates
+  and _must not_ write or expect to consume their own headers!"
   [& codecs]
   (when-not (seq codecs)
     (throw (IllegalArgumentException.

(ns multicodec.codecs.mux
  "Multiplexing codec which uses a set of iternal functions to decide which
  codec to use when encoding or decoding data.

  - `codecs` is a map from keys to codecs.
  - `select-encoder` takes the collection of codecs and the value to be encoded
    and returns a key identifying the codec to write the value with.
  - `select-decoder` takes the collection of codecs and the header path and
    returns a key identifying the codec to read the value with.

  By default, the selection functions will look for codecs which can encode and
  decode the values and headers passed to the mux codec."
  (:require
    [multicodec.core :as codec]
    [multicodec.header :as header]
    [multicodec.codecs.wrap :as wrap]))


(defn find-encodable
  "Finds a codec in the map which can encode the given value. Returns the key
  for the codec, or nil if none are found."
  [codecs value]
  (ffirst (filter #(codec/encodable? (val %) value) codecs)))


(defn find-decodable
  "Finds a codec in the map which can decode the given header. Returns the key
  for the codec, or nil if none are found."
  [codecs header]
  (ffirst (filter #(codec/decodable? (val %) header) codecs)))


(defn- resolve-codec!
  "Returns the selected codec, if it exists. Otherwise, throws an exception."
  [codecs selected value]
  (when-not selected
    (throw (ex-info
             (str "No codec selected for: " (pr-str value))
             {:codecs (keys codecs)
              :value value})))
  (when-not (get codecs selected)
    (throw (ex-info
             (str "Selected codec " selected " which is not present in"
                  " the codec map " (pr-str (seq (keys codecs)))
                  " for: " (pr-str value))
             {:codecs (keys codecs)
              :selected selected
              :value value})))
  (get codecs selected))




      (throw (IllegalArgumentException.
               (str "Every codec must specify a header path: "
                    (pr-str bad-codecs)))))
    (MuxCodec. "/multicodec" codec-map)))


;; Remove automatic constructor functions.
