Source file caqti_encoders.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
(** Helper functions for creating Caqti types with custom encoder/decoders. *)
module Data = struct
type _ t =
| [] : unit t
| ( :: ) : ('a * 'b t) -> ('a * 'b) t
let rec make_value : type a. a t -> a =
fun xs ->
match xs with
| [] -> ()
| x :: xs -> x, make_value xs
;;
end
module Schema = struct
type _ t =
| [] : unit t
| ( :: ) : ('a Caqti_type.t * 'b t) -> ('a * 'b) t
let rec make_type : type a. a t -> a Caqti_type.t =
fun xs ->
match xs with
| [] -> failwith "Schema shouldn't be empty"
| x :: [] -> Caqti_type.(t2 x unit)
| x :: xs -> Caqti_type.(t2 x (make_type xs))
;;
end
let custom
: type a b.
encode:(b -> (a Data.t, string) result)
-> decode:(a -> (b, string) result)
-> a Schema.t
-> b Caqti_type.t
=
fun ~encode ~decode schema ->
let typ = Schema.make_type schema in
let encode data = encode data |> Result.map Data.make_value in
Caqti_type.custom ~encode ~decode typ
;;
let custom_ok
: type a b.
encode:(b -> a Data.t) -> decode:(a -> b) -> a Schema.t -> b Caqti_type.t
=
let open CCFun in
fun ~encode ~decode schema ->
let typ = Schema.make_type schema in
let encode = CCResult.(encode %> return %> map Data.make_value) in
Caqti_type.custom ~encode ~decode:(decode %> CCResult.return) typ
;;