eure_document/write/
record.rs1extern crate alloc;
4
5use alloc::string::ToString;
6
7use crate::document::constructor::DocumentConstructor;
8use crate::path::PathSegment;
9use crate::value::ObjectKey;
10
11use super::{IntoEure, WriteError};
12
13pub struct RecordWriter<'a> {
27 constructor: &'a mut DocumentConstructor,
28}
29
30impl<'a> RecordWriter<'a> {
31 pub(crate) fn new(constructor: &'a mut DocumentConstructor) -> Self {
33 Self { constructor }
34 }
35
36 pub fn field<T: IntoEure>(&mut self, name: &str, value: T) -> Result<(), WriteError> {
44 let scope = self.constructor.begin_scope();
45 self.constructor
46 .navigate(PathSegment::Value(ObjectKey::String(name.to_string())))?;
47 T::write(value, self.constructor)?;
48 self.constructor.end_scope(scope)?;
49 Ok(())
50 }
51
52 pub fn field_via<M, T>(&mut self, name: &str, value: T) -> Result<(), WriteError>
64 where
65 M: IntoEure<T>,
66 {
67 let scope = self.constructor.begin_scope();
68 self.constructor
69 .navigate(PathSegment::Value(ObjectKey::String(name.to_string())))?;
70 M::write(value, self.constructor)?;
71 self.constructor.end_scope(scope)?;
72 Ok(())
73 }
74
75 pub fn field_optional<T: IntoEure>(
84 &mut self,
85 name: &str,
86 value: Option<T>,
87 ) -> Result<(), WriteError> {
88 if let Some(v) = value {
89 self.field(name, v)?;
90 }
91 Ok(())
92 }
93
94 pub fn field_with<F, T>(&mut self, name: &str, f: F) -> Result<T, WriteError>
109 where
110 F: FnOnce(&mut DocumentConstructor) -> Result<T, WriteError>,
111 {
112 let scope = self.constructor.begin_scope();
113 self.constructor
114 .navigate(PathSegment::Value(ObjectKey::String(name.to_string())))?;
115 let result = f(self.constructor)?;
116 self.constructor.end_scope(scope)?;
117 Ok(result)
118 }
119
120 pub fn field_with_optional<T, F, R>(
131 &mut self,
132 name: &str,
133 value: Option<T>,
134 f: F,
135 ) -> Result<Option<R>, WriteError>
136 where
137 F: FnOnce(&mut DocumentConstructor, T) -> Result<R, WriteError>,
138 {
139 if let Some(v) = value {
140 let result = self.field_with(name, |c| f(c, v))?;
141 Ok(Some(result))
142 } else {
143 Ok(None)
144 }
145 }
146
147 pub fn constructor(&mut self) -> &mut DocumentConstructor {
151 self.constructor
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use crate::document::node::NodeValue;
159 use crate::text::Text;
160 use crate::value::PrimitiveValue;
161
162 #[test]
163 fn test_field() {
164 let mut c = DocumentConstructor::new();
165 c.record(|rec| {
166 rec.field("name", "Alice")?;
167 Ok(())
168 })
169 .unwrap();
170 let doc = c.finish();
171 let map = doc.root().as_map().unwrap();
172 let name_id = map.get(&ObjectKey::String("name".to_string())).unwrap();
173 let node = doc.node(*name_id);
174 assert_eq!(
175 node.content,
176 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext("Alice")))
177 );
178 }
179
180 #[test]
181 fn test_field_optional_some() {
182 let mut c = DocumentConstructor::new();
183 c.record(|rec| {
184 rec.field_optional("age", Some(30i32))?;
185 Ok(())
186 })
187 .unwrap();
188 let doc = c.finish();
189 let map = doc.root().as_map().unwrap();
190 assert!(map.get(&ObjectKey::String("age".to_string())).is_some());
191 }
192
193 #[test]
194 fn test_field_optional_none() {
195 let mut c = DocumentConstructor::new();
196 c.record(|rec| {
197 rec.field_optional::<i32>("age", None)?;
198 Ok(())
199 })
200 .unwrap();
201 let doc = c.finish();
202 let map = doc.root().as_map().unwrap();
203 assert!(map.get(&ObjectKey::String("age".to_string())).is_none());
204 }
205
206 #[test]
207 fn test_field_with() {
208 let mut c = DocumentConstructor::new();
209 c.record(|rec| {
210 rec.field_with("nested", |c| {
211 c.record(|rec| {
212 rec.field("inner", "value")?;
213 Ok(())
214 })
215 })?;
216 Ok(())
217 })
218 .unwrap();
219 let doc = c.finish();
220 let map = doc.root().as_map().unwrap();
221 let nested_id = map.get(&ObjectKey::String("nested".to_string())).unwrap();
222 let nested = doc.node(*nested_id).as_map().unwrap();
223 assert!(
224 nested
225 .get(&ObjectKey::String("inner".to_string()))
226 .is_some()
227 );
228 }
229
230 #[test]
231 fn test_multiple_fields() {
232 let mut c = DocumentConstructor::new();
233 c.record(|rec| {
234 rec.field("name", "Bob")?;
235 rec.field("age", 25i32)?;
236 rec.field("active", true)?;
237 Ok(())
238 })
239 .unwrap();
240 let doc = c.finish();
241 let map = doc.root().as_map().unwrap();
242 assert_eq!(map.len(), 3);
243 }
244}