Skip to content

Commit

Permalink
Merge pull request #243 from metosin/int
Browse files Browse the repository at this point in the history
Int
  • Loading branch information
ikitommi committed Aug 17, 2020
2 parents 3246df2 + 7d335e9 commit e5b2177
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 13 deletions.
33 changes: 20 additions & 13 deletions src/malli/core.cljc
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
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
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
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
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
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
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

0 comments on commit e5b2177

Please sign in to comment.