Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Int #243

Merged
merged 2 commits into from
Aug 17, 2020
Merged

Int #243

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 20 additions & 13 deletions src/malli/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -769,27 +769,30 @@
(-get [this key default] (-get-entries this key default))
(-set [this key value] (-set-entries this key value)))))))

(defn -string-schema []
(defn -min-max-pred [f]
(fn [{:keys [min max]}]
(cond
(not (or min max)) nil
(and min max) (fn [x] (let [size (f x)] (<= min size max)))
min (fn [x] (<= min (f x)))
max (fn [x] (<= (f x) max)))))

(defn -simple-schema [{:keys [type pred property-pred]}]
^{:type ::into-schema}
(reify IntoSchema
(-into-schema [_ {:keys [min max] :as properties} children options]
(-check-children! :string properties children {:min 0, :max 0})
(let [count-validator (cond
(not (or min max)) nil
(and min max) (fn [x] (let [size (count x)] (<= min size max)))
min (fn [x] (<= min (count x)))
max (fn [x] (<= (count x) max)))
validator (if count-validator (fn [x] (and (string? x) (count-validator x))) string?)
form (-create-form :string properties children)]
(-into-schema [_ properties children options]
(-check-children! type properties children {:min 0, :max 0})
(let [pvalidator (if property-pred (property-pred properties))
validator (if pvalidator (fn [x] (and (pred x) (pvalidator x))) pred)
form (-create-form type properties children)]
^{:type ::schema}
(reify
Schema
(-type [_] :string)
(-type [_] type)
(-validator [_] validator)
(-explainer [this path]
(fn explain [x in acc]
(if (or (not (string? x)) (and count-validator (not (count-validator x))))
(conj acc (-error path in this x)) acc)))
(if-not (validator x) (conj acc (-error path in this x)) acc)))
(-transformer [this transformer method options]
(-value-transformer transformer this method options))
(-walk [this walker path options]
Expand All @@ -804,6 +807,9 @@
(-get [_ _ default] default)
(-set [this key _] (-fail! ::non-associative-schema {:schema this, :key key})))))))

(defn -string-schema [] (-simple-schema {:type :string, :pred string?, :property-pred (-min-max-pred count)}))
(defn -int-schema [] (-simple-schema {:type :int, :pred int?, :property-pred (-min-max-pred identity)}))

(defn- -ref-schema []
^{:type ::into-schema}
(reify IntoSchema
Expand Down Expand Up @@ -1141,6 +1147,7 @@
:re (-re-schema false)
:fn (-fn-schema)
:string (-string-schema)
:int (-int-schema)
:ref (-ref-schema)
:schema (-schema-schema nil)
::schema (-schema-schema {:raw true})})
Expand Down
8 changes: 8 additions & 0 deletions src/malli/error.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@
(first (m/children schema))
(str "either " (->> (m/children schema) butlast (str/join ", "))
" or " (last (m/children schema))))))}}
:int {:error/fn {:en (fn [{:keys [schema value]} _]
(let [{:keys [min max]} (m/properties schema)]
(cond
(not (int? value)) "should be an integer"
(and min (= min max)) (str "should be " min)
(and min max) (str "should be between " min " and " max)
min (str "should be at least " min)
max (str "should be at most " max))))}}
:string {:error/fn {:en (fn [{:keys [schema value]} _]
(let [{:keys [min max]} (m/properties schema)]
(cond
Expand Down
1 change: 1 addition & 0 deletions src/malli/generator.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
(defmethod -schema-generator :tuple [schema options] (apply gen/tuple (mapv #(generator % options) (m/children schema options))))
#?(:clj (defmethod -schema-generator :re [schema options] (-re-gen schema options)))
(defmethod -schema-generator :string [schema options] (-string-gen schema options))
(defmethod -schema-generator :int [schema options] (gen/large-integer* (-min-max schema options)))
(defmethod -schema-generator :ref [schema options] (generator (m/-deref schema) options))
(defmethod -schema-generator :schema [schema options] (generator (m/-deref schema) options))
(defmethod -schema-generator ::m/schema [schema options] (generator (m/-deref schema) options))
Expand Down
2 changes: 2 additions & 0 deletions src/malli/transform.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@
'nat-int? -string->long
'zero? -string->long

:int -string->long

:> -string->long
:>= -string->long
:< -string->long
Expand Down
33 changes: 33 additions & 0 deletions test/malli/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,39 @@

(is (= [:string {:min 1, :max 4}] (m/form schema)))))

(testing "int schemas"
(let [schema (m/schema [:int {:min 1, :max 4}])]

(is (true? (m/validate schema 1)))
(is (true? (m/validate schema 4)))
(is (false? (m/validate schema nil)))
(is (false? (m/validate schema "invalid")))
(is (false? (m/validate schema 5)))

(is (nil? (m/explain schema 1)))
(is (results= {:schema [:int {:min 1, :max 4}]
:value false
:errors [{:path [], :in [], :schema [:int {:min 1, :max 4}], :value false}]}
(m/explain schema false)))
(is (results= {:schema [:int {:min 1, :max 4}]
:value 5
:errors [{:path [], :in [], :schema [:int {:min 1, :max 4}], :value 5}]}
(m/explain schema 5)))

(is (= 1 (m/decode schema "1" mt/string-transformer)))
(is (= "1" (m/decode schema "1" mt/json-transformer)))

(is (= 3 (m/decode
[:int {:decode/string {:enter inc, :leave inc}}]
1 mt/string-transformer)))

(is (true? (m/validate (over-the-wire schema) 3)))

(is (= {:type :int, :properties {:min 1, :max 4}}
(mu/to-map-syntax schema)))

(is (= [:int {:min 1, :max 4}] (m/form schema)))))

(testing "ref schemas"

(testing "invalid refs fail"
Expand Down
23 changes: 23 additions & 0 deletions test/malli/error_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,29 @@
:f "invalid"})
(me/humanize)))))

(deftest int-test
(is (= {:a ["should be an integer"]
:b ["should be at least 1"]
:c ["should be at most 4"]
:d ["should be between 1 and 4"]
:e ["should be an integer"]
:f ["should be 4"]}
(-> [:map
[:a :int]
[:b [:int {:min 1}]]
[:c [:int {:max 4}]]
[:d [:int {:min 1, :max 4}]]
[:e [:int {:min 1, :max 4}]]
[:f [:int {:min 4, :max 4}]]]
(m/explain
{:a "123"
:b 0
:c 5
:d 0
:e "123"
:f 5})
(me/humanize)))))

(deftest re-test
(testing "success"
(is (= nil
Expand Down
4 changes: 4 additions & 0 deletions test/malli/generator_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
(let [schema [:string {:min 1, :max 4}]]
(is (every? (partial m/validate schema) (mg/sample schema {:size 1000})))))

(testing "int"
(let [schema [:int {:min 1, :max 4}]]
(is (every? (partial m/validate schema) (mg/sample schema {:size 1000})))))

(testing "ref"
(testing "recursion"
(let [schema [:schema {:registry {::cons [:maybe [:tuple int? [:ref ::cons]]]}}
Expand Down