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 {
141 ($($t:ty),+ $(,)?) => {
142 $(
143 impl EdifactSerialize for $t {
144 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
145 use std::io::Write as _;
146 let mut buf = [0u8; 320];
147 let mut w: &mut [u8] = &mut buf;
148 if write!(w, "{self}").is_ok() {
149 let written = 320 - w.len();
150 let s = std::str::from_utf8(&buf[..written]).map_err(|_| EdifactError::InvalidUtf8)?;
152 emitter.emit(EdifactEvent::Element { value: s })
153 } else {
154 let s = format!("{self}");
156 emitter.emit(EdifactEvent::Element { value: &s })
157 }
158 }
159 }
160 )+
161 };
162}
163
164impl_serialize_float!(f32, f64);
165
166#[derive(Debug, Clone, Copy, PartialEq)]
194pub struct DecimalFloat<T>(pub T);
195
196#[derive(Debug, Clone, Copy, PartialEq)]
201pub struct DecimalFloatDisplay<T: std::fmt::Display>(pub T);
202
203fn serialize_with_decimal_mark<E: EventEmitter>(
204 display: &dyn std::fmt::Display,
205 emitter: &mut E,
206) -> Result<(), EdifactError> {
207 use std::io::Write as _;
208 let mark = emitter.decimal_mark();
209
210 if mark == b'.' {
212 let mut buf = [0u8; 320];
213 let mut w: &mut [u8] = &mut buf;
214 if write!(w, "{display}").is_ok() {
215 let written = 320 - w.len();
216 let s = std::str::from_utf8(&buf[..written]).map_err(|_| EdifactError::InvalidUtf8)?;
218 return emitter.emit(EdifactEvent::Element { value: s });
219 }
220 let s = format!("{display}");
222 return emitter.emit(EdifactEvent::Element { value: &s });
223 }
224
225 let s = format!("{display}");
228 let mark_char = mark as char;
229 if s.contains('.') {
230 let replaced = s.replace('.', &mark_char.to_string());
231 emitter.emit(EdifactEvent::Element { value: &replaced })
232 } else {
233 emitter.emit(EdifactEvent::Element { value: &s })
234 }
235}
236
237impl EdifactSerialize for DecimalFloat<f32> {
238 #[inline]
239 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
240 serialize_with_decimal_mark(&self.0, emitter)
241 }
242}
243
244impl EdifactSerialize for DecimalFloat<f64> {
245 #[inline]
246 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
247 serialize_with_decimal_mark(&self.0, emitter)
248 }
249}
250
251impl<T: std::fmt::Display> EdifactSerialize for DecimalFloatDisplay<T> {
252 #[inline]
253 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
254 serialize_with_decimal_mark(&self.0, emitter)
255 }
256}
257
258pub fn to_writer<T, W>(inner: W, value: &T) -> Result<(), EdifactError>
260where
261 T: EdifactSerialize,
262 W: Write,
263{
264 let mut emitter = WriterEmitter::new(inner);
265 value.edifact_serialize(&mut emitter)?;
266 emitter.finish().map(|_| ())
267}
268
269pub fn to_bytes<T: EdifactSerialize>(value: &T) -> Result<Vec<u8>, EdifactError> {
271 let mut buf = Vec::new();
272 to_writer(&mut buf, value)?;
273 Ok(buf)
274}
275
276pub fn to_edifact_string<T: EdifactSerialize>(value: &T) -> Result<String, EdifactError> {
285 let bytes = to_bytes(value)?;
286 String::from_utf8(bytes).map_err(|_| EdifactError::InvalidUtf8)
287}
288
289#[cfg(test)]
290mod tests {
291 use super::*;
292 use crate::event::{OwnedEdifactEvent, VecEmitter};
293
294 struct BgmSegment {
295 doc_name_code: String,
296 pruef_id: String,
297 msg_function: Option<String>,
298 }
299
300 impl EdifactSerialize for BgmSegment {
301 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
302 emitter.emit(EdifactEvent::StartSegment { tag: "BGM" })?;
303 emitter.emit(EdifactEvent::Element {
304 value: &self.doc_name_code,
305 })?;
306 emitter.emit(EdifactEvent::Element {
307 value: &self.pruef_id,
308 })?;
309 self.msg_function.edifact_serialize(emitter)?;
310 emitter.emit(EdifactEvent::EndSegment)?;
311 Ok(())
312 }
313 }
314
315 #[test]
316 fn vec_emitter_captures_segment_events() {
317 let seg = BgmSegment {
318 doc_name_code: "E03".to_owned(),
319 pruef_id: "11042".to_owned(),
320 msg_function: None,
321 };
322 let mut emitter = VecEmitter::default();
323 seg.edifact_serialize(&mut emitter).unwrap();
324
325 assert_eq!(
326 emitter.events[0],
327 OwnedEdifactEvent::StartSegment {
328 tag: "BGM".to_owned()
329 }
330 );
331 assert_eq!(emitter.events.last(), Some(&OwnedEdifactEvent::EndSegment));
332 }
333
334 #[test]
335 fn to_bytes_produces_valid_edifact() {
336 let seg = BgmSegment {
337 doc_name_code: "E03".to_owned(),
338 pruef_id: "11042".to_owned(),
339 msg_function: Some("9".to_owned()),
340 };
341 let bytes = to_bytes(&seg).unwrap();
342 assert_eq!(std::str::from_utf8(&bytes).unwrap(), "BGM+E03+11042+9'");
343 }
344
345 #[test]
346 fn option_none_emits_empty_element() {
347 let val: Option<String> = None;
348 let mut emitter = VecEmitter::default();
349 val.edifact_serialize(&mut emitter).unwrap();
350 assert_eq!(
351 emitter.events[0],
352 OwnedEdifactEvent::Element {
353 value: String::new()
354 }
355 );
356 }
357
358 #[test]
359 fn option_some_emits_value() {
360 let val: Option<String> = Some("TEST".to_owned());
361 let mut emitter = VecEmitter::default();
362 val.edifact_serialize(&mut emitter).unwrap();
363 assert_eq!(
364 emitter.events[0],
365 OwnedEdifactEvent::Element {
366 value: "TEST".to_owned()
367 }
368 );
369 }
370
371 #[test]
372 fn integer_types_serialize_without_alloc() {
373 let mut emitter = VecEmitter::default();
374 42u32.edifact_serialize(&mut emitter).unwrap();
375 assert_eq!(
376 emitter.events[0],
377 OwnedEdifactEvent::Element {
378 value: "42".to_owned()
379 }
380 );
381 let mut emitter2 = VecEmitter::default();
383 i128::MIN.edifact_serialize(&mut emitter2).unwrap();
384 assert_eq!(
385 emitter2.events[0],
386 OwnedEdifactEvent::Element {
387 value: "-170141183460469231731687303715884105728".to_owned()
388 }
389 );
390 }
391
392 #[test]
393 fn float_extremes_do_not_panic() {
394 let mut emitter = VecEmitter::default();
396 f64::MAX.edifact_serialize(&mut emitter).unwrap();
397 let s = match &emitter.events[0] {
398 OwnedEdifactEvent::Element { value } => value.clone(),
399 _ => panic!("expected Element event"),
400 };
401 assert!(!s.is_empty());
402 let mut emitter2 = VecEmitter::default();
404 f32::MAX.edifact_serialize(&mut emitter2).unwrap();
405 assert!(matches!(
406 &emitter2.events[0],
407 OwnedEdifactEvent::Element { .. }
408 ));
409 }
410
411 #[test]
412 fn vec_serializes_each_item() {
413 let segments = vec![
414 BgmSegment {
415 doc_name_code: "E03".to_owned(),
416 pruef_id: "11042".to_owned(),
417 msg_function: None,
418 },
419 BgmSegment {
420 doc_name_code: "E01".to_owned(),
421 pruef_id: "11043".to_owned(),
422 msg_function: None,
423 },
424 ];
425 let bytes = to_bytes(&segments).unwrap();
426 let s = std::str::from_utf8(&bytes).unwrap();
427 assert!(s.contains("BGM+E03+11042"));
428 assert!(s.contains("BGM+E01+11043"));
429 }
430}