eure_document/write/
tuple.rs1extern crate alloc;
4
5use crate::document::constructor::DocumentConstructor;
6use crate::path::PathSegment;
7
8use super::{IntoDocument, WriteError};
9
10pub struct TupleWriter<'a> {
26 constructor: &'a mut DocumentConstructor,
27 position: u8,
28}
29
30impl<'a> TupleWriter<'a> {
31 pub(crate) fn new(constructor: &'a mut DocumentConstructor) -> Self {
33 Self {
34 constructor,
35 position: 0,
36 }
37 }
38
39 pub fn next<T: IntoDocument>(&mut self, value: T) -> Result<(), WriteError> {
48 let scope = self.constructor.begin_scope();
49 self.constructor
50 .navigate(PathSegment::TupleIndex(self.position))?;
51 value.write_to(self.constructor)?;
52 self.constructor.end_scope(scope)?;
53 self.position += 1;
54 Ok(())
55 }
56
57 pub fn next_with<F, R>(&mut self, f: F) -> Result<R, WriteError>
72 where
73 F: FnOnce(&mut DocumentConstructor) -> Result<R, WriteError>,
74 {
75 let scope = self.constructor.begin_scope();
76 self.constructor
77 .navigate(PathSegment::TupleIndex(self.position))?;
78 let result = f(self.constructor)?;
79 self.constructor.end_scope(scope)?;
80 self.position += 1;
81 Ok(result)
82 }
83
84 pub fn position(&self) -> u8 {
86 self.position
87 }
88
89 pub fn constructor(&mut self) -> &mut DocumentConstructor {
93 self.constructor
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use alloc::string::ToString;
100
101 use super::*;
102 use crate::document::node::NodeValue;
103 use crate::text::Text;
104 use crate::value::{ObjectKey, PrimitiveValue};
105
106 #[test]
107 fn test_next_sequential() {
108 let mut c = DocumentConstructor::new();
109 c.tuple(|t| {
110 t.next(1i32)?;
111 t.next("two")?;
112 t.next(true)?;
113 Ok(())
114 })
115 .unwrap();
116 let doc = c.finish();
117 let tuple = doc.root().as_tuple().unwrap();
118 assert_eq!(tuple.len(), 3);
119 }
120
121 #[test]
122 fn test_next_with_nested() {
123 let mut c = DocumentConstructor::new();
124 c.tuple(|t| {
125 t.next("first")?;
126 t.next_with(|c| {
127 c.record(|rec| {
128 rec.field("inner", "value")?;
129 Ok(())
130 })
131 })?;
132 Ok(())
133 })
134 .unwrap();
135 let doc = c.finish();
136 let tuple = doc.root().as_tuple().unwrap();
137 assert_eq!(tuple.len(), 2);
138
139 let nested_id = tuple.get(1).unwrap();
141 let nested = doc.node(nested_id).as_map().unwrap();
142 assert!(
143 nested
144 .get(&ObjectKey::String("inner".to_string()))
145 .is_some()
146 );
147 }
148
149 #[test]
150 fn test_position_tracking() {
151 let mut c = DocumentConstructor::new();
152 c.tuple(|t| {
153 assert_eq!(t.position(), 0);
154 t.next(1i32)?;
155 assert_eq!(t.position(), 1);
156 t.next(2i32)?;
157 assert_eq!(t.position(), 2);
158 Ok(())
159 })
160 .unwrap();
161 }
162
163 #[test]
164 fn test_empty_tuple() {
165 let mut c = DocumentConstructor::new();
166 c.tuple(|_t| Ok(())).unwrap();
167 let doc = c.finish();
168 let tuple = doc.root().as_tuple().unwrap();
169 assert!(tuple.is_empty());
170 }
171
172 #[test]
173 fn test_values_written_correctly() {
174 let mut c = DocumentConstructor::new();
175 c.tuple(|t| {
176 t.next(42i32)?;
177 t.next("hello")?;
178 Ok(())
179 })
180 .unwrap();
181 let doc = c.finish();
182 let tuple = doc.root().as_tuple().unwrap();
183
184 let first_id = tuple.get(0).unwrap();
186 assert_eq!(
187 doc.node(first_id).content,
188 NodeValue::Primitive(PrimitiveValue::Integer(42.into()))
189 );
190
191 let second_id = tuple.get(1).unwrap();
193 assert_eq!(
194 doc.node(second_id).content,
195 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext("hello")))
196 );
197 }
198}