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
129#[derive(Debug, Clone, Copy, PartialEq)]
158pub struct DecimalFloat<T>(pub T);
159
160#[derive(Debug, Clone, Copy, PartialEq)]
165pub struct DecimalFloatDisplay<T: std::fmt::Display>(pub T);
166
167fn serialize_with_decimal_mark<E: EventEmitter>(
168 display: &dyn std::fmt::Display,
169 emitter: &mut E,
170) -> Result<(), EdifactError> {
171 use std::io::Write as _;
172 let mark = emitter.decimal_mark();
173
174 if mark == b'.' {
176 let mut buf = [0u8; 320];
177 let mut w: &mut [u8] = &mut buf;
178 if write!(w, "{display}").is_ok() {
179 let written = 320 - w.len();
180 let s = std::str::from_utf8(&buf[..written]).map_err(|_| EdifactError::InvalidUtf8)?;
182 return emitter.emit(EdifactEvent::Element { value: s });
183 }
184 let s = format!("{display}");
186 return emitter.emit(EdifactEvent::Element { value: &s });
187 }
188
189 let s = format!("{display}");
192 if s.contains('.') {
193 let mut mark_buf = [0u8; 4];
195 let mark_str = (mark as char).encode_utf8(&mut mark_buf);
196 let replaced = s.replace('.', mark_str);
197 emitter.emit(EdifactEvent::Element { value: &replaced })
198 } else {
199 emitter.emit(EdifactEvent::Element { value: &s })
200 }
201}
202
203#[inline]
211fn reject_non_finite(value: f64) -> Result<(), EdifactError> {
212 if value.is_finite() {
213 return Ok(());
214 }
215 Err(EdifactError::NonFiniteNumber {
216 value: value.to_string(),
217 })
218}
219
220impl EdifactSerialize for DecimalFloat<f32> {
221 #[inline]
222 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
223 reject_non_finite(f64::from(self.0))?;
224 serialize_with_decimal_mark(&self.0, emitter)
225 }
226}
227
228impl EdifactSerialize for DecimalFloat<f64> {
229 #[inline]
230 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
231 reject_non_finite(self.0)?;
232 serialize_with_decimal_mark(&self.0, emitter)
233 }
234}
235
236impl<T: std::fmt::Display> EdifactSerialize for DecimalFloatDisplay<T> {
237 #[inline]
238 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
239 serialize_with_decimal_mark(&self.0, emitter)
240 }
241}
242
243pub fn emit_sparse_segment<E: EventEmitter>(
287 emitter: &mut E,
288 tag: &str,
289 parts: &mut [(usize, usize, std::borrow::Cow<'_, str>)],
290) -> Result<(), EdifactError> {
291 parts.sort_by_key(|(element, component, _)| (*element, *component));
292
293 emitter.emit(EdifactEvent::StartSegment { tag })?;
294
295 let mut cursor = 0usize;
298 let element_count = parts.last().map_or(0, |(element, _, _)| *element + 1);
299 for element in 0..element_count {
300 let mut next_component = 0usize;
302 let mut opened = false;
303 while cursor < parts.len() && parts[cursor].0 == element {
304 let (_, component, value) = &parts[cursor];
305 if *component < next_component {
306 cursor += 1;
309 continue;
310 }
311 while next_component < *component {
313 let event = if opened {
314 EdifactEvent::ComponentElement { value: "" }
315 } else {
316 EdifactEvent::Element { value: "" }
317 };
318 emitter.emit(event)?;
319 opened = true;
320 next_component += 1;
321 }
322 let event = if opened {
323 EdifactEvent::ComponentElement { value }
324 } else {
325 EdifactEvent::Element { value }
326 };
327 emitter.emit(event)?;
328 opened = true;
329 next_component += 1;
330 cursor += 1;
331 }
332 if !opened {
333 emitter.emit(EdifactEvent::Element { value: "" })?;
336 }
337 }
338
339 emitter.emit(EdifactEvent::EndSegment)
340}
341
342pub fn to_writer<T, W>(inner: W, value: &T) -> Result<(), EdifactError>
344where
345 T: EdifactSerialize,
346 W: Write,
347{
348 let mut emitter = WriterEmitter::new(inner);
349 value.edifact_serialize(&mut emitter)?;
350 emitter.finish().map(|_| ())
351}
352
353pub fn to_bytes<T: EdifactSerialize>(value: &T) -> Result<Vec<u8>, EdifactError> {
355 let mut buf = Vec::new();
356 to_writer(&mut buf, value)?;
357 Ok(buf)
358}
359
360pub fn to_edifact_string<T: EdifactSerialize>(value: &T) -> Result<String, EdifactError> {
369 let bytes = to_bytes(value)?;
370 String::from_utf8(bytes).map_err(|_| EdifactError::InvalidUtf8)
371}
372
373#[cfg(test)]
374mod tests {
375 use super::*;
376 use crate::event::{OwnedEdifactEvent, VecEmitter};
377 use std::borrow::Cow;
378
379 fn sparse_to_wire(parts: &mut [(usize, usize, Cow<'_, str>)], tag: &str) -> String {
382 let mut buf = Vec::new();
383 {
384 let mut emitter = crate::WriterEmitter::new(&mut buf);
385 emit_sparse_segment(&mut emitter, tag, parts).expect("emit");
386 emitter.finish().expect("finish");
387 }
388 String::from_utf8(buf).expect("utf-8")
389 }
390
391 #[test]
392 fn emit_sparse_segment_fills_gaps_in_elements_and_components() {
393 let mut parts = vec![
394 (1, 2, Cow::Borrowed("293")),
395 (0, 0, Cow::Borrowed("MS")),
396 (3, 1, Cow::Borrowed("late")),
397 ];
398 assert_eq!(sparse_to_wire(&mut parts, "NAD"), "NAD+MS+::293++:late'");
401 }
402
403 #[test]
404 fn emit_sparse_segment_first_value_wins_on_a_duplicate_slot() {
405 let mut parts = vec![
408 (0, 0, Cow::Borrowed("MS")),
409 (1, 0, Cow::Borrowed("first")),
410 (1, 0, Cow::Borrowed("second")),
411 (1, 2, Cow::Borrowed("293")),
412 ];
413 assert_eq!(sparse_to_wire(&mut parts, "NAD"), "NAD+MS+first::293'");
414 }
415
416 #[test]
417 fn emit_sparse_segment_with_no_parts_writes_a_bare_tag() {
418 assert_eq!(sparse_to_wire(&mut [], "UNS"), "UNS'");
419 }
420
421 struct BgmSegment {
422 doc_name_code: String,
423 pruef_id: String,
424 msg_function: Option<String>,
425 }
426
427 impl EdifactSerialize for BgmSegment {
428 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
429 emitter.emit(EdifactEvent::StartSegment { tag: "BGM" })?;
430 emitter.emit(EdifactEvent::Element {
431 value: &self.doc_name_code,
432 })?;
433 emitter.emit(EdifactEvent::Element {
434 value: &self.pruef_id,
435 })?;
436 self.msg_function.edifact_serialize(emitter)?;
437 emitter.emit(EdifactEvent::EndSegment)?;
438 Ok(())
439 }
440 }
441
442 #[test]
443 fn vec_emitter_captures_segment_events() {
444 let seg = BgmSegment {
445 doc_name_code: "E03".to_owned(),
446 pruef_id: "11042".to_owned(),
447 msg_function: None,
448 };
449 let mut emitter = VecEmitter::default();
450 seg.edifact_serialize(&mut emitter).unwrap();
451
452 assert_eq!(
453 emitter.events[0],
454 OwnedEdifactEvent::StartSegment {
455 tag: "BGM".to_owned()
456 }
457 );
458 assert_eq!(emitter.events.last(), Some(&OwnedEdifactEvent::EndSegment));
459 }
460
461 #[test]
462 fn to_bytes_produces_valid_edifact() {
463 let seg = BgmSegment {
464 doc_name_code: "E03".to_owned(),
465 pruef_id: "11042".to_owned(),
466 msg_function: Some("9".to_owned()),
467 };
468 let bytes = to_bytes(&seg).unwrap();
469 assert_eq!(std::str::from_utf8(&bytes).unwrap(), "BGM+E03+11042+9'");
470 }
471
472 #[test]
473 fn option_none_emits_empty_element() {
474 let val: Option<String> = None;
475 let mut emitter = VecEmitter::default();
476 val.edifact_serialize(&mut emitter).unwrap();
477 assert_eq!(
478 emitter.events[0],
479 OwnedEdifactEvent::Element {
480 value: String::new()
481 }
482 );
483 }
484
485 #[test]
486 fn option_some_emits_value() {
487 let val: Option<String> = Some("TEST".to_owned());
488 let mut emitter = VecEmitter::default();
489 val.edifact_serialize(&mut emitter).unwrap();
490 assert_eq!(
491 emitter.events[0],
492 OwnedEdifactEvent::Element {
493 value: "TEST".to_owned()
494 }
495 );
496 }
497
498 #[test]
499 fn integer_types_serialize_without_alloc() {
500 let mut emitter = VecEmitter::default();
501 42u32.edifact_serialize(&mut emitter).unwrap();
502 assert_eq!(
503 emitter.events[0],
504 OwnedEdifactEvent::Element {
505 value: "42".to_owned()
506 }
507 );
508 let mut emitter2 = VecEmitter::default();
510 i128::MIN.edifact_serialize(&mut emitter2).unwrap();
511 assert_eq!(
512 emitter2.events[0],
513 OwnedEdifactEvent::Element {
514 value: "-170141183460469231731687303715884105728".to_owned()
515 }
516 );
517 }
518
519 #[test]
520 fn float_extremes_do_not_panic() {
521 use super::DecimalFloat;
522 let mut emitter = VecEmitter::default();
524 DecimalFloat(f64::MAX)
525 .edifact_serialize(&mut emitter)
526 .unwrap();
527 let s = match &emitter.events[0] {
528 OwnedEdifactEvent::Element { value } => value.clone(),
529 _ => panic!("expected Element event"),
530 };
531 assert!(!s.is_empty());
532 let mut emitter2 = VecEmitter::default();
534 DecimalFloat(f32::MAX)
535 .edifact_serialize(&mut emitter2)
536 .unwrap();
537 assert!(matches!(
538 &emitter2.events[0],
539 OwnedEdifactEvent::Element { .. }
540 ));
541 }
542
543 #[test]
544 fn vec_serializes_each_item() {
545 let segments = vec![
546 BgmSegment {
547 doc_name_code: "E03".to_owned(),
548 pruef_id: "11042".to_owned(),
549 msg_function: None,
550 },
551 BgmSegment {
552 doc_name_code: "E01".to_owned(),
553 pruef_id: "11043".to_owned(),
554 msg_function: None,
555 },
556 ];
557 let bytes = to_bytes(&segments).unwrap();
558 let s = std::str::from_utf8(&bytes).unwrap();
559 assert!(s.contains("BGM+E03+11042"));
560 assert!(s.contains("BGM+E01+11043"));
561 }
562}