Skip to main content

fixed_json/
builder.rs

1use core::{array, mem::MaybeUninit, ptr, slice};
2
3use crate::{Array, Attr, Result, read_object};
4
5pub struct ObjectBuilder<'input, 'a, const N: usize> {
6    input: &'input str,
7    attrs: [MaybeUninit<Attr<'a>>; N],
8    len: usize,
9}
10
11impl<'input, 'a, const N: usize> ObjectBuilder<'input, 'a, N> {
12    #[inline]
13    pub fn new(input: &'input str) -> Self {
14        Self {
15            input,
16            attrs: array::from_fn(|_| MaybeUninit::uninit()),
17            len: 0,
18        }
19    }
20
21    #[inline]
22    pub fn attr(mut self, attr: Attr<'a>) -> Self {
23        assert!(self.len < N, "too many attributes for ObjectBuilder");
24        self.attrs[self.len].write(attr);
25        self.len += 1;
26        self
27    }
28
29    #[inline]
30    pub fn integer(self, name: &'a str, target: &'a mut i32) -> Self {
31        self.attr(Attr::integer(name, target))
32    }
33
34    #[inline]
35    pub fn integers(self, name: &'a str, target: &'a mut [i32]) -> Self {
36        self.attr(Attr::integers(name, target))
37    }
38
39    #[inline]
40    pub fn uinteger(self, name: &'a str, target: &'a mut u32) -> Self {
41        self.attr(Attr::uinteger(name, target))
42    }
43
44    #[inline]
45    pub fn uintegers(self, name: &'a str, target: &'a mut [u32]) -> Self {
46        self.attr(Attr::uintegers(name, target))
47    }
48
49    #[inline]
50    pub fn short(self, name: &'a str, target: &'a mut i16) -> Self {
51        self.attr(Attr::short(name, target))
52    }
53
54    #[inline]
55    pub fn shorts(self, name: &'a str, target: &'a mut [i16]) -> Self {
56        self.attr(Attr::shorts(name, target))
57    }
58
59    #[inline]
60    pub fn ushort(self, name: &'a str, target: &'a mut u16) -> Self {
61        self.attr(Attr::ushort(name, target))
62    }
63
64    #[inline]
65    pub fn ushorts(self, name: &'a str, target: &'a mut [u16]) -> Self {
66        self.attr(Attr::ushorts(name, target))
67    }
68
69    #[inline]
70    pub fn real(self, name: &'a str, target: &'a mut f64) -> Self {
71        self.attr(Attr::real(name, target))
72    }
73
74    #[inline]
75    pub fn reals(self, name: &'a str, target: &'a mut [f64]) -> Self {
76        self.attr(Attr::reals(name, target))
77    }
78
79    #[inline]
80    pub fn string(self, name: &'a str, target: &'a mut [u8]) -> Self {
81        self.attr(Attr::string(name, target))
82    }
83
84    #[inline]
85    pub fn boolean(self, name: &'a str, target: &'a mut bool) -> Self {
86        self.attr(Attr::boolean(name, target))
87    }
88
89    #[inline]
90    pub fn booleans(self, name: &'a str, target: &'a mut [bool]) -> Self {
91        self.attr(Attr::booleans(name, target))
92    }
93
94    #[inline]
95    pub fn character(self, name: &'a str, target: &'a mut u8) -> Self {
96        self.attr(Attr::character(name, target))
97    }
98
99    #[inline]
100    pub fn characters(self, name: &'a str, target: &'a mut [u8]) -> Self {
101        self.attr(Attr::characters(name, target))
102    }
103
104    #[inline]
105    pub fn time(self, name: &'a str, target: &'a mut f64) -> Self {
106        self.attr(Attr::time(name, target))
107    }
108
109    #[inline]
110    pub fn object(self, name: &'a str, attrs: &'a mut [Attr<'a>]) -> Self {
111        self.attr(Attr::object(name, attrs))
112    }
113
114    #[inline]
115    pub fn array(self, name: &'a str, array: Array<'a>) -> Self {
116        self.attr(Attr::array(name, array))
117    }
118
119    #[inline]
120    pub fn check(self, name: &'a str, expected: &'a str) -> Self {
121        self.attr(Attr::check(name, expected))
122    }
123
124    #[inline]
125    pub fn ignore_any(self) -> Self {
126        self.attr(Attr::ignore_any())
127    }
128
129    #[inline]
130    pub fn read(mut self) -> Result<usize> {
131        // The first `len` entries are initialized exclusively by `attr`.
132        let attrs = unsafe {
133            slice::from_raw_parts_mut(self.attrs.as_mut_ptr().cast::<Attr<'a>>(), self.len)
134        };
135        read_object(self.input, attrs)
136    }
137}
138
139impl<const N: usize> Drop for ObjectBuilder<'_, '_, N> {
140    fn drop(&mut self) {
141        for attr in &mut self.attrs[..self.len] {
142            // Match the initialized prefix maintained by `attr`.
143            unsafe {
144                ptr::drop_in_place(attr.as_mut_ptr());
145            }
146        }
147    }
148}
149
150#[cfg(test)]
151mod tests {
152    use super::ObjectBuilder;
153    use crate::{Attr, DefaultValue};
154
155    #[test]
156    fn reads_basic_object_with_builder() {
157        let mut flag1 = false;
158        let mut flag2 = false;
159        let mut count = 0;
160
161        let end = ObjectBuilder::<3>::new(r#"{"flag2":false,"count":7,"flag1":true}"#)
162            .integer("count", &mut count)
163            .boolean("flag1", &mut flag1)
164            .boolean("flag2", &mut flag2)
165            .read()
166            .unwrap();
167
168        assert_eq!(end, 38);
169        assert_eq!(count, 7);
170        assert!(flag1);
171        assert!(!flag2);
172    }
173
174    #[test]
175    fn accepts_preconfigured_attrs() {
176        let mut count = 1;
177
178        ObjectBuilder::<1>::new(r#"{}"#)
179            .attr(Attr::integer("count", &mut count).with_default(DefaultValue::Integer(5)))
180            .read()
181            .unwrap();
182
183        assert_eq!(count, 5);
184    }
185}