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 use std::io::Write as _;
106 let mut buf = [0u8; 42];
107 let mut w: &mut [u8] = &mut buf;
108 if write!(w, "{self}").is_ok() {
109 let written = 42 - w.len();
110 let s = std::str::from_utf8(&buf[..written]).map_err(|_| EdifactError::InvalidUtf8)?;
112 emitter.emit(EdifactEvent::Element { value: s })
113 } else {
114 let s = format!("{self}");
116 emitter.emit(EdifactEvent::Element { value: &s })
117 }
118 }
119 }
120 )+
121 };
122}
123
124impl_serialize_int!(
126 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, bool
127);
128
129macro_rules! impl_serialize_float {
135 ($($t:ty),+ $(,)?) => {
136 $(
137 impl EdifactSerialize for $t {
138 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
139 use std::io::Write as _;
140 let mut buf = [0u8; 320];
141 let mut w: &mut [u8] = &mut buf;
142 if write!(w, "{self}").is_ok() {
143 let written = 320 - w.len();
144 let s = std::str::from_utf8(&buf[..written]).map_err(|_| EdifactError::InvalidUtf8)?;
146 emitter.emit(EdifactEvent::Element { value: s })
147 } else {
148 let s = format!("{self}");
150 emitter.emit(EdifactEvent::Element { value: &s })
151 }
152 }
153 }
154 )+
155 };
156}
157
158impl_serialize_float!(f32, f64);
159
160#[derive(Debug, Clone, Copy, PartialEq)]
202pub struct DecimalFloat<T>(pub T);
203
204#[derive(Debug, Clone, Copy, PartialEq)]
209pub struct DecimalFloatDisplay<T: std::fmt::Display>(pub T);
210
211fn serialize_with_decimal_mark<E: EventEmitter>(
212 display: &dyn std::fmt::Display,
213 emitter: &mut E,
214) -> Result<(), EdifactError> {
215 use std::io::Write as _;
216 let mark = emitter.decimal_mark();
217
218 if mark == b'.' {
220 let mut buf = [0u8; 320];
221 let mut w: &mut [u8] = &mut buf;
222 if write!(w, "{display}").is_ok() {
223 let written = 320 - w.len();
224 let s = std::str::from_utf8(&buf[..written]).map_err(|_| EdifactError::InvalidUtf8)?;
226 return emitter.emit(EdifactEvent::Element { value: s });
227 }
228 let s = format!("{display}");
230 return emitter.emit(EdifactEvent::Element { value: &s });
231 }
232
233 let s = format!("{display}");
236 if s.contains('.') {
237 let mut mark_buf = [0u8; 4];
239 let mark_str = (mark as char).encode_utf8(&mut mark_buf);
240 let replaced = s.replace('.', mark_str);
241 emitter.emit(EdifactEvent::Element { value: &replaced })
242 } else {
243 emitter.emit(EdifactEvent::Element { value: &s })
244 }
245}
246
247impl EdifactSerialize for DecimalFloat<f32> {
248 #[inline]
249 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
250 serialize_with_decimal_mark(&self.0, emitter)
251 }
252}
253
254impl EdifactSerialize for DecimalFloat<f64> {
255 #[inline]
256 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
257 serialize_with_decimal_mark(&self.0, emitter)
258 }
259}
260
261impl<T: std::fmt::Display> EdifactSerialize for DecimalFloatDisplay<T> {
262 #[inline]
263 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
264 serialize_with_decimal_mark(&self.0, emitter)
265 }
266}
267
268pub fn to_writer<T, W>(inner: W, value: &T) -> Result<(), EdifactError>
270where
271 T: EdifactSerialize,
272 W: Write,
273{
274 let mut emitter = WriterEmitter::new(inner);
275 value.edifact_serialize(&mut emitter)?;
276 emitter.finish().map(|_| ())
277}
278
279pub fn to_bytes<T: EdifactSerialize>(value: &T) -> Result<Vec<u8>, EdifactError> {
281 let mut buf = Vec::new();
282 to_writer(&mut buf, value)?;
283 Ok(buf)
284}
285
286pub fn to_edifact_string<T: EdifactSerialize>(value: &T) -> Result<String, EdifactError> {
295 let bytes = to_bytes(value)?;
296 String::from_utf8(bytes).map_err(|_| EdifactError::InvalidUtf8)
297}
298
299#[cfg(test)]
300mod tests {
301 use super::*;
302 use crate::event::{OwnedEdifactEvent, VecEmitter};
303
304 struct BgmSegment {
305 doc_name_code: String,
306 pruef_id: String,
307 msg_function: Option<String>,
308 }
309
310 impl EdifactSerialize for BgmSegment {
311 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
312 emitter.emit(EdifactEvent::StartSegment { tag: "BGM" })?;
313 emitter.emit(EdifactEvent::Element {
314 value: &self.doc_name_code,
315 })?;
316 emitter.emit(EdifactEvent::Element {
317 value: &self.pruef_id,
318 })?;
319 self.msg_function.edifact_serialize(emitter)?;
320 emitter.emit(EdifactEvent::EndSegment)?;
321 Ok(())
322 }
323 }
324
325 #[test]
326 fn vec_emitter_captures_segment_events() {
327 let seg = BgmSegment {
328 doc_name_code: "E03".to_owned(),
329 pruef_id: "11042".to_owned(),
330 msg_function: None,
331 };
332 let mut emitter = VecEmitter::default();
333 seg.edifact_serialize(&mut emitter).unwrap();
334
335 assert_eq!(
336 emitter.events[0],
337 OwnedEdifactEvent::StartSegment {
338 tag: "BGM".to_owned()
339 }
340 );
341 assert_eq!(emitter.events.last(), Some(&OwnedEdifactEvent::EndSegment));
342 }
343
344 #[test]
345 fn to_bytes_produces_valid_edifact() {
346 let seg = BgmSegment {
347 doc_name_code: "E03".to_owned(),
348 pruef_id: "11042".to_owned(),
349 msg_function: Some("9".to_owned()),
350 };
351 let bytes = to_bytes(&seg).unwrap();
352 assert_eq!(std::str::from_utf8(&bytes).unwrap(), "BGM+E03+11042+9'");
353 }
354
355 #[test]
356 fn option_none_emits_empty_element() {
357 let val: Option<String> = None;
358 let mut emitter = VecEmitter::default();
359 val.edifact_serialize(&mut emitter).unwrap();
360 assert_eq!(
361 emitter.events[0],
362 OwnedEdifactEvent::Element {
363 value: String::new()
364 }
365 );
366 }
367
368 #[test]
369 fn option_some_emits_value() {
370 let val: Option<String> = Some("TEST".to_owned());
371 let mut emitter = VecEmitter::default();
372 val.edifact_serialize(&mut emitter).unwrap();
373 assert_eq!(
374 emitter.events[0],
375 OwnedEdifactEvent::Element {
376 value: "TEST".to_owned()
377 }
378 );
379 }
380
381 #[test]
382 fn integer_types_serialize_without_alloc() {
383 let mut emitter = VecEmitter::default();
384 42u32.edifact_serialize(&mut emitter).unwrap();
385 assert_eq!(
386 emitter.events[0],
387 OwnedEdifactEvent::Element {
388 value: "42".to_owned()
389 }
390 );
391 let mut emitter2 = VecEmitter::default();
393 i128::MIN.edifact_serialize(&mut emitter2).unwrap();
394 assert_eq!(
395 emitter2.events[0],
396 OwnedEdifactEvent::Element {
397 value: "-170141183460469231731687303715884105728".to_owned()
398 }
399 );
400 }
401
402 #[test]
403 fn float_extremes_do_not_panic() {
404 let mut emitter = VecEmitter::default();
406 f64::MAX.edifact_serialize(&mut emitter).unwrap();
407 let s = match &emitter.events[0] {
408 OwnedEdifactEvent::Element { value } => value.clone(),
409 _ => panic!("expected Element event"),
410 };
411 assert!(!s.is_empty());
412 let mut emitter2 = VecEmitter::default();
414 f32::MAX.edifact_serialize(&mut emitter2).unwrap();
415 assert!(matches!(
416 &emitter2.events[0],
417 OwnedEdifactEvent::Element { .. }
418 ));
419 }
420
421 #[test]
422 fn vec_serializes_each_item() {
423 let segments = vec![
424 BgmSegment {
425 doc_name_code: "E03".to_owned(),
426 pruef_id: "11042".to_owned(),
427 msg_function: None,
428 },
429 BgmSegment {
430 doc_name_code: "E01".to_owned(),
431 pruef_id: "11043".to_owned(),
432 msg_function: None,
433 },
434 ];
435 let bytes = to_bytes(&segments).unwrap();
436 let s = std::str::from_utf8(&bytes).unwrap();
437 assert!(s.contains("BGM+E03+11042"));
438 assert!(s.contains("BGM+E01+11043"));
439 }
440}