haste_fhir_serialization_json/
serialize_primitives.rs

1use std::io::{BufWriter, Write};
2
3use crate::{SerializeError, traits::FHIRJSONSerializer};
4
5impl FHIRJSONSerializer for i64 {
6    fn serialize_value(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
7        writer.write_all(self.to_string().as_bytes())?;
8
9        Ok(true)
10    }
11
12    fn serialize_extension(
13        &self,
14        _writer: &mut dyn std::io::Write,
15    ) -> Result<bool, SerializeError> {
16        Ok(false)
17    }
18
19    fn serialize_field(
20        &self,
21        field: &str,
22        writer: &mut dyn std::io::Write,
23    ) -> Result<bool, SerializeError> {
24        writer.write_all("\"".as_bytes())?;
25        writer.write_all(field.as_bytes())?;
26        writer.write_all("\":".as_bytes())?;
27        self.serialize_value(writer)?;
28
29        Ok(true)
30    }
31
32    fn is_fp_primitive(&self) -> bool {
33        false
34    }
35}
36
37impl FHIRJSONSerializer for u64 {
38    fn serialize_value(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
39        writer.write_all(self.to_string().as_bytes())?;
40
41        Ok(true)
42    }
43
44    fn serialize_extension(
45        &self,
46        _writer: &mut dyn std::io::Write,
47    ) -> Result<bool, SerializeError> {
48        Ok(false)
49    }
50
51    fn serialize_field(
52        &self,
53        field: &str,
54        writer: &mut dyn std::io::Write,
55    ) -> Result<bool, SerializeError> {
56        writer.write_all("\"".as_bytes())?;
57        writer.write_all(field.as_bytes())?;
58        writer.write_all("\":".as_bytes())?;
59        self.serialize_value(writer)?;
60
61        Ok(true)
62    }
63
64    fn is_fp_primitive(&self) -> bool {
65        false
66    }
67}
68
69impl FHIRJSONSerializer for f64 {
70    fn serialize_value(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
71        writer.write_all(self.to_string().as_bytes())?;
72
73        Ok(true)
74    }
75
76    fn serialize_extension(
77        &self,
78        _writer: &mut dyn std::io::Write,
79    ) -> Result<bool, SerializeError> {
80        Ok(false)
81    }
82
83    fn serialize_field(
84        &self,
85        field: &str,
86        writer: &mut dyn std::io::Write,
87    ) -> Result<bool, SerializeError> {
88        writer.write_all("\"".as_bytes())?;
89        writer.write_all(field.as_bytes())?;
90        writer.write_all("\":".as_bytes())?;
91        self.serialize_value(writer)?;
92
93        Ok(true)
94    }
95
96    fn is_fp_primitive(&self) -> bool {
97        false
98    }
99}
100
101impl FHIRJSONSerializer for bool {
102    fn serialize_value(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
103        writer.write_all(self.to_string().as_bytes())?;
104
105        Ok(true)
106    }
107
108    fn serialize_extension(
109        &self,
110        _writer: &mut dyn std::io::Write,
111    ) -> Result<bool, SerializeError> {
112        Ok(false)
113    }
114
115    fn serialize_field(
116        &self,
117        field: &str,
118        writer: &mut dyn std::io::Write,
119    ) -> Result<bool, SerializeError> {
120        writer.write_all("\"".as_bytes())?;
121        writer.write_all(field.as_bytes())?;
122        writer.write_all("\":".as_bytes())?;
123        self.serialize_value(writer)?;
124
125        Ok(true)
126    }
127
128    fn is_fp_primitive(&self) -> bool {
129        false
130    }
131}
132
133// https://datatracker.ietf.org/doc/html/rfc7159#section-7
134// char = unescaped /
135//           escape (
136//               %x22 /          ; "    quotation mark  U+0022
137//               %x5C /          ; \    reverse solidus U+005C
138//               %x2F /          ; /    solidus         U+002F
139
140//               %x62 /          ; b    backspace       U+0008
141//               %x66 /          ; f    form feed       U+000C
142//               %x6E /          ; n    line feed       U+000A
143//               %x72 /          ; r    carriage return U+000D
144//               %x74 /          ; t    tab             U+0009
145//               %x75 4HEXDIG )  ; uXXXX                U+XXXX
146impl FHIRJSONSerializer for String {
147    fn serialize_value(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
148        writer.write_all(&[b'"'])?;
149        for c in self.chars() {
150            match c {
151                // '\u{002F}' => {
152                //     writer.write_all(&[b'\x5c', b'\x2f'])?;
153                // }
154
155                // backslash
156                '\u{005C}' => {
157                    writer.write_all(&[b'\x5c', b'\x5c'])?;
158                }
159                '\u{0022}' => {
160                    writer.write_all(&[b'\x5c', c as u8])?;
161                }
162                // Backspace
163                '\u{0008}' => {
164                    writer.write_all(&[b'\x5c', b'\x62'])?;
165                }
166                // Form feed
167                '\u{000C}' => {
168                    writer.write_all(&[b'\x5c', b'\x66'])?;
169                }
170                // Line Feed
171                '\u{000A}' => {
172                    writer.write_all(&[b'\x5c', b'\x6e'])?;
173                }
174                // Carriage return
175                '\u{000D}' => {
176                    writer.write_all(&[b'\x5c', b'\x72'])?;
177                }
178
179                // Tab
180                '\u{0009}' => {
181                    writer.write_all(&[b'\x5c', b'\x74'])?;
182                }
183
184                ch => {
185                    let mut buf = [0; 4];
186                    writer.write_all(ch.encode_utf8(&mut buf).as_bytes())?;
187                }
188            }
189        }
190
191        writer.write_all(&[b'"'])?;
192
193        Ok(true)
194    }
195
196    fn serialize_extension(
197        &self,
198        _writer: &mut dyn std::io::Write,
199    ) -> Result<bool, SerializeError> {
200        Ok(false)
201    }
202
203    fn serialize_field(
204        &self,
205        field: &str,
206        writer: &mut dyn std::io::Write,
207    ) -> Result<bool, SerializeError> {
208        writer.write_all(&[b'"'])?;
209        writer.write_all(field.as_bytes())?;
210        writer.write_all(&[b'"', b':'])?;
211        self.serialize_value(writer)?;
212        Ok(true)
213    }
214
215    fn is_fp_primitive(&self) -> bool {
216        false
217    }
218}
219
220impl<T> FHIRJSONSerializer for Vec<T>
221where
222    T: FHIRJSONSerializer,
223{
224    fn serialize_value(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
225        if self.is_empty() {
226            return Ok(false);
227        }
228
229        let mut total = 0;
230
231        let mut tmp_buffer = BufWriter::new(Vec::new());
232        tmp_buffer.write_all(&[b'['])?;
233
234        for i in 0..(self.len() - 1) {
235            let v = &self[i];
236            if v.serialize_value(&mut tmp_buffer)? {
237                total += 1;
238            } else {
239                tmp_buffer.write_all("null".as_bytes())?;
240            }
241            tmp_buffer.write_all(&[b','])?;
242        }
243
244        // Last one don't want trailing comma.
245        if self[self.len() - 1].serialize_value(&mut tmp_buffer)? {
246            total += 1;
247        }
248
249        tmp_buffer.write_all(&[b']'])?;
250        if total > 0 {
251            tmp_buffer.flush()?;
252            writer.write_all(&tmp_buffer.into_inner()?)?;
253            Ok(true)
254        } else {
255            Ok(false)
256        }
257    }
258
259    fn serialize_extension(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
260        if self.is_empty() {
261            return Ok(false);
262        }
263
264        if self[0].is_fp_primitive() {
265            let mut total = 0;
266
267            let mut tmp_buffer = BufWriter::new(Vec::new());
268            tmp_buffer.write_all(&[b'['])?;
269
270            for i in 0..(self.len() - 1) {
271                let v = &self[i];
272                if v.serialize_extension(&mut tmp_buffer)? {
273                    total += 1;
274                    tmp_buffer.write_all(&[b','])?;
275                } else {
276                    tmp_buffer.write_all("null".as_bytes())?;
277                }
278            }
279
280            // Last one don't want trailing comma.
281            if self[self.len() - 1].serialize_extension(&mut tmp_buffer)? {
282                total += 1;
283            }
284
285            tmp_buffer.write_all(&[b']'])?;
286
287            if total > 0 {
288                tmp_buffer.flush()?;
289                writer.write_all(&tmp_buffer.into_inner()?)?;
290                Ok(true)
291            } else {
292                Ok(false)
293            }
294        } else {
295            Ok(false)
296        }
297    }
298
299    fn serialize_field(
300        &self,
301        field: &str,
302        writer: &mut dyn std::io::Write,
303    ) -> Result<bool, SerializeError> {
304        let mut extension_buffer = BufWriter::new(Vec::new());
305        let mut value_buffer = BufWriter::new(Vec::new());
306
307        let should_serialize_extension = self.serialize_extension(&mut extension_buffer)?;
308        let shoud_serialize_value = self.serialize_value(&mut value_buffer)?;
309
310        value_buffer.flush()?;
311        let value_u8 = value_buffer.into_inner()?;
312
313        extension_buffer.flush()?;
314        let extension_u8 = extension_buffer.into_inner()?;
315
316        if should_serialize_extension {
317            writer.write_all(&[b'"', b'_'])?;
318            writer.write_all(field.as_bytes())?;
319            writer.write_all(&[b'"', b':'])?;
320            writer.write_all(&extension_u8)?;
321            // If value not empty put trailing comma after extension value.
322            if shoud_serialize_value {
323                writer.write_all(&[b','])?;
324            }
325        }
326
327        if shoud_serialize_value {
328            writer.write_all(&[b'"'])?;
329            writer.write_all(field.as_bytes())?;
330            writer.write_all(&[b'"', b':'])?;
331            writer.write_all(&value_u8)?;
332        }
333
334        Ok(shoud_serialize_value || should_serialize_extension)
335    }
336
337    fn is_fp_primitive(&self) -> bool {
338        false
339    }
340}
341
342impl<T> FHIRJSONSerializer for Option<T>
343where
344    T: FHIRJSONSerializer,
345{
346    fn serialize_value(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
347        match self {
348            Some(v) => v.serialize_value(writer),
349            None => Ok(false),
350        }
351    }
352
353    fn serialize_extension(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
354        match self {
355            Some(v) => v.serialize_extension(writer),
356            None => Ok(false),
357        }
358    }
359
360    fn serialize_field(
361        &self,
362        field: &str,
363        writer: &mut dyn std::io::Write,
364    ) -> Result<bool, SerializeError> {
365        match self {
366            Some(v) => v.serialize_field(field, writer),
367            None => Ok(false),
368        }
369    }
370
371    fn is_fp_primitive(&self) -> bool {
372        match self {
373            Some(v) => v.is_fp_primitive(),
374            None => false,
375        }
376    }
377}
378
379impl<T> FHIRJSONSerializer for Box<T>
380where
381    T: FHIRJSONSerializer,
382{
383    fn serialize_value(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
384        self.as_ref().serialize_value(writer)
385    }
386
387    fn serialize_extension(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
388        self.as_ref().serialize_extension(writer)
389    }
390
391    fn serialize_field(
392        &self,
393        field: &str,
394        writer: &mut dyn std::io::Write,
395    ) -> Result<bool, SerializeError> {
396        self.as_ref().serialize_field(field, writer)
397    }
398
399    fn is_fp_primitive(&self) -> bool {
400        self.as_ref().is_fp_primitive()
401    }
402}