Skip to content

Commit 7773d9b

Browse files
committed
Fix #88
1 parent 54ecec1 commit 7773d9b

File tree

5 files changed

+143
-11
lines changed

5 files changed

+143
-11
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- Add `Yocaml.Data.Validation.String`, a set of validator for `String` (by [Okhuomon Ajayi](https://github.com/six-shot))
1818
- Add missing test coverage for `Nel.equal` and `Nel.append` functions (by [Bill Njoroge](https://github.com/Bnjoroge1))
1919
- Add `to_data` and `from_data` for Archetypes (by [gr-im](https://github.com/xvw))
20+
- Add `Yocaml.Data.Validation.Int` and `Float`, a set of validator for `Int` and `Float` (by [gr-im](https://github.com/gr-im))
2021

2122

2223
### v2.6.0 2025-09-23 Nantes (France)

lib/core/data.ml

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,11 +416,9 @@ module Validation = struct
416416
Validators specifically for string values. *)
417417

418418
module String = struct
419-
(* String-specific parameters for generic validators *)
420419
let string_pp = Format.pp_print_string
421420
let string_equal = Stdlib.String.equal
422421

423-
(* Use generic validators with string-specific parameters *)
424422
let equal expected actual =
425423
equal ~pp:string_pp ~equal:string_equal expected actual
426424

@@ -473,7 +471,6 @@ module Validation = struct
473471

474472
let length_eq = has_length
475473

476-
(* String-specific validators that don't have generic equivalents *)
477474
let not_empty actual =
478475
let actual_length = Stdlib.String.length actual in
479476
if Int.compare actual_length 0 > 0 then Ok actual
@@ -542,6 +539,45 @@ module Validation = struct
542539

543540
let where ?message predicate actual =
544541
where ~pp:string_pp ?message predicate actual
542+
543+
let lowercase_ascii = Stdlib.String.lowercase_ascii
544+
let trim = Stdlib.String.trim
545+
end
546+
547+
module Int = struct
548+
let with_pp f = f ?pp:(Some Format.pp_print_int)
549+
let with_equal f = f ?equal:(Some Stdlib.Int.equal)
550+
let with_compare f = f ?compare:(Some Stdlib.Int.compare)
551+
let pp_equal f = with_equal (with_pp f)
552+
let pp_cmp f = with_compare (with_pp f)
553+
let positive = positive
554+
let bounded = bounded
555+
let equal = pp_equal equal
556+
let not_equal = pp_equal not_equal
557+
let gt = pp_cmp gt
558+
let ge = pp_cmp ge
559+
let lt = pp_cmp lt
560+
let le = pp_cmp le
561+
let one_of = pp_equal one_of
562+
let where = with_pp where
563+
end
564+
565+
module Float = struct
566+
let with_pp f = f ?pp:(Some Format.pp_print_float)
567+
let with_equal f = f ?equal:(Some Float.equal)
568+
let with_compare f = f ?compare:(Some Float.compare)
569+
let pp_equal f = with_equal (with_pp f)
570+
let pp_cmp f = with_compare (with_pp f)
571+
let positive = positive'
572+
let bounded = bounded'
573+
let equal = pp_equal equal
574+
let not_equal = pp_equal not_equal
575+
let gt = pp_cmp gt
576+
let ge = pp_cmp ge
577+
let lt = pp_cmp lt
578+
let le = pp_cmp le
579+
let one_of = pp_equal one_of
580+
let where = with_pp where
545581
end
546582

547583
(** {2 Validator combinators} *)

lib/core/data.mli

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,88 @@ module Validation : sig
529529
-> string validated_value
530530
(** [where ?message predicate actual] ensures that [actual] satisfies
531531
[predicate]. [message] is used for custom error messages. *)
532+
533+
(** Useful function to be used with regular string validators. *)
534+
535+
val lowercase_ascii : string -> string
536+
val trim : string -> string
537+
end
538+
539+
(** {2 Int validators}
540+
541+
Validators specifically for int values. *)
542+
543+
module Int : sig
544+
val positive : int -> int validated_value
545+
(** Integer version of {!val:Data.Validation.positive} *)
546+
547+
val bounded : min:int -> max:int -> int -> int validated_value
548+
(** Integer version of {!val:Data.Validation.bounded} *)
549+
550+
val equal : int -> int -> int validated_value
551+
(** Integer version of {!val:Data.Validation.equal} *)
552+
553+
val not_equal : int -> int -> int validated_value
554+
(** Integer version of {!val:Data.Validation.not_equal} *)
555+
556+
val gt : int -> int -> int validated_value
557+
(** Integer version of {!val:Data.Validation.gt} *)
558+
559+
val ge : int -> int -> int validated_value
560+
(** Integer version of {!val:Data.Validation.ge} *)
561+
562+
val lt : int -> int -> int validated_value
563+
(** Integer version of {!val:Data.Validation.lt} *)
564+
565+
val le : int -> int -> int validated_value
566+
(** Integer version of {!val:Data.Validation.le} *)
567+
568+
val one_of : int list -> int -> int validated_value
569+
(** Integer version of {!val:Data.Validation.one_of} *)
570+
571+
val where :
572+
?message:(int -> string) -> (int -> bool) -> int -> int validated_value
573+
(** Integer version of {!val:Data.Validation.where} *)
574+
end
575+
576+
(** {2 Float validators}
577+
578+
Validators specifically for float values. *)
579+
580+
module Float : sig
581+
val positive : float -> float validated_value
582+
(** Float version of {!val:Data.Validation.positive} *)
583+
584+
val bounded : min:float -> max:float -> float -> float validated_value
585+
(** Float version of {!val:Data.Validation.bounded} *)
586+
587+
val equal : float -> float -> float validated_value
588+
(** Float version of {!val:Data.Validation.equal} *)
589+
590+
val not_equal : float -> float -> float validated_value
591+
(** Float version of {!val:Data.Validation.not_equal} *)
592+
593+
val gt : float -> float -> float validated_value
594+
(** Float version of {!val:Data.Validation.gt} *)
595+
596+
val ge : float -> float -> float validated_value
597+
(** Float version of {!val:Data.Validation.ge} *)
598+
599+
val lt : float -> float -> float validated_value
600+
(** Float version of {!val:Data.Validation.lt} *)
601+
602+
val le : float -> float -> float validated_value
603+
(** Float version of {!val:Data.Validation.le} *)
604+
605+
val one_of : float list -> float -> float validated_value
606+
(** Float version of {!val:Data.Validation.one_of} *)
607+
608+
val where :
609+
?message:(float -> string)
610+
-> (float -> bool)
611+
-> float
612+
-> float validated_value
613+
(** Float version of {!val:Data.Validation.where} *)
532614
end
533615

534616
(** {2 Validator combinators} *)

test/lib/testable.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ let rec equal_value_error cst a b =
158158
, Invalid_list { errors = eb; given = gb } ) ->
159159
Yocaml.Nel.equal
160160
(fun (ia, va) (ib, vb) ->
161-
Int.equal ia ib && equal_value_error cst va vb)
161+
Stdlib.Int.equal ia ib && equal_value_error cst va vb)
162162
ea eb
163163
&& List.equal Yocaml.Data.equal ga gb
164164
| ( Invalid_record { errors = ea; given = ga }

test/yocaml/data_test.ml

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,9 @@ let test_equal =
942942
let open Alcotest in
943943
test_case "equal - validate equal" `Quick (fun () ->
944944
let check = check (Testable.validated_value int) "should be equal" in
945-
let v = V.(int & equal ~pp:Format.pp_print_int ~equal:Int.equal 10) in
945+
let v =
946+
V.(int & equal ~pp:Format.pp_print_int ~equal:Stdlib.Int.equal 10)
947+
in
946948
let () = check (Ok 10) (v @@ D.int 10) in
947949
let () =
948950
check
@@ -957,7 +959,9 @@ let test_not_equal =
957959
let open Alcotest in
958960
test_case "not_equal - validate not_equal" `Quick (fun () ->
959961
let check = check (Testable.validated_value int) "should be equal" in
960-
let v = V.(int & not_equal ~pp:Format.pp_print_int ~equal:Int.equal 10) in
962+
let v =
963+
V.(int & not_equal ~pp:Format.pp_print_int ~equal:Stdlib.Int.equal 10)
964+
in
961965
let () = check (Ok 11) (v @@ D.int 11) in
962966
let () =
963967
check
@@ -973,7 +977,9 @@ let test_gt =
973977
let open Alcotest in
974978
test_case "gt - validate gt" `Quick (fun () ->
975979
let check = check (Testable.validated_value int) "should be equal" in
976-
let v = V.(int & gt ~pp:Format.pp_print_int ~compare:Int.compare 10) in
980+
let v =
981+
V.(int & gt ~pp:Format.pp_print_int ~compare:Stdlib.Int.compare 10)
982+
in
977983
let () = check (Ok 11) (v @@ D.int 11) in
978984
let () =
979985
check
@@ -989,7 +995,9 @@ let test_ge =
989995
let open Alcotest in
990996
test_case "ge - validate ge" `Quick (fun () ->
991997
let check = check (Testable.validated_value int) "should be equal" in
992-
let v = V.(int & ge ~pp:Format.pp_print_int ~compare:Int.compare 10) in
998+
let v =
999+
V.(int & ge ~pp:Format.pp_print_int ~compare:Stdlib.Int.compare 10)
1000+
in
9931001
let () = check (Ok 11) (v @@ D.int 11) in
9941002
let () = check (Ok 10) (v @@ D.int 10) in
9951003
let () =
@@ -1006,7 +1014,9 @@ let test_lt =
10061014
let open Alcotest in
10071015
test_case "lt - validate lt" `Quick (fun () ->
10081016
let check = check (Testable.validated_value int) "should be equal" in
1009-
let v = V.(int & lt ~pp:Format.pp_print_int ~compare:Int.compare 10) in
1017+
let v =
1018+
V.(int & lt ~pp:Format.pp_print_int ~compare:Stdlib.Int.compare 10)
1019+
in
10101020
let () = check (Ok 9) (v @@ D.int 9) in
10111021
let () =
10121022
check
@@ -1022,7 +1032,9 @@ let test_le =
10221032
let open Alcotest in
10231033
test_case "le - validate le" `Quick (fun () ->
10241034
let check = check (Testable.validated_value int) "should be equal" in
1025-
let v = V.(int & le ~pp:Format.pp_print_int ~compare:Int.compare 10) in
1035+
let v =
1036+
V.(int & le ~pp:Format.pp_print_int ~compare:Stdlib.Int.compare 10)
1037+
in
10261038
let () = check (Ok 9) (v @@ D.int 9) in
10271039
let () = check (Ok 10) (v @@ D.int 10) in
10281040
let () =
@@ -1066,7 +1078,8 @@ let test_where_or_const =
10661078
/ ((int & where ~pp:Format.pp_print_int (fun x -> x mod 2 = 0))
10671079
$ string_of_int)
10681080
/ ((float
1069-
& where ~pp:Format.pp_print_float (fun x -> Float.floor x >= 3.0))
1081+
& where ~pp:Format.pp_print_float (fun x ->
1082+
Stdlib.Float.floor x >= 3.0))
10701083
& const "a float")
10711084
in
10721085
let () = check (Ok "foo") (v @@ D.string "foo") in

0 commit comments

Comments
 (0)