package serde_derive
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha256=0766b13f1e9421f98fab8efc5d43657229f3b3bc13ca4722086da634fe076ca4
sha512=1023dcd53c4b69032f466b338e2f0146ee3443b2ec4ce8db2d1f226e1409d81a3da3767ac73e9e047fd61b904a829ff841c26317c8ea050351ba6f70ab4158c4
doc/serde_derive/Serde_derive/De/Record_deserializer/index.html
Module De.Record_deserializerSource
Deserializes records in different ways.
val deserialize_with_unordered_fields :
ctxt:Ppxlib.Expansion_context.Deriver.t ->
Attributes.type_attributes ->
Ppxlib.label_declaration list ->
(Ppxlib__.Import.expression -> Ppxlib_ast.Ast.expression) ->
Ppxlib_ast.Ast.expressionGenerates the implementation of a deserializer for a given record type (or list of label declarations).
The outline of the generated code is:
* create a field_visitor that maps strings and ints to an ad-hoc field polyvar (field name "hello" matches `hello)
* declare field value holders (one 'a option ref per field)
* create a recursive function for consuimng fields one by one, using the visitor to validate them, and directing the deserialization to the right field deserializer
* extract the field value holders and validate that all fields are present
* construct the final result
So for a record like:
ocaml[
type person = { name: string; age: int
The generated code would look like:
ocaml[
let deserialize_person = De.(deserializer @@ fun ctx ->
record ctx "person" 2 @@ fun ctx ->
let field_visitor = Visitor.make
~visit_string:(fun _ctx str ->
match str with
| "name" -> Ok `name
| "age" -> Ok `age
| _ -> Error `invalid_field_type)
~visit_int:(fun _ctx int ->
match int with
| 0 -> Ok `name
| 1 -> Ok `age
| _ -> Error `invalid_field_type)
()
in
let name = ref None in
let age = ref None in
let rec read_fields () =
let* tag = next_field ctx field_visitor in
match tag with
| Some `name ->
let* v = field ctx "name" string in
name := Some v;
read_fields ()
| Some `age ->
let* v = field ctx "age" int in
age := Some v;
read_fields ()
| None ->
Ok ()
in
let* () = read_fields () in
let* name = Option.to_result ~none:(`Msg "missing field 'name'") name in
let* age = Option.to_result ~none:(`Msg "missing field 'age'") age in
Ok {name;age )