eure_document/write/
tuple.rs1extern crate alloc;
4
5use crate::document::constructor::DocumentConstructor;
6use crate::path::PathSegment;
7
8use super::{IntoEure, 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: IntoEure>(&mut self, value: T) -> Result<(), WriteError> {
48 let scope = self.constructor.begin_scope();
49 self.constructor
50 .navigate(PathSegment::TupleIndex(self.position))?;
51 T::write(value, self.constructor)?;
52 self.constructor.end_scope(scope)?;
53 self.position += 1;
54 Ok(())
55 }
56
57 pub fn next_via<M, T>(&mut self, value: T) -> Result<(), WriteError>
69 where
70 M: IntoEure<T>,
71 {
72 let scope = self.constructor.begin_scope();
73 self.constructor
74 .navigate(PathSegment::TupleIndex(self.position))?;
75 M::write(value, self.constructor)?;
76 self.constructor.end_scope(scope)?;
77 self.position += 1;
78 Ok(())
79 }
80
81 pub fn next_with<F, R>(&mut self, f: F) -> Result<R, WriteError>
96 where
97 F: FnOnce(&mut DocumentConstructor) -> Result<R, WriteError>,
98 {
99 let scope = self.constructor.begin_scope();
100 self.constructor
101 .navigate(PathSegment::TupleIndex(self.position))?;
102 let result = f(self.constructor)?;
103 self.constructor.end_scope(scope)?;
104 self.position += 1;
105 Ok(result)
106 }
107
108 pub fn position(&self) -> u8 {
110 self.position
111 }
112
113 pub fn constructor(&mut self) -> &mut DocumentConstructor {
117 self.constructor
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use alloc::string::ToString;
124
125 use super::*;
126 use crate::document::node::NodeValue;
127 use crate::text::Text;
128 use crate::value::{ObjectKey, PrimitiveValue};
129
130 #[test]
131 fn test_next_sequential() {
132 let mut c = DocumentConstructor::new();
133 c.tuple(|t| {
134 t.next(1i32)?;
135 t.next("two")?;
136 t.next(true)?;
137 Ok(())
138 })
139 .unwrap();
140 let doc = c.finish();
141 let tuple = doc.root().as_tuple().unwrap();
142 assert_eq!(tuple.len(), 3);
143 }
144
145 #[test]
146 fn test_next_with_nested() {
147 let mut c = DocumentConstructor::new();
148 c.tuple(|t| {
149 t.next("first")?;
150 t.next_with(|c| {
151 c.record(|rec| {
152 rec.field("inner", "value")?;
153 Ok(())
154 })
155 })?;
156 Ok(())
157 })
158 .unwrap();
159 let doc = c.finish();
160 let tuple = doc.root().as_tuple().unwrap();
161 assert_eq!(tuple.len(), 2);
162
163 let nested_id = tuple.get(1).unwrap();
165 let nested = doc.node(nested_id).as_map().unwrap();
166 assert!(
167 nested
168 .get(&ObjectKey::String("inner".to_string()))
169 .is_some()
170 );
171 }
172
173 #[test]
174 fn test_position_tracking() {
175 let mut c = DocumentConstructor::new();
176 c.tuple(|t| {
177 assert_eq!(t.position(), 0);
178 t.next(1i32)?;
179 assert_eq!(t.position(), 1);
180 t.next(2i32)?;
181 assert_eq!(t.position(), 2);
182 Ok(())
183 })
184 .unwrap();
185 }
186
187 #[test]
188 fn test_empty_tuple() {
189 let mut c = DocumentConstructor::new();
190 c.tuple(|_t| Ok(())).unwrap();
191 let doc = c.finish();
192 let tuple = doc.root().as_tuple().unwrap();
193 assert!(tuple.is_empty());
194 }
195
196 #[test]
197 fn test_values_written_correctly() {
198 let mut c = DocumentConstructor::new();
199 c.tuple(|t| {
200 t.next(42i32)?;
201 t.next("hello")?;
202 Ok(())
203 })
204 .unwrap();
205 let doc = c.finish();
206 let tuple = doc.root().as_tuple().unwrap();
207
208 let first_id = tuple.get(0).unwrap();
210 assert_eq!(
211 doc.node(first_id).content,
212 NodeValue::Primitive(PrimitiveValue::Integer(42.into()))
213 );
214
215 let second_id = tuple.get(1).unwrap();
217 assert_eq!(
218 doc.node(second_id).content,
219 NodeValue::Primitive(PrimitiveValue::Text(Text::plaintext("hello")))
220 );
221 }
222}