Skip to main content

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        } else {
248            tmp_buffer.write_all("null".as_bytes())?;
249        }
250
251        tmp_buffer.write_all(&[b']'])?;
252        if total > 0 {
253            tmp_buffer.flush()?;
254            writer.write_all(&tmp_buffer.into_inner()?)?;
255            Ok(true)
256        } else {
257            Ok(false)
258        }
259    }
260
261    fn serialize_extension(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
262        if self.is_empty() {
263            return Ok(false);
264        }
265
266        if self[0].is_fp_primitive() {
267            let mut total = 0;
268
269            let mut tmp_buffer = BufWriter::new(Vec::new());
270            tmp_buffer.write_all(&[b'['])?;
271
272            for i in 0..(self.len() - 1) {
273                let v = &self[i];
274                if v.serialize_extension(&mut tmp_buffer)? {
275                    total += 1;
276                } else {
277                    tmp_buffer.write_all("null".as_bytes())?;
278                }
279                tmp_buffer.write_all(&[b','])?;
280            }
281
282            // Last one don't want trailing comma.
283            if self[self.len() - 1].serialize_extension(&mut tmp_buffer)? {
284                total += 1;
285            } else {
286                tmp_buffer.write_all("null".as_bytes())?;
287            }
288
289            tmp_buffer.write_all(&[b']'])?;
290
291            if total > 0 {
292                tmp_buffer.flush()?;
293                writer.write_all(&tmp_buffer.into_inner()?)?;
294                Ok(true)
295            } else {
296                Ok(false)
297            }
298        } else {
299            Ok(false)
300        }
301    }
302
303    fn serialize_field(
304        &self,
305        field: &str,
306        writer: &mut dyn std::io::Write,
307    ) -> Result<bool, SerializeError> {
308        let mut extension_buffer = BufWriter::new(Vec::new());
309        let mut value_buffer = BufWriter::new(Vec::new());
310
311        let should_serialize_extension = self.serialize_extension(&mut extension_buffer)?;
312        let shoud_serialize_value = self.serialize_value(&mut value_buffer)?;
313
314        value_buffer.flush()?;
315        let value_u8 = value_buffer.into_inner()?;
316
317        extension_buffer.flush()?;
318        let extension_u8 = extension_buffer.into_inner()?;
319
320        if should_serialize_extension {
321            writer.write_all(&[b'"', b'_'])?;
322            writer.write_all(field.as_bytes())?;
323            writer.write_all(&[b'"', b':'])?;
324            writer.write_all(&extension_u8)?;
325            // If value not empty put trailing comma after extension value.
326            if shoud_serialize_value {
327                writer.write_all(&[b','])?;
328            }
329        }
330
331        if shoud_serialize_value {
332            writer.write_all(&[b'"'])?;
333            writer.write_all(field.as_bytes())?;
334            writer.write_all(&[b'"', b':'])?;
335            writer.write_all(&value_u8)?;
336        }
337
338        Ok(shoud_serialize_value || should_serialize_extension)
339    }
340
341    fn is_fp_primitive(&self) -> bool {
342        false
343    }
344}
345
346impl<T> FHIRJSONSerializer for Option<T>
347where
348    T: FHIRJSONSerializer,
349{
350    fn serialize_value(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
351        match self {
352            Some(v) => v.serialize_value(writer),
353            None => Ok(false),
354        }
355    }
356
357    fn serialize_extension(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
358        match self {
359            Some(v) => v.serialize_extension(writer),
360            None => Ok(false),
361        }
362    }
363
364    fn serialize_field(
365        &self,
366        field: &str,
367        writer: &mut dyn std::io::Write,
368    ) -> Result<bool, SerializeError> {
369        match self {
370            Some(v) => v.serialize_field(field, writer),
371            None => Ok(false),
372        }
373    }
374
375    fn is_fp_primitive(&self) -> bool {
376        match self {
377            Some(v) => v.is_fp_primitive(),
378            None => false,
379        }
380    }
381}
382
383impl<T> FHIRJSONSerializer for Box<T>
384where
385    T: FHIRJSONSerializer,
386{
387    fn serialize_value(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
388        self.as_ref().serialize_value(writer)
389    }
390
391    fn serialize_extension(&self, writer: &mut dyn std::io::Write) -> Result<bool, SerializeError> {
392        self.as_ref().serialize_extension(writer)
393    }
394
395    fn serialize_field(
396        &self,
397        field: &str,
398        writer: &mut dyn std::io::Write,
399    ) -> Result<bool, SerializeError> {
400        self.as_ref().serialize_field(field, writer)
401    }
402
403    fn is_fp_primitive(&self) -> bool {
404        self.as_ref().is_fp_primitive()
405    }
406}