My agentic slop goes here. Not intended for anyone else!
1(** JMAP JSON Parser Utilities
2
3 This module provides helper functions for parsing JMAP objects using jsonm/ezjsonm.
4
5 All parsing functions should reference specific test files for expected JSON format.
6*)
7
8(** Helper functions for working with ezjsonm values *)
9module Helpers = struct
10 (** Expect a JSON object and return field list *)
11 let expect_object = function
12 | `O fields -> fields
13 | _ -> raise (Jmap_error.Parse_error "Expected JSON object")
14
15 (** Expect a JSON array and return element list *)
16 let expect_array = function
17 | `A items -> items
18 | _ -> raise (Jmap_error.Parse_error "Expected JSON array")
19
20 (** Expect a JSON string *)
21 let expect_string = function
22 | `String s -> s
23 | _ -> raise (Jmap_error.Parse_error "Expected JSON string")
24
25 (** Expect a JSON integer *)
26 let expect_int = function
27 | `Float f -> int_of_float f
28 | _ -> raise (Jmap_error.Parse_error "Expected JSON number")
29
30 (** Expect a JSON boolean *)
31 let expect_bool = function
32 | `Bool b -> b
33 | _ -> raise (Jmap_error.Parse_error "Expected JSON boolean")
34
35 (** Find optional field in object *)
36 let find_field name fields =
37 List.assoc_opt name fields
38
39 (** Require field to be present *)
40 let require_field name fields =
41 match find_field name fields with
42 | Some v -> v
43 | None -> raise (Jmap_error.Parse_error (Printf.sprintf "Missing required field: %s" name))
44
45 (** Get optional string field *)
46 let get_string_opt name fields =
47 match find_field name fields with
48 | Some (`String s) -> Some s
49 | Some _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a string" name))
50 | None -> None
51
52 (** Get required string field *)
53 let get_string name fields =
54 match require_field name fields with
55 | `String s -> s
56 | _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a string" name))
57
58 (** Get optional boolean field with default *)
59 let get_bool_opt name fields default =
60 match find_field name fields with
61 | Some (`Bool b) -> b
62 | Some _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a boolean" name))
63 | None -> default
64
65 (** Get required boolean field *)
66 let get_bool name fields =
67 match require_field name fields with
68 | `Bool b -> b
69 | _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a boolean" name))
70
71 (** Get optional int field *)
72 let get_int_opt name fields =
73 match find_field name fields with
74 | Some (`Float f) -> Some (int_of_float f)
75 | Some _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a number" name))
76 | None -> None
77
78 (** Get required int field *)
79 let get_int name fields =
80 match require_field name fields with
81 | `Float f -> int_of_float f
82 | _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a number" name))
83
84 (** Parse a map with string keys *)
85 let parse_map parse_value = function
86 | `O fields ->
87 List.map (fun (k, v) -> (k, parse_value v)) fields
88 | _ -> raise (Jmap_error.Parse_error "Expected JSON object for map")
89
90 (** Parse an array *)
91 let parse_array parse_elem = function
92 | `A items -> List.map parse_elem items
93 | `Null -> []
94 | _ -> raise (Jmap_error.Parse_error "Expected JSON array")
95
96 (** Parse optional array (null or array) *)
97 let parse_array_opt parse_elem = function
98 | `Null -> None
99 | `A items -> Some (List.map parse_elem items)
100 | _ -> raise (Jmap_error.Parse_error "Expected JSON array or null")
101end
102
103(** TODO: Implement specific parsers for each JMAP type.
104 Each parser should reference its corresponding test file. *)
105
106(** Parse JMAP Request
107 Test files: test/data/core/request_*.json *)
108let parse_request json =
109 Jmap_request.Parser.of_json json
110
111(** Parse JMAP Response
112 Test files: test/data/core/response_*.json *)
113let parse_response json =
114 Jmap_response.Parser.of_json json
115
116(** Parse JMAP Session
117 Test files: test/data/core/session.json *)
118let parse_session json =
119 Jmap_session.Parser.of_json json