Skip to content

Commit

Permalink
feat: begin attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
leostera committed Feb 19, 2024
1 parent 9b5c570 commit f3a5a55
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 6 deletions.
35 changes: 35 additions & 0 deletions derive/attributes.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
type type_attributes = {
rename : string;
mode :
[ `tag of string
| `tag_and_content of string * string
| `untagged
| `normal ];
rename_all :
[ `lowercase
| `UPPERCASE
| `camelCase
| `PascalCase
| `snake_case
| `SCREAMING_SNAKE_CASE
| `kebab_case
| `SCREAMING_KEBAB_CASE ]
option;
error_on_unknown_fields : bool;
}

type variant_attributes = {
rename : string;
should_skip : [ `skip_serializing | `skip_deserializing | `always | `never ];
is_catch_all : bool;
}

type field_attributes = {
rename : string;
default : string option;
should_skip :
[ `skip_serializing_if of string
| `skip_deserializing_if of string
| `always
| `never ];
}
25 changes: 19 additions & 6 deletions derive/de.ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ let is_primitive = function
true
| _ -> false

(** [deserializer_for_type] creates a call to a deserializer based on a type.
When type is a constructor (or [Ptyp_constr], which is OCaml for "any type name"),
we will look at the number of arguments it has and
*)
let rec deserializer_for_type ~ctxt (core_type : Parsetree.core_type) =
let loc = loc ~ctxt in
match core_type.ptyp_desc with
Expand Down Expand Up @@ -330,7 +336,7 @@ module Record_deserializer = struct
@@ record_expr
end

let gen_serialize_variant_impl ~ctxt ptype_name cstr_declarations =
let gen_deserialize_variant_impl ~ctxt ptype_name cstr_declarations =
let loc = loc ~ctxt in
let type_name = Ast.estring ~loc ptype_name.txt in
let constructor_names =
Expand Down Expand Up @@ -470,7 +476,11 @@ let gen_serialize_variant_impl ~ctxt ptype_name cstr_declarations =
let* tag = identifier ctx field_visitor in
[%e tag_dispatch]]

let gen_serialize_record_impl ~ctxt ptype_name label_declarations =
(** Generate the deserializer function for a record type.
See [Record_deserializer] above for more info.
*)
let gen_deserialize_record_impl ~ctxt ptype_name label_declarations =
let loc = loc ~ctxt in
let type_name = Ast.estring ~loc ptype_name.txt in
let field_count = Ast.eint ~loc (List.length label_declarations) in
Expand All @@ -483,17 +493,20 @@ let gen_serialize_record_impl ~ctxt ptype_name label_declarations =

[%expr record ctx [%e type_name] [%e field_count] (fun ctx -> [%e body])]

let gen_serialize_impl ~ctxt type_decl =
(** Generates a deserializer implementation dispatching based on the kind of
type that the [@@deriving] attribute was set on.
*)
let gen_deserialize_impl ~ctxt type_decl =
let loc = loc ~ctxt in

let typename = type_decl.ptype_name.txt in

let body =
match type_decl with
| { ptype_kind = Ptype_record label_declarations; ptype_name; _ } ->
gen_serialize_record_impl ~ctxt ptype_name label_declarations
gen_deserialize_record_impl ~ctxt ptype_name label_declarations
| { ptype_kind = Ptype_variant cstrs_declaration; ptype_name; _ } ->
gen_serialize_variant_impl ~ctxt ptype_name cstrs_declaration
gen_deserialize_variant_impl ~ctxt ptype_name cstrs_declaration
| { ptype_kind; ptype_name; _ } ->
let err =
match ptype_kind with
Expand All @@ -516,7 +529,7 @@ let gen_serialize_impl ~ctxt type_decl =
let generate_impl ~ctxt (_rec_flag, type_declarations) =
let loc = loc ~ctxt in
[ [%stri open! Serde]; [%stri let ( let* ) = Result.bind] ]
@ List.map (gen_serialize_impl ~ctxt) type_declarations
@ List.map (gen_deserialize_impl ~ctxt) type_declarations

let impl_generator = Deriving.Generator.V2.make_noarg generate_impl

Expand Down

0 comments on commit f3a5a55

Please sign in to comment.