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 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 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}