Skip to main content

haste_fhir_serialization_json_derive/
lib.rs

1mod deserialize;
2mod serde_deserialize;
3mod serde_serialize;
4mod serialize;
5mod utilities;
6
7use proc_macro::TokenStream;
8use syn::{Attribute, DeriveInput, Expr, Lit, Meta, parse_macro_input};
9
10/// Determines the de/serialization type of the derive macro.
11fn get_attribute_serialization_type(attrs: &[Attribute]) -> Option<String> {
12    attrs.iter().find_map(|attr| match &attr.meta {
13        Meta::NameValue(name_value) => {
14            if name_value.path.is_ident("fhir_serialize_type") {
15                match &name_value.value {
16                    Expr::Lit(lit) => match &lit.lit {
17                        Lit::Str(lit) => Some(lit.value()),
18                        _ => panic!("Expected a string literal"),
19                    },
20                    _ => panic!("Expected a string literal"),
21                }
22            } else {
23                None
24            }
25        }
26        _ => None,
27    })
28}
29
30#[proc_macro_derive(
31    FHIRJSONSerialize,
32    attributes(
33        fhir_serialize_type,
34        rename_field,
35        // Used on the enum itself for typechoice.
36        type_choice_field_name,
37         // Used on field itself for variants.
38        type_choice_variants,
39        primitive,
40        code,
41        // For validation on vector min maxes.
42        cardinality,
43        reference
44    )
45)]
46pub fn serialize(input: TokenStream) -> TokenStream {
47    let input = parse_macro_input!(input as DeriveInput);
48
49    let serialize_type = get_attribute_serialization_type(&input.attrs);
50
51    let result = match serialize_type.unwrap().as_str() {
52        "primitive" => serialize::primitve_serialization(input),
53        "typechoice" => serialize::typechoice_serialization(input),
54        "complex" => {
55            serialize::complex_serialization(input, serialize::ComplexSerializeType::Complex)
56        }
57        "resource" => {
58            serialize::complex_serialization(input, serialize::ComplexSerializeType::Resource)
59        }
60        "valueset" => serialize::value_set_serialization(input),
61        "enum-variant" => serialize::enum_variant_serialization(input),
62        // Some("typechoice") => typechoice_serialization(input),
63        _ => panic!("Must be one of primitive, typechoice, complex or resource."),
64    };
65
66    result
67}
68
69#[derive(PartialEq)]
70enum DeserializeComplexType {
71    Complex,
72    Resource,
73}
74
75#[proc_macro_derive(
76    FHIRJSONDeserialize,
77    attributes(
78        fhir_serialize_type,
79        rename_field,
80
81        // Used on the enum itself for typechoice.
82        type_choice_field_name,
83
84        // Used on field itself for variants.
85        type_choice_variants,
86
87        primitive,
88
89        // Used for enum serialization.
90        determine_by,
91
92        // For validation on vector min maxes.
93        cardinality,
94        reference
95    )
96)]
97
98pub fn deserialize(input: TokenStream) -> TokenStream {
99    let input = parse_macro_input!(input as DeriveInput);
100
101    let serialize_type = get_attribute_serialization_type(&input.attrs);
102
103    let result = match serialize_type.unwrap().as_str() {
104        "primitive" => deserialize::fhir_primitive_deserialization(input),
105        "typechoice" => deserialize::deserialize_typechoice(input),
106        "resource" => deserialize::deserialize_complex(input, DeserializeComplexType::Resource),
107        "complex" => deserialize::deserialize_complex(input, DeserializeComplexType::Complex),
108        "enum-variant" => deserialize::enum_variant_deserialization(input),
109        "valueset" => deserialize::deserialize_valueset(input),
110        _ => panic!("Must be one of primitive, typechoice, complex or resource."),
111    };
112
113    result.into()
114}
115
116#[proc_macro_derive(
117    FHIRSerdeDeserialize,
118    attributes(
119        fhir_serialize_type,
120        rename_field,
121
122        // Used on the enum itself for typechoice.
123        type_choice_field_name,
124
125        // Used on field itself for variants.
126        type_choice_variants,
127
128        primitive,
129
130        // Used for enum serialization.
131        determine_by,
132
133        // For validation on vector min maxes.
134        cardinality,
135        reference
136    )
137)]
138pub fn serde_deserialize(input: TokenStream) -> TokenStream {
139    let input = parse_macro_input!(input as DeriveInput);
140
141    let serialize_type = get_attribute_serialization_type(&input.attrs);
142
143    let result = match serialize_type.unwrap().as_str() {
144        "primitive" => serde_deserialize::fhir_primitive_deserialization(input),
145        "valueset" => serde_deserialize::valueset_deserialization(input),
146        "typechoice" => serde_deserialize::typechoice_deserialization(input),
147        "complex" => {
148            serde_deserialize::complex_deserialization(input, DeserializeComplexType::Complex)
149        }
150        "resource" => {
151            serde_deserialize::complex_deserialization(input, DeserializeComplexType::Resource)
152        }
153        _ => panic!("Only primitive and valueset supported for serde deserialization."),
154    };
155
156    result.into()
157}
158
159#[proc_macro_derive(
160    FHIRSerdeSerialize,
161    attributes(
162        fhir_serialize_type,
163        rename_field,
164        // Used on the enum itself for typechoice.
165        type_choice_field_name,
166         // Used on field itself for variants.
167        type_choice_variants,
168        primitive,
169        code,
170        // For validation on vector min maxes.
171        cardinality,
172        reference
173    )
174)]
175pub fn serde_serialize(input: TokenStream) -> TokenStream {
176    let input = parse_macro_input!(input as DeriveInput);
177
178    let serialize_type = get_attribute_serialization_type(&input.attrs);
179
180    let result = match serialize_type.unwrap().as_str() {
181        "primitive" => serde_serialize::fhir_primitive_serialization(input),
182        "valueset" => serde_serialize::valueset_serialization(input),
183        "typechoice" => serde_serialize::typechoice_serialization(input),
184        "complex" => serde_serialize::complex_serialization(input, DeserializeComplexType::Complex),
185        "resource" => {
186            serde_serialize::complex_serialization(input, DeserializeComplexType::Resource)
187        }
188        "enum-variant" => serde_serialize::enum_variant_serialization(input),
189        _ => panic!("Only primitive and valueset supported for serde deserialization."),
190    };
191
192    result.into()
193}