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
203impl EdifactSerialize for DecimalFloat<f32> {
204 #[inline]
205 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
206 serialize_with_decimal_mark(&self.0, emitter)
207 }
208}
209
210impl EdifactSerialize for DecimalFloat<f64> {
211 #[inline]
212 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
213 serialize_with_decimal_mark(&self.0, emitter)
214 }
215}
216
217impl<T: std::fmt::Display> EdifactSerialize for DecimalFloatDisplay<T> {
218 #[inline]
219 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
220 serialize_with_decimal_mark(&self.0, emitter)
221 }
222}
223
224pub fn to_writer<T, W>(inner: W, value: &T) -> Result<(), EdifactError>
226where
227 T: EdifactSerialize,
228 W: Write,
229{
230 let mut emitter = WriterEmitter::new(inner);
231 value.edifact_serialize(&mut emitter)?;
232 emitter.finish().map(|_| ())
233}
234
235pub fn to_bytes<T: EdifactSerialize>(value: &T) -> Result<Vec<u8>, EdifactError> {
237 let mut buf = Vec::new();
238 to_writer(&mut buf, value)?;
239 Ok(buf)
240}
241
242pub fn to_edifact_string<T: EdifactSerialize>(value: &T) -> Result<String, EdifactError> {
251 let bytes = to_bytes(value)?;
252 String::from_utf8(bytes).map_err(|_| EdifactError::InvalidUtf8)
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258 use crate::event::{OwnedEdifactEvent, VecEmitter};
259
260 struct BgmSegment {
261 doc_name_code: String,
262 pruef_id: String,
263 msg_function: Option<String>,
264 }
265
266 impl EdifactSerialize for BgmSegment {
267 fn edifact_serialize<E: EventEmitter>(&self, emitter: &mut E) -> Result<(), EdifactError> {
268 emitter.emit(EdifactEvent::StartSegment { tag: "BGM" })?;
269 emitter.emit(EdifactEvent::Element {
270 value: &self.doc_name_code,
271 })?;
272 emitter.emit(EdifactEvent::Element {
273 value: &self.pruef_id,
274 })?;
275 self.msg_function.edifact_serialize(emitter)?;
276 emitter.emit(EdifactEvent::EndSegment)?;
277 Ok(())
278 }
279 }
280
281 #[test]
282 fn vec_emitter_captures_segment_events() {
283 let seg = BgmSegment {
284 doc_name_code: "E03".to_owned(),
285 pruef_id: "11042".to_owned(),
286 msg_function: None,
287 };
288 let mut emitter = VecEmitter::default();
289 seg.edifact_serialize(&mut emitter).unwrap();
290
291 assert_eq!(
292 emitter.events[0],
293 OwnedEdifactEvent::StartSegment {
294 tag: "BGM".to_owned()
295 }
296 );
297 assert_eq!(emitter.events.last(), Some(&OwnedEdifactEvent::EndSegment));
298 }
299
300 #[test]
301 fn to_bytes_produces_valid_edifact() {
302 let seg = BgmSegment {
303 doc_name_code: "E03".to_owned(),
304 pruef_id: "11042".to_owned(),
305 msg_function: Some("9".to_owned()),
306 };
307 let bytes = to_bytes(&seg).unwrap();
308 assert_eq!(std::str::from_utf8(&bytes).unwrap(), "BGM+E03+11042+9'");
309 }
310
311 #[test]
312 fn option_none_emits_empty_element() {
313 let val: Option<String> = None;
314 let mut emitter = VecEmitter::default();
315 val.edifact_serialize(&mut emitter).unwrap();
316 assert_eq!(
317 emitter.events[0],
318 OwnedEdifactEvent::Element {
319 value: String::new()
320 }
321 );
322 }
323
324 #[test]
325 fn option_some_emits_value() {
326 let val: Option<String> = Some("TEST".to_owned());
327 let mut emitter = VecEmitter::default();
328 val.edifact_serialize(&mut emitter).unwrap();
329 assert_eq!(
330 emitter.events[0],
331 OwnedEdifactEvent::Element {
332 value: "TEST".to_owned()
333 }
334 );
335 }
336
337 #[test]
338 fn integer_types_serialize_without_alloc() {
339 let mut emitter = VecEmitter::default();
340 42u32.edifact_serialize(&mut emitter).unwrap();
341 assert_eq!(
342 emitter.events[0],
343 OwnedEdifactEvent::Element {
344 value: "42".to_owned()
345 }
346 );
347 let mut emitter2 = VecEmitter::default();
349 i128::MIN.edifact_serialize(&mut emitter2).unwrap();
350 assert_eq!(
351 emitter2.events[0],
352 OwnedEdifactEvent::Element {
353 value: "-170141183460469231731687303715884105728".to_owned()
354 }
355 );
356 }
357
358 #[test]
359 fn float_extremes_do_not_panic() {
360 use super::DecimalFloat;
361 let mut emitter = VecEmitter::default();
363 DecimalFloat(f64::MAX)
364 .edifact_serialize(&mut emitter)
365 .unwrap();
366 let s = match &emitter.events[0] {
367 OwnedEdifactEvent::Element { value } => value.clone(),
368 _ => panic!("expected Element event"),
369 };
370 assert!(!s.is_empty());
371 let mut emitter2 = VecEmitter::default();
373 DecimalFloat(f32::MAX)
374 .edifact_serialize(&mut emitter2)
375 .unwrap();
376 assert!(matches!(
377 &emitter2.events[0],
378 OwnedEdifactEvent::Element { .. }
379 ));
380 }
381
382 #[test]
383 fn vec_serializes_each_item() {
384 let segments = vec![
385 BgmSegment {
386 doc_name_code: "E03".to_owned(),
387 pruef_id: "11042".to_owned(),
388 msg_function: None,
389 },
390 BgmSegment {
391 doc_name_code: "E01".to_owned(),
392 pruef_id: "11043".to_owned(),
393 msg_function: None,
394 },
395 ];
396 let bytes = to_bytes(&segments).unwrap();
397 let s = std::str::from_utf8(&bytes).unwrap();
398 assert!(s.contains("BGM+E03+11042"));
399 assert!(s.contains("BGM+E01+11043"));
400 }
401}