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(""));
41 }
42
43 emitter.emit(EdifactEvent::element(&self[0]))?;
44 for component in self.iter().skip(1) {
45 emitter.emit(EdifactEvent::component(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(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(self.as_str()))
64 }
65}
66
67impl<T: EdifactSerialize> EdifactSerialize for Option<T> {
69 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
70 match self {
71 Some(v) => v.edifact_serialize(emitter),
72 None => emitter.emit(EdifactEvent::element("")),
73 }
74 }
75}
76
77impl<T: EdifactSerialize> EdifactSerialize for Vec<T> {
79 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
80 for item in self {
81 item.edifact_serialize(emitter)?;
82 }
83 Ok(())
84 }
85}
86
87impl<T: EdifactSerialize> EdifactSerialize for [T] {
89 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
90 for item in self {
91 item.edifact_serialize(emitter)?;
92 }
93 Ok(())
94 }
95}
96
97macro_rules! impl_serialize_int {
98 ($($t:ty),+ $(,)?) => {
99 $(
100 impl EdifactSerialize for $t {
101 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
102 use std::io::Write as _;
104 let mut buf = [0u8; 42];
105 let mut w: &mut [u8] = &mut buf;
106 if write!(w, "{self}").is_ok() {
107 let written = 42 - w.len();
108 let s = std::str::from_utf8(&buf[..written]).map_err(|_| EdifactError::InvalidUtf8)?;
110 emitter.emit(EdifactEvent::element(s))
111 } else {
112 let s = format!("{self}");
114 emitter.emit(EdifactEvent::element(&s))
115 }
116 }
117 }
118 )+
119 };
120}
121
122impl_serialize_int!(
124 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, bool
125);
126
127#[derive(Debug, Clone, Copy, PartialEq)]
175pub struct DecimalFloat<T>(pub T);
176
177fn serialize_with_decimal_mark<E: EventEmitter>(
178 display: &dyn std::fmt::Display,
179 emitter: &mut E,
180) -> Result<(), EdifactError> {
181 use std::io::Write as _;
182 let mark = emitter.decimal_mark();
183
184 if mark == b'.' {
186 let mut buf = [0u8; 320];
187 let mut w: &mut [u8] = &mut buf;
188 if write!(w, "{display}").is_ok() {
189 let written = 320 - w.len();
190 let s = std::str::from_utf8(&buf[..written]).map_err(|_| EdifactError::InvalidUtf8)?;
191 reject_non_finite(s)?;
192 return emitter.emit(EdifactEvent::element(s));
193 }
194 let s = format!("{display}");
196 reject_non_finite(&s)?;
197 return emitter.emit(EdifactEvent::element(&s));
198 }
199
200 let s = format!("{display}");
203 reject_non_finite(&s)?;
204 if s.contains('.') {
205 let mut mark_buf = [0u8; 4];
207 let mark_str = (mark as char).encode_utf8(&mut mark_buf);
208 let replaced = s.replace('.', mark_str);
209 emitter.emit(EdifactEvent::element(&replaced))
210 } else {
211 emitter.emit(EdifactEvent::element(&s))
212 }
213}
214
215#[inline]
228fn reject_non_finite(rendered: &str) -> Result<(), EdifactError> {
229 let bare = rendered.strip_prefix(['+', '-']).unwrap_or(rendered);
230 if bare.eq_ignore_ascii_case("nan")
231 || bare.eq_ignore_ascii_case("inf")
232 || bare.eq_ignore_ascii_case("infinity")
233 {
234 return Err(EdifactError::NonFiniteNumber {
235 value: rendered.to_owned(),
236 });
237 }
238 Ok(())
239}
240
241impl<T: std::fmt::Display> EdifactSerialize for DecimalFloat<T> {
242 #[inline]
243 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
244 serialize_with_decimal_mark(&self.0, emitter)
245 }
246}
247
248pub fn emit_sparse_segment<E: EventEmitter>(
292 emitter: &mut E,
293 tag: &str,
294 parts: &mut [(usize, usize, std::borrow::Cow<'_, str>)],
295) -> Result<(), EdifactError> {
296 parts.sort_by_key(|(element, component, _)| (*element, *component));
297
298 emitter.emit(EdifactEvent::start(tag))?;
299
300 let mut cursor = 0usize;
303 let element_count = parts.last().map_or(0, |(element, _, _)| *element + 1);
304 for element in 0..element_count {
305 let mut next_component = 0usize;
307 let mut opened = false;
308 while cursor < parts.len() && parts[cursor].0 == element {
309 let (_, component, value) = &parts[cursor];
310 if *component < next_component {
311 cursor += 1;
314 continue;
315 }
316 while next_component < *component {
318 let event = if opened {
319 EdifactEvent::component("")
320 } else {
321 EdifactEvent::element("")
322 };
323 emitter.emit(event)?;
324 opened = true;
325 next_component += 1;
326 }
327 let event = if opened {
328 EdifactEvent::component(value.as_ref())
329 } else {
330 EdifactEvent::element(value.as_ref())
331 };
332 emitter.emit(event)?;
333 opened = true;
334 next_component += 1;
335 cursor += 1;
336 }
337 if !opened {
338 emitter.emit(EdifactEvent::element(""))?;
341 }
342 }
343
344 emitter.emit(EdifactEvent::EndSegment)
345}
346
347pub fn to_writer<T, W>(inner: W, value: &T) -> Result<(), EdifactError>
349where
350 T: EdifactSerialize,
351 W: Write,
352{
353 let mut emitter = WriterEmitter::new(inner);
354 value.edifact_serialize(&mut emitter)?;
355 emitter.finish().map(|_| ())
356}
357
358pub fn to_bytes<T: EdifactSerialize>(value: &T) -> Result<Vec<u8>, EdifactError> {
360 let mut buf = Vec::new();
361 to_writer(&mut buf, value)?;
362 Ok(buf)
363}
364
365pub fn to_edifact_string<T: EdifactSerialize>(value: &T) -> Result<String, EdifactError> {
374 let bytes = to_bytes(value)?;
375 String::from_utf8(bytes).map_err(|_| EdifactError::InvalidUtf8)
376}
377
378#[cfg(test)]
379mod tests {
380 use super::*;
381 use crate::event::{EdifactEvent, VecEmitter};
382 use std::borrow::Cow;
383
384 fn sparse_to_wire(parts: &mut [(usize, usize, Cow<'_, str>)], tag: &str) -> String {
387 let mut buf = Vec::new();
388 {
389 let mut emitter = crate::WriterEmitter::new(&mut buf);
390 emit_sparse_segment(&mut emitter, tag, parts).expect("emit");
391 emitter.finish().expect("finish");
392 }
393 String::from_utf8(buf).expect("utf-8")
394 }
395
396 #[test]
397 fn emit_sparse_segment_fills_gaps_in_elements_and_components() {
398 let mut parts = vec![
399 (1, 2, Cow::Borrowed("293")),
400 (0, 0, Cow::Borrowed("MS")),
401 (3, 1, Cow::Borrowed("late")),
402 ];
403 assert_eq!(sparse_to_wire(&mut parts, "NAD"), "NAD+MS+::293++:late'");
406 }
407
408 #[test]
409 fn emit_sparse_segment_first_value_wins_on_a_duplicate_slot() {
410 let mut parts = vec![
413 (0, 0, Cow::Borrowed("MS")),
414 (1, 0, Cow::Borrowed("first")),
415 (1, 0, Cow::Borrowed("second")),
416 (1, 2, Cow::Borrowed("293")),
417 ];
418 assert_eq!(sparse_to_wire(&mut parts, "NAD"), "NAD+MS+first::293'");
419 }
420
421 #[test]
422 fn emit_sparse_segment_with_no_parts_writes_a_bare_tag() {
423 assert_eq!(sparse_to_wire(&mut [], "UNS"), "UNS'");
424 }
425
426 struct BgmSegment {
427 doc_name_code: String,
428 pruef_id: String,
429 msg_function: Option<String>,
430 }
431
432 impl EdifactSerialize for BgmSegment {
433 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
434 emitter.emit(EdifactEvent::start("BGM"))?;
435 emitter.emit(EdifactEvent::element(&self.doc_name_code))?;
436 emitter.emit(EdifactEvent::element(&self.pruef_id))?;
437 self.msg_function.edifact_serialize(emitter)?;
438 emitter.emit(EdifactEvent::EndSegment)?;
439 Ok(())
440 }
441 }
442
443 #[test]
444 fn vec_emitter_captures_segment_events() {
445 let seg = BgmSegment {
446 doc_name_code: "E03".to_owned(),
447 pruef_id: "11042".to_owned(),
448 msg_function: None,
449 };
450 let mut emitter = VecEmitter::default();
451 seg.edifact_serialize(&mut emitter).unwrap();
452
453 assert_eq!(emitter.events[0], EdifactEvent::start("BGM".to_owned()));
454 assert_eq!(emitter.events.last(), Some(&EdifactEvent::EndSegment));
455 }
456
457 #[test]
458 fn to_bytes_produces_valid_edifact() {
459 let seg = BgmSegment {
460 doc_name_code: "E03".to_owned(),
461 pruef_id: "11042".to_owned(),
462 msg_function: Some("9".to_owned()),
463 };
464 let bytes = to_bytes(&seg).unwrap();
465 assert_eq!(std::str::from_utf8(&bytes).unwrap(), "BGM+E03+11042+9'");
466 }
467
468 #[test]
469 fn option_none_emits_empty_element() {
470 let val: Option<String> = None;
471 let mut emitter = VecEmitter::default();
472 val.edifact_serialize(&mut emitter).unwrap();
473 assert_eq!(emitter.events[0], EdifactEvent::element(String::new()));
474 }
475
476 #[test]
477 fn option_some_emits_value() {
478 let val: Option<String> = Some("TEST".to_owned());
479 let mut emitter = VecEmitter::default();
480 val.edifact_serialize(&mut emitter).unwrap();
481 assert_eq!(emitter.events[0], EdifactEvent::element("TEST".to_owned()));
482 }
483
484 #[test]
485 fn integer_types_serialize_without_alloc() {
486 let mut emitter = VecEmitter::default();
487 42u32.edifact_serialize(&mut emitter).unwrap();
488 assert_eq!(emitter.events[0], EdifactEvent::element("42".to_owned()));
489 let mut emitter2 = VecEmitter::default();
491 i128::MIN.edifact_serialize(&mut emitter2).unwrap();
492 assert_eq!(
493 emitter2.events[0],
494 EdifactEvent::element("-170141183460469231731687303715884105728".to_owned())
495 );
496 }
497
498 #[test]
499 fn float_extremes_do_not_panic() {
500 use super::DecimalFloat;
501 let mut emitter = VecEmitter::default();
503 DecimalFloat(f64::MAX)
504 .edifact_serialize(&mut emitter)
505 .unwrap();
506 let s = match &emitter.events[0] {
507 EdifactEvent::Element { value } => value.clone(),
508 _ => panic!("expected Element event"),
509 };
510 assert!(!s.is_empty());
511 let mut emitter2 = VecEmitter::default();
513 DecimalFloat(f32::MAX)
514 .edifact_serialize(&mut emitter2)
515 .unwrap();
516 assert!(matches!(&emitter2.events[0], EdifactEvent::Element { .. }));
517 }
518
519 #[test]
520 fn vec_serializes_each_item() {
521 let segments = vec![
522 BgmSegment {
523 doc_name_code: "E03".to_owned(),
524 pruef_id: "11042".to_owned(),
525 msg_function: None,
526 },
527 BgmSegment {
528 doc_name_code: "E01".to_owned(),
529 pruef_id: "11043".to_owned(),
530 msg_function: None,
531 },
532 ];
533 let bytes = to_bytes(&segments).unwrap();
534 let s = std::str::from_utf8(&bytes).unwrap();
535 assert!(s.contains("BGM+E03+11042"));
536 assert!(s.contains("BGM+E01+11043"));
537 }
538}