 
 
 (defrecord MuxCodec
-  [header codecs select-encoder select-decoder]
+  [header codecs]
 
   codec/Encoder
 
   (encodable?
     [this value]
-    (boolean (when-let [codec (get codecs (select-encoder codecs value))]
-               (codec/encodable? codec value))))
+    (boolean (find-encodable codecs value)))
 
 
   (encode!
     [this output value]
-    (let [codec-key (select-encoder codecs value)
-          codec (resolve-codec! codecs codec-key value)]
-      (when (bound? #'*dispatched-codec*)
+    (let [[codec-key codec] (find-encodable codecs value)]
+      (when-not codec
+        (throw (ex-info
+                 (str "No codecs can encode value: " (pr-str value))
+                 {:codecs (keys codecs)
+                  :value value})))
+      (when (and (bound? #'*dispatched-codec*)
+                 (nil? *dispatched-codec*))
         (set! *dispatched-codec* codec-key))
       (wrap/write-header-encoded! codec output (:header codec) value)))
 

    (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))
                     :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.

  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 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.

  As a consequence, the delegated codecs _must not_ write or expect to consume
  their own headers!"
  [& codecs]
  (when-not (seq codecs)
    (throw (IllegalArgumentException.


  (decodable?
    [this header']
    (boolean (find-decodable codecs header')))


  (decode!
    [this input]
    (let [header' (header/read-header! input)
          [codec-key codec] (find-decodable codecs header')]
      (when-not codec
        (throw (ex-info
                 (str "No codecs can decode header: " (pr-str header'))
                 {:codecs (keys codecs)
                  :header header'})))
      (when (and (bound? #'*dispatched-codec*)
                 (nil? *dispatched-codec*))
        (set! *dispatched-codec* codec-key))
      (codec/decode! codec input))))

