1use crate::EdifactError;
8use crate::event::{EdifactEvent, EventEmitter, WriterEmitter};
9use std::io::Write;
10
11pub trait EdifactSerialize {
18 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError>;
20}
21
22pub trait EdifactCompositeSerialize {
27 fn edifact_serialize_composite<E: EventEmitter>(
29 &self,
30 emitter: &mut E,
31 ) -> Result<(), EdifactError>;
32}
33
34impl EdifactCompositeSerialize for Vec<String> {
35 fn edifact_serialize_composite<E: EventEmitter>(
36 &self,
37 emitter: &mut E,
38 ) -> Result<(), EdifactError> {
39 if self.is_empty() {
40 return emitter.emit(EdifactEvent::Element { value: "" });
41 }
42
43 emitter.emit(EdifactEvent::Element { value: &self[0] })?;
44 for component in self.iter().skip(1) {
45 emitter.emit(EdifactEvent::ComponentElement { value: component })?;
46 }
47 Ok(())
48 }
49}
50
51impl EdifactSerialize for str {
54 #[inline]
55 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
56 emitter.emit(EdifactEvent::Element { value: self })
57 }
58}
59
60impl EdifactSerialize for String {
61 #[inline]
62 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
63 emitter.emit(EdifactEvent::Element {
64 value: self.as_str(),
65 })
66 }
67}
68
69impl<T: EdifactSerialize> EdifactSerialize for Option<T> {
71 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
72 match self {
73 Some(v) => v.edifact_serialize(emitter),
74 None => emitter.emit(EdifactEvent::Element { value: "" }),
75 }
76 }
77}
78
79impl<T: EdifactSerialize> EdifactSerialize for Vec<T> {
81 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
82 for item in self {
83 item.edifact_serialize(emitter)?;
84 }
85 Ok(())
86 }
87}
88
89impl<T: EdifactSerialize> EdifactSerialize for [T] {
91 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
92 for item in self {
93 item.edifact_serialize(emitter)?;
94 }
95 Ok(())
96 }
97}
98
99macro_rules! impl_serialize_int {
100 ($($t:ty),+ $(,)?) => {
101 $(
102 impl EdifactSerialize for $t {
103 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
104 let mut buf = [0u8; 40];
108 let s = {
109 use std::io::Write as _;
110 let mut cursor = std::io::Cursor::new(&mut buf[..]);
111 write!(cursor, "{}", self).expect("integer format into fixed buffer");
113 let len = cursor.position() as usize;
114 std::str::from_utf8(&buf[..len]).expect("integer output is valid UTF-8")
115 };
116 emitter.emit(EdifactEvent::Element { value: s })
117 }
118 }
119 )+
120 };
121}
122
123impl_serialize_int!(
125 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, bool
126);
127
128macro_rules! impl_serialize_float {
139 ($($t:ty),+ $(,)?) => {
140 $(
141 impl EdifactSerialize for $t {
142 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
143 use std::io::Write as _;
144 let mut buf = [0u8; 320];
145 let written = {
146 let mut w: &mut [u8] = &mut buf;
147 write!(w, "{self}").expect("float Display exceeded 320-byte stack buffer");
148 320 - w.len()
149 };
150 let s = std::str::from_utf8(&buf[..written])
151 .expect("float Display is always ASCII");
152 emitter.emit(EdifactEvent::Element { value: s })
153 }
154 }
155 )+
156 };
157}
158
159impl_serialize_float!(f32, f64);
160
161pub fn to_writer<T, W>(inner: W, value: &T) -> Result<(), EdifactError>
165where
166 T: EdifactSerialize,
167 W: Write,
168{
169 let mut emitter = WriterEmitter::new(inner);
170 value.edifact_serialize(&mut emitter)?;
171 emitter.finish().map(|_| ())
172}
173
174pub fn to_bytes<T: EdifactSerialize>(value: &T) -> Result<Vec<u8>, EdifactError> {
176 let mut buf = Vec::new();
177 to_writer(&mut buf, value)?;
178 Ok(buf)
179}
180
181pub fn to_edifact_string<T: EdifactSerialize>(value: &T) -> Result<String, EdifactError> {
190 let bytes = to_bytes(value)?;
191 String::from_utf8(bytes).map_err(|_| EdifactError::InvalidUtf8)
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197 use crate::event::{OwnedEdifactEvent, VecEmitter};
198
199 struct BgmSegment {
200 doc_name_code: String,
201 pruef_id: String,
202 msg_function: Option<String>,
203 }
204
205 impl EdifactSerialize for BgmSegment {
206 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
207 emitter.emit(EdifactEvent::StartSegment { tag: "BGM" })?;
208 emitter.emit(EdifactEvent::Element {
209 value: &self.doc_name_code,
210 })?;
211 emitter.emit(EdifactEvent::Element {
212 value: &self.pruef_id,
213 })?;
214 self.msg_function.edifact_serialize(emitter)?;
215 emitter.emit(EdifactEvent::EndSegment)?;
216 Ok(())
217 }
218 }
219
220 #[test]
221 fn vec_emitter_captures_segment_events() {
222 let seg = BgmSegment {
223 doc_name_code: "E03".to_owned(),
224 pruef_id: "11042".to_owned(),
225 msg_function: None,
226 };
227 let mut emitter = VecEmitter::default();
228 seg.edifact_serialize(&mut emitter).unwrap();
229
230 assert_eq!(
231 emitter.events[0],
232 OwnedEdifactEvent::StartSegment {
233 tag: "BGM".to_owned()
234 }
235 );
236 assert_eq!(emitter.events.last(), Some(&OwnedEdifactEvent::EndSegment));
237 }
238
239 #[test]
240 fn to_bytes_produces_valid_edifact() {
241 let seg = BgmSegment {
242 doc_name_code: "E03".to_owned(),
243 pruef_id: "11042".to_owned(),
244 msg_function: Some("9".to_owned()),
245 };
246 let bytes = to_bytes(&seg).unwrap();
247 assert_eq!(std::str::from_utf8(&bytes).unwrap(), "BGM+E03+11042+9'");
248 }
249
250 #[test]
251 fn option_none_emits_empty_element() {
252 let val: Option<String> = None;
253 let mut emitter = VecEmitter::default();
254 val.edifact_serialize(&mut emitter).unwrap();
255 assert_eq!(
256 emitter.events[0],
257 OwnedEdifactEvent::Element {
258 value: String::new()
259 }
260 );
261 }
262
263 #[test]
264 fn option_some_emits_value() {
265 let val: Option<String> = Some("TEST".to_owned());
266 let mut emitter = VecEmitter::default();
267 val.edifact_serialize(&mut emitter).unwrap();
268 assert_eq!(
269 emitter.events[0],
270 OwnedEdifactEvent::Element {
271 value: "TEST".to_owned()
272 }
273 );
274 }
275
276 #[test]
277 fn integer_types_serialize_without_alloc() {
278 let mut emitter = VecEmitter::default();
279 42u32.edifact_serialize(&mut emitter).unwrap();
280 assert_eq!(
281 emitter.events[0],
282 OwnedEdifactEvent::Element {
283 value: "42".to_owned()
284 }
285 );
286 let mut emitter2 = VecEmitter::default();
288 i128::MIN.edifact_serialize(&mut emitter2).unwrap();
289 assert_eq!(
290 emitter2.events[0],
291 OwnedEdifactEvent::Element {
292 value: "-170141183460469231731687303715884105728".to_owned()
293 }
294 );
295 }
296
297 #[test]
298 fn float_extremes_do_not_panic() {
299 let mut emitter = VecEmitter::default();
301 f64::MAX.edifact_serialize(&mut emitter).unwrap();
302 let s = match &emitter.events[0] {
303 OwnedEdifactEvent::Element { value } => value.clone(),
304 _ => panic!("expected Element event"),
305 };
306 assert!(!s.is_empty());
307 let mut emitter2 = VecEmitter::default();
309 f32::MAX.edifact_serialize(&mut emitter2).unwrap();
310 assert!(matches!(&emitter2.events[0], OwnedEdifactEvent::Element { .. }));
311 }
312
313 #[test]
314 fn vec_serializes_each_item() {
315 let segments = vec![
316 BgmSegment {
317 doc_name_code: "E03".to_owned(),
318 pruef_id: "11042".to_owned(),
319 msg_function: None,
320 },
321 BgmSegment {
322 doc_name_code: "E01".to_owned(),
323 pruef_id: "11043".to_owned(),
324 msg_function: None,
325 },
326 ];
327 let bytes = to_bytes(&segments).unwrap();
328 let s = std::str::from_utf8(&bytes).unwrap();
329 assert!(s.contains("BGM+E03+11042"));
330 assert!(s.contains("BGM+E01+11043"));
331 }
332}