(every-impl form pred opts)
(every-impl form pred {conform-into :into, describe-form :clojure.spec.alpha/describe, :keys [kind :clojure.spec.alpha/kind-form count max-count min-count distinct gen-max :clojure.spec.alpha/kfn :clojure.spec.alpha/cpred conform-keys :clojure.spec.alpha/conform-all], :or {gen-max 20}, :as opts} gfn)
Do not call this directly, use 'every', 'every-kv', 'coll-of' or 'map-of'
Source
(defn ^:skip-wiki every-impl
"Do not call this directly, use 'every', 'every-kv', 'coll-of' or 'map-of'"
([form pred opts] (every-impl form pred opts nil))
([form pred {conform-into :into
describe-form ::describe
:keys [kind ::kind-form count max-count min-count distinct gen-max ::kfn ::cpred
conform-keys ::conform-all]
:or {gen-max 20}
:as opts}
gfn]
(let [gen-into (if conform-into (empty conform-into) (get empty-coll kind-form))
spec (delay (specize pred))
check? #(valid? @spec %)
kfn (c/or kfn (fn [i v] i))
addcv (fn [ret i v cv] (conj ret cv))
cfns (fn [x]
;;returns a tuple of [init add complete] fns
(cond
(c/and (vector? x) (c/or (not conform-into) (vector? conform-into)))
[identity
(fn [ret i v cv]
(if (identical? v cv)
ret
(assoc ret i cv)))
identity]
(c/and (map? x) (c/or (c/and kind (not conform-into)) (map? conform-into)))
[(if conform-keys empty identity)
(fn [ret i v cv]
(if (c/and (identical? v cv) (not conform-keys))
ret
(assoc ret (nth (if conform-keys cv v) 0) (nth cv 1))))
identity]
(c/or (list? conform-into) (seq? conform-into) (c/and (not conform-into) (c/or (list? x) (seq? x))))
[(constantly ()) addcv reverse]
:else [#(empty (c/or conform-into %)) addcv identity]))]
(reify
Specize
(specize* [s] s)
(specize* [s _] s)
Spec
(conform* [_ x]
(let [spec @spec]
(cond
(not (cpred x)) ::invalid
conform-all
(let [[init add complete] (cfns x)]
(loop [ret (init x), i 0, [v & vs :as vseq] (seq x)]
(if vseq
(let [cv (conform* spec v)]
(if (invalid? cv)
::invalid
(recur (add ret i v cv) (inc i) vs)))
(complete ret))))
:else
(if (indexed? x)
(let [step (max 1 (long (/ (c/count x) *coll-check-limit*)))]
(loop [i 0]
(if (>= i (c/count x))
x
(if (valid? spec (nth x i))
(recur (c/+ i step))
::invalid))))
(let [limit *coll-check-limit*]
(loop [i 0 [v & vs :as vseq] (seq x)]
(cond
(c/or (nil? vseq) (= i limit)) x
(valid? spec v) (recur (inc i) vs)
:else ::invalid)))))))
(unform* [_ x]
(if conform-all
(let [spec @spec
[init add complete] (cfns x)]
(loop [ret (init x), i 0, [v & vs :as vseq] (seq x)]
(if (>= i (c/count x))
(complete ret)
(recur (add ret i v (unform* spec v)) (inc i) vs))))
x))
(explain* [_ path via in x]
(c/or (coll-prob x kind kind-form distinct count min-count max-count
path via in)
(apply concat
((if conform-all identity (partial take *coll-error-limit*))
(keep identity
(map (fn [i v]
(let [k (kfn i v)]
(when-not (check? v)
(let [prob (explain-1 form pred path via (conj in k) v)]
prob))))
(range) x))))))
(gen* [_ overrides path rmap]
(if gfn
(gfn)
(let [pgen (gensub pred overrides path rmap form)]
(gen/bind
(cond
gen-into (gen/return gen-into)
kind (gen/fmap #(if (empty? %) % (empty %))
(gensub kind overrides path rmap form))
:else (gen/return []))
(fn [init]
(gen/fmap
#(if (vector? init) % (into init %))
(cond
distinct
(if count
(gen/vector-distinct pgen {:num-elements count :max-tries 100})
(gen/vector-distinct pgen {:min-elements (c/or min-count 0)
:max-elements (c/or max-count (max gen-max (c/* 2 (c/or min-count 0))))
:max-tries 100}))
count
(gen/vector pgen count)
(c/or min-count max-count)
(gen/vector pgen (c/or min-count 0) (c/or max-count (max gen-max (c/* 2 (c/or min-count 0)))))
:else
(gen/vector pgen 0 gen-max))))))))
(with-gen* [_ gfn] (every-impl form pred opts gfn))
(describe* [_] (c/or describe-form `(every ~(res form) ~@(mapcat identity opts))))))))