(** JMAP JSON Parser Utilities This module provides helper functions for parsing JMAP objects using jsonm/ezjsonm. All parsing functions should reference specific test files for expected JSON format. *) (** Helper functions for working with ezjsonm values *) module Helpers = struct (** Expect a JSON object and return field list *) let expect_object = function | `O fields -> fields | _ -> raise (Jmap_error.Parse_error "Expected JSON object") (** Expect a JSON array and return element list *) let expect_array = function | `A items -> items | _ -> raise (Jmap_error.Parse_error "Expected JSON array") (** Expect a JSON string *) let expect_string = function | `String s -> s | _ -> raise (Jmap_error.Parse_error "Expected JSON string") (** Expect a JSON integer *) let expect_int = function | `Float f -> int_of_float f | _ -> raise (Jmap_error.Parse_error "Expected JSON number") (** Expect a JSON boolean *) let expect_bool = function | `Bool b -> b | _ -> raise (Jmap_error.Parse_error "Expected JSON boolean") (** Find optional field in object *) let find_field name fields = List.assoc_opt name fields (** Require field to be present *) let require_field name fields = match find_field name fields with | Some v -> v | None -> raise (Jmap_error.Parse_error (Printf.sprintf "Missing required field: %s" name)) (** Get optional string field *) let get_string_opt name fields = match find_field name fields with | Some (`String s) -> Some s | Some _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a string" name)) | None -> None (** Get required string field *) let get_string name fields = match require_field name fields with | `String s -> s | _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a string" name)) (** Get optional boolean field with default *) let get_bool_opt name fields default = match find_field name fields with | Some (`Bool b) -> b | Some _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a boolean" name)) | None -> default (** Get required boolean field *) let get_bool name fields = match require_field name fields with | `Bool b -> b | _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a boolean" name)) (** Get optional int field *) let get_int_opt name fields = match find_field name fields with | Some (`Float f) -> Some (int_of_float f) | Some _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a number" name)) | None -> None (** Get required int field *) let get_int name fields = match require_field name fields with | `Float f -> int_of_float f | _ -> raise (Jmap_error.Parse_error (Printf.sprintf "Field %s must be a number" name)) (** Parse a map with string keys *) let parse_map parse_value = function | `O fields -> List.map (fun (k, v) -> (k, parse_value v)) fields | _ -> raise (Jmap_error.Parse_error "Expected JSON object for map") (** Parse an array *) let parse_array parse_elem = function | `A items -> List.map parse_elem items | `Null -> [] | _ -> raise (Jmap_error.Parse_error "Expected JSON array") (** Parse optional array (null or array) *) let parse_array_opt parse_elem = function | `Null -> None | `A items -> Some (List.map parse_elem items) | _ -> raise (Jmap_error.Parse_error "Expected JSON array or null") end (** TODO: Implement specific parsers for each JMAP type. Each parser should reference its corresponding test file. *) (** Parse JMAP Request Test files: test/data/core/request_*.json *) let parse_request json = Jmap_request.Parser.of_json json (** Parse JMAP Response Test files: test/data/core/response_*.json *) let parse_response json = Jmap_response.Parser.of_json json (** Parse JMAP Session Test files: test/data/core/session.json *) let parse_session json = Jmap_session.Parser.of_json json