1extern crate alloc;
4
5pub mod record;
6pub mod tuple;
7
8pub use record::RecordWriter;
9pub use tuple::TupleWriter;
10
11use alloc::string::String;
12use num_bigint::BigInt;
13
14use crate::document::InsertError;
15use crate::document::constructor::{DocumentConstructor, ScopeError};
16use crate::path::PathSegment;
17use crate::prelude_internal::*;
18use crate::text::Text;
19
20#[derive(Debug, thiserror::Error, Clone)]
22pub enum WriteError {
23 #[error("insert error: {0}")]
25 Insert(#[from] InsertError),
26
27 #[error("scope error: {0}")]
29 Scope(#[from] ScopeError),
30
31 #[error("invalid identifier: {0}")]
33 InvalidIdentifier(String),
34}
35
36pub trait IntoEure {
55 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError>;
57}
58
59impl IntoEure for bool {
64 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
65 c.bind_primitive(PrimitiveValue::Bool(self))?;
66 Ok(())
67 }
68}
69
70impl IntoEure for i32 {
71 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
72 c.bind_primitive(PrimitiveValue::Integer(BigInt::from(self)))?;
73 Ok(())
74 }
75}
76
77impl IntoEure for i64 {
78 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
79 c.bind_primitive(PrimitiveValue::Integer(BigInt::from(self)))?;
80 Ok(())
81 }
82}
83
84impl IntoEure for u32 {
85 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
86 c.bind_primitive(PrimitiveValue::Integer(BigInt::from(self)))?;
87 Ok(())
88 }
89}
90
91impl IntoEure for u64 {
92 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
93 c.bind_primitive(PrimitiveValue::Integer(BigInt::from(self)))?;
94 Ok(())
95 }
96}
97
98impl IntoEure for usize {
99 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
100 c.bind_primitive(PrimitiveValue::Integer(BigInt::from(self)))?;
101 Ok(())
102 }
103}
104
105impl IntoEure for f32 {
106 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
107 c.bind_primitive(PrimitiveValue::F32(self))?;
108 Ok(())
109 }
110}
111
112impl IntoEure for f64 {
113 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
114 c.bind_primitive(PrimitiveValue::F64(self))?;
115 Ok(())
116 }
117}
118
119impl IntoEure for BigInt {
120 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
121 c.bind_primitive(PrimitiveValue::Integer(self))?;
122 Ok(())
123 }
124}
125
126impl IntoEure for String {
127 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
128 c.bind_primitive(PrimitiveValue::Text(Text::plaintext(self)))?;
129 Ok(())
130 }
131}
132
133impl IntoEure for &str {
134 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
135 c.bind_primitive(PrimitiveValue::Text(Text::plaintext(self)))?;
136 Ok(())
137 }
138}
139
140impl IntoEure for Text {
141 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
142 c.bind_primitive(PrimitiveValue::Text(self))?;
143 Ok(())
144 }
145}
146
147impl IntoEure for PrimitiveValue {
148 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
149 c.bind_primitive(self)?;
150 Ok(())
151 }
152}
153
154impl IntoEure for Identifier {
155 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
156 c.bind_primitive(PrimitiveValue::Text(Text::plaintext(self.into_string())))?;
157 Ok(())
158 }
159}
160
161impl<T: IntoEure> IntoEure for Vec<T> {
166 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
167 c.bind_empty_array()?;
168 for item in self {
169 let scope = c.begin_scope();
170 c.navigate(PathSegment::ArrayIndex(None))?;
171 item.write_to(c)?;
172 c.end_scope(scope)?;
173 }
174 Ok(())
175 }
176}
177
178impl<K, V> IntoEure for Map<K, V>
179where
180 K: Into<ObjectKey>,
181 V: IntoEure,
182{
183 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
184 c.bind_empty_map()?;
185 for (key, value) in self {
186 let scope = c.begin_scope();
187 c.navigate(PathSegment::Value(key.into()))?;
188 value.write_to(c)?;
189 c.end_scope(scope)?;
190 }
191 Ok(())
192 }
193}
194
195impl<T: IntoEure> IntoEure for Option<T> {
196 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
197 match self {
198 Some(value) => value.write_to(c),
199 None => {
200 c.bind_primitive(PrimitiveValue::Null)?;
201 Ok(())
202 }
203 }
204 }
205}
206
207macro_rules! impl_into_document_tuple {
212 ($n:expr, $($idx:tt: $var:ident),+) => {
213 impl<$($var: IntoEure),+> IntoEure for ($($var,)+) {
214 fn write_to(self, c: &mut DocumentConstructor) -> Result<(), WriteError> {
215 c.bind_empty_tuple()?;
216 $(
217 let scope = c.begin_scope();
218 c.navigate(PathSegment::TupleIndex($idx))?;
219 self.$idx.write_to(c)?;
220 c.end_scope(scope)?;
221 )+
222 Ok(())
223 }
224 }
225 };
226}
227
228impl_into_document_tuple!(1, 0: A);
229impl_into_document_tuple!(2, 0: A, 1: B);
230impl_into_document_tuple!(3, 0: A, 1: B, 2: C);
231impl_into_document_tuple!(4, 0: A, 1: B, 2: C, 3: D);
232impl_into_document_tuple!(5, 0: A, 1: B, 2: C, 3: D, 4: E);
233impl_into_document_tuple!(6, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F);
234impl_into_document_tuple!(7, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G);
235impl_into_document_tuple!(8, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H);
236impl_into_document_tuple!(9, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I);
237impl_into_document_tuple!(10, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J);
238impl_into_document_tuple!(11, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K);
239impl_into_document_tuple!(12, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L);
240impl_into_document_tuple!(13, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L, 12: M);
241impl_into_document_tuple!(14, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L, 12: M, 13: N);
242impl_into_document_tuple!(15, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L, 12: M, 13: N, 14: O);
243impl_into_document_tuple!(16, 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L, 12: M, 13: N, 14: O, 15: P);
244
245impl DocumentConstructor {
250 pub fn record<F, T>(&mut self, f: F) -> Result<T, WriteError>
262 where
263 F: FnOnce(&mut RecordWriter<'_>) -> Result<T, WriteError>,
264 {
265 self.bind_empty_map()?;
266 let mut writer = RecordWriter::new(self);
267 f(&mut writer)
268 }
269
270 pub fn tuple<F, T>(&mut self, f: F) -> Result<T, WriteError>
283 where
284 F: FnOnce(&mut TupleWriter<'_>) -> Result<T, WriteError>,
285 {
286 self.bind_empty_tuple()?;
287 let mut writer = TupleWriter::new(self);
288 f(&mut writer)
289 }
290
291 pub fn set_extension<T: IntoEure>(&mut self, name: &str, value: T) -> Result<(), WriteError> {
299 let ident: Identifier = name
300 .parse()
301 .map_err(|_| WriteError::InvalidIdentifier(name.into()))?;
302 let scope = self.begin_scope();
303 self.navigate(PathSegment::Extension(ident))?;
304 value.write_to(self)?;
305 self.end_scope(scope)?;
306 Ok(())
307 }
308
309 pub fn set_extension_optional<T: IntoEure>(
318 &mut self,
319 name: &str,
320 value: Option<T>,
321 ) -> Result<(), WriteError> {
322 if let Some(v) = value {
323 self.set_extension(name, v)?;
324 }
325 Ok(())
326 }
327
328 pub fn set_variant(&mut self, variant: &str) -> Result<(), WriteError> {
341 self.set_extension("variant", variant)
342 }
343
344 pub fn write<T: IntoEure>(&mut self, value: T) -> Result<(), WriteError> {
352 value.write_to(self)
353 }
354}
355
356#[cfg(test)]
357mod tests {
358 use super::*;
359
360 #[test]
361 fn test_primitive_bool() {
362 let mut c = DocumentConstructor::new();
363 true.write_to(&mut c).unwrap();
364 let doc = c.finish();
365 assert_eq!(
366 doc.root().content,
367 NodeValue::Primitive(PrimitiveValue::Bool(true))
368 );
369 }
370
371 #[test]
372 fn test_primitive_string() {
373 let mut c = DocumentConstructor::new();
374 "hello".write_to(&mut c).unwrap();
375 let doc = c.finish();
376 assert_eq!(
377 doc.root().content,
378 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext("hello")))
379 );
380 }
381
382 #[test]
383 fn test_vec() {
384 let mut c = DocumentConstructor::new();
385 vec![1i32, 2, 3].write_to(&mut c).unwrap();
386 let doc = c.finish();
387 let arr = doc.root().as_array().unwrap();
388 assert_eq!(arr.len(), 3);
389 }
390
391 #[test]
392 fn test_tuple() {
393 let mut c = DocumentConstructor::new();
394 (1i32, "two", true).write_to(&mut c).unwrap();
395 let doc = c.finish();
396 let tuple = doc.root().as_tuple().unwrap();
397 assert_eq!(tuple.len(), 3);
398 }
399
400 #[test]
401 fn test_record() {
402 let mut c = DocumentConstructor::new();
403 c.record(|rec| {
404 rec.field("name", "Alice")?;
405 rec.field("age", 30i32)?;
406 Ok(())
407 })
408 .unwrap();
409 let doc = c.finish();
410 let map = doc.root().as_map().unwrap();
411 assert_eq!(map.len(), 2);
412 }
413
414 #[test]
415 fn test_set_extension() {
416 let mut c = DocumentConstructor::new();
417 c.record(|rec| {
418 rec.field("type", "string")?;
419 Ok(())
420 })
421 .unwrap();
422 c.set_extension("optional", true).unwrap();
423 let doc = c.finish();
424
425 let root = doc.root();
426 assert!(
427 root.extensions
428 .contains_key(&"optional".parse::<Identifier>().unwrap())
429 );
430 }
431
432 #[test]
433 fn test_set_variant() {
434 let mut c = DocumentConstructor::new();
435 c.set_variant("foo").unwrap();
436 c.record(|rec| {
437 rec.field("value", 42i32)?;
438 Ok(())
439 })
440 .unwrap();
441 let doc = c.finish();
442
443 let root = doc.root();
444 assert!(
445 root.extensions
446 .contains_key(&"variant".parse::<Identifier>().unwrap())
447 );
448 }
449
450 #[test]
451 fn test_nested_record() {
452 let mut c = DocumentConstructor::new();
453 c.record(|rec| {
454 rec.field("name", "Alice")?;
455 rec.field_with("address", |c| {
456 c.record(|rec| {
457 rec.field("city", "Tokyo")?;
458 rec.field("zip", "100-0001")?;
459 Ok(())
460 })
461 })?;
462 Ok(())
463 })
464 .unwrap();
465 let doc = c.finish();
466 let map = doc.root().as_map().unwrap();
467 assert_eq!(map.len(), 2);
468 }
469}