faster malli coercion

This commit is contained in:
Tommi Reiman 2020-05-25 21:54:55 +03:00
parent a2d8208600
commit ea5ec93793

View file

@ -13,7 +13,11 @@
;; coercion ;; coercion
;; ;;
(defrecord Coercer [decoder encoder validator explainer]) (defprotocol Coercer
(-decode [this value])
(-encode [this value])
(-validate [this value])
(-explain [this value]))
(defprotocol TransformationProvider (defprotocol TransformationProvider
(-transformer [this options])) (-transformer [this options]))
@ -32,10 +36,16 @@
(defn- -coercer [schema type transformers f encoder opts] (defn- -coercer [schema type transformers f encoder opts]
(if schema (if schema
(let [->coercer (fn [t] (if t (->Coercer (m/decoder schema opts t) (let [->coercer (fn [t]
(m/encoder schema opts t) (let [decoder (if t (m/decoder schema opts t) (constantly true))
(m/validator schema opts) encoder (if t (m/encoder schema opts t) (constantly true))
(m/explainer schema opts)))) validator (m/validator schema opts)
explainer (m/explainer schema opts)]
(reify Coercer
(-decode [_ value] (decoder value))
(-encode [_ value] (encoder value))
(-validate [_ value] (validator value))
(-explain [_ value] (explainer value)))))
{:keys [formats default]} (transformers type) {:keys [formats default]} (transformers type)
default-coercer (->coercer default) default-coercer (->coercer default)
encode (or encoder (fn [value _format] value)) encode (or encoder (fn [value _format] value))
@ -44,29 +54,23 @@
default-coercer (constantly default-coercer))] default-coercer (constantly default-coercer))]
(if get-coercer (if get-coercer
(if (= f :decode) (if (= f :decode)
;; decode -> validate ;; decode: decode -> validate
(fn [value format] (fn [value format]
(if-let [coercer (get-coercer format)] (if-let [coercer (get-coercer format)]
(let [decoder (:decoder coercer) (let [transformed (-decode coercer value)]
validator (:validator coercer) (if (-validate coercer transformed)
transformed (decoder value)]
(if (validator transformed)
transformed transformed
(let [explainer (:explainer coercer) (let [error (-explain coercer transformed)]
error (explainer transformed)]
(coercion/map->CoercionError (coercion/map->CoercionError
(assoc error :transformed transformed))))) (assoc error :transformed transformed)))))
value)) value))
;; decode -> validate -> encode ;; encode: decode -> validate -> encode
(fn [value format] (fn [value format]
(if-let [coercer (get-coercer format)] (if-let [coercer (get-coercer format)]
(let [decoder (:decoder coercer) (let [transformed (-decode coercer value)]
validator (:validator coercer) (if (-validate coercer transformed)
transformed (decoder value)]
(if (validator transformed)
(encode transformed format) (encode transformed format)
(let [explainer (:explainer coercer) (let [error (-explain coercer transformed)]
error (explainer transformed)]
(coercion/map->CoercionError (coercion/map->CoercionError
(assoc error :transformed transformed))))) (assoc error :transformed transformed)))))
value))))))) value)))))))