1use crate::EdifactError;
8use std::io::Write;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
14#[non_exhaustive]
15pub enum EdifactEvent<'a> {
16 StartSegment {
18 tag: &'a str,
20 },
21 Element {
23 value: &'a str,
25 },
26 ComponentElement {
28 value: &'a str,
30 },
31 RepeatElement {
45 value: &'a str,
47 },
48 EndSegment,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
54#[non_exhaustive]
55pub enum OwnedEdifactEvent {
56 StartSegment {
58 tag: String,
60 },
61 Element {
63 value: String,
65 },
66 ComponentElement {
68 value: String,
70 },
71 RepeatElement {
73 value: String,
75 },
76 EndSegment,
78}
79
80impl EdifactEvent<'_> {
81 pub fn into_owned(self) -> OwnedEdifactEvent {
83 match self {
84 Self::StartSegment { tag } => OwnedEdifactEvent::StartSegment {
85 tag: tag.to_owned(),
86 },
87 Self::Element { value } => OwnedEdifactEvent::Element {
88 value: value.to_owned(),
89 },
90 Self::ComponentElement { value } => OwnedEdifactEvent::ComponentElement {
91 value: value.to_owned(),
92 },
93 Self::RepeatElement { value } => OwnedEdifactEvent::RepeatElement {
94 value: value.to_owned(),
95 },
96 Self::EndSegment => OwnedEdifactEvent::EndSegment,
97 }
98 }
99}
100
101pub trait EventEmitter {
105 fn emit(&mut self, event: EdifactEvent<'_>) -> Result<(), EdifactError>;
107
108 #[inline]
118 fn decimal_mark(&self) -> u8 {
119 b'.'
120 }
121}
122
123#[derive(Debug, Default)]
129pub struct VecEmitter {
130 pub events: Vec<OwnedEdifactEvent>,
132}
133
134impl EventEmitter for VecEmitter {
135 fn emit(&mut self, event: EdifactEvent<'_>) -> Result<(), EdifactError> {
136 self.events.push(event.into_owned());
137 Ok(())
138 }
139}
140
141#[derive(Debug, Clone, Copy, PartialEq, Eq)]
145enum EmitterState {
146 Idle,
148 InSegment,
150 InElement,
152}
153
154pub struct WriterEmitter<W: Write> {
170 writer: crate::Writer<W>,
171 state: EmitterState,
172}
173
174impl<W: Write> WriterEmitter<W> {
175 pub fn new(inner: W) -> Self {
177 Self {
178 writer: crate::Writer::new(inner),
179 state: EmitterState::Idle,
180 }
181 }
182
183 pub fn with_una(
189 inner: W,
190 ssa: crate::tokenizer::ServiceStringAdvice,
191 ) -> Result<Self, crate::EdifactError> {
192 Ok(Self {
193 writer: crate::Writer::with_una(inner, ssa)?,
194 state: EmitterState::Idle,
195 })
196 }
197
198 #[must_use]
219 pub fn with_charset(mut self, charset: crate::Charset) -> Self {
220 self.writer = self.writer.with_charset(charset);
221 self
222 }
223
224 pub fn finish(self) -> Result<W, EdifactError> {
226 self.writer.finish()
227 }
228
229 pub fn segment_count(&self) -> u64 {
231 self.writer.segment_count()
232 }
233
234 pub fn service_string_advice(&self) -> crate::tokenizer::ServiceStringAdvice {
239 self.writer.service_string_advice()
240 }
241}
242
243impl<W: Write> EventEmitter for WriterEmitter<W> {
244 #[inline]
245 fn decimal_mark(&self) -> u8 {
246 self.writer.service_string_advice().decimal_mark
247 }
248
249 fn emit(&mut self, event: EdifactEvent<'_>) -> Result<(), EdifactError> {
250 match event {
251 EdifactEvent::StartSegment { tag } => {
252 if self.state != EmitterState::Idle {
253 return Err(EdifactError::InvalidEventSequence {
254 message: "StartSegment emitted while a segment is already open; emit EndSegment first",
255 });
256 }
257 self.state = EmitterState::InSegment;
258 self.writer.write_tag_only(tag)?;
259 }
260 EdifactEvent::Element { value } => {
261 if self.state == EmitterState::Idle {
262 return Err(EdifactError::InvalidEventSequence {
263 message: "Element emitted outside of a segment; emit StartSegment first",
264 });
265 }
266 self.state = EmitterState::InElement;
267 self.writer.write_element_sep()?;
268 self.writer.write_escaped(value)?;
269 }
270 EdifactEvent::ComponentElement { value } => {
271 if self.state != EmitterState::InElement {
272 return Err(EdifactError::InvalidEventSequence {
273 message: "ComponentElement emitted without a preceding Element in the same segment",
274 });
275 }
276 self.writer.write_component_sep()?;
277 self.writer.write_escaped(value)?;
278 }
279 EdifactEvent::RepeatElement { value } => {
280 if self.state != EmitterState::InElement {
281 return Err(EdifactError::InvalidEventSequence {
282 message: "RepeatElement emitted without a preceding Element in the same segment",
283 });
284 }
285 self.writer.write_repetition_sep()?;
288 self.writer.write_escaped(value)?;
289 }
290 EdifactEvent::EndSegment => {
291 if self.state == EmitterState::Idle {
292 return Err(EdifactError::InvalidEventSequence {
293 message: "EndSegment emitted while no segment is open; emit StartSegment first",
294 });
295 }
296 self.state = EmitterState::Idle;
297 self.writer.write_segment_term_and_count()?;
298 }
299 }
300 Ok(())
301 }
302}
303
304#[cfg(test)]
305mod tests {
306 use super::*;
307
308 #[test]
309 fn vec_emitter_no_memory_leak() {
310 let mut e = VecEmitter::default();
311 e.emit(EdifactEvent::StartSegment { tag: "BGM" }).unwrap();
312 e.emit(EdifactEvent::Element { value: "E03" }).unwrap();
313 e.emit(EdifactEvent::EndSegment).unwrap();
314 assert_eq!(
315 e.events[0],
316 OwnedEdifactEvent::StartSegment {
317 tag: "BGM".to_owned()
318 }
319 );
320 assert_eq!(
321 e.events[1],
322 OwnedEdifactEvent::Element {
323 value: "E03".to_owned()
324 }
325 );
326 }
327
328 #[test]
329 fn writer_emitter_produces_valid_edifact() {
330 let mut buf = Vec::new();
331 {
332 let mut e = WriterEmitter::new(&mut buf);
333 e.emit(EdifactEvent::StartSegment { tag: "BGM" }).unwrap();
334 e.emit(EdifactEvent::Element { value: "E03" }).unwrap();
335 e.emit(EdifactEvent::Element { value: "11042" }).unwrap();
336 e.emit(EdifactEvent::EndSegment).unwrap();
337 e.finish().unwrap();
338 }
339 assert_eq!(buf, b"BGM+E03+11042'");
340 }
341
342 #[test]
343 fn writer_emitter_handles_components() {
344 let mut buf = Vec::new();
345 {
346 let mut e = WriterEmitter::new(&mut buf);
347 e.emit(EdifactEvent::StartSegment { tag: "NAD" }).unwrap();
348 e.emit(EdifactEvent::Element { value: "MS" }).unwrap();
349 e.emit(EdifactEvent::Element {
350 value: "9900112233445",
351 })
352 .unwrap();
353 e.emit(EdifactEvent::ComponentElement { value: "" })
354 .unwrap();
355 e.emit(EdifactEvent::ComponentElement { value: "293" })
356 .unwrap();
357 e.emit(EdifactEvent::EndSegment).unwrap();
358 e.finish().unwrap();
359 }
360 let s = std::str::from_utf8(&buf).unwrap();
361 assert_eq!(s, "NAD+MS+9900112233445::293'");
362 }
363
364 #[test]
365 fn repetitions_round_trip_through_the_event_layer() {
366 let ssa = crate::ServiceStringAdvice::from_bytes(b"UNA:+.?*'").unwrap();
370 let mut buf = Vec::new();
371 {
372 let mut e = WriterEmitter::with_una(&mut buf, ssa).unwrap();
373 e.emit(EdifactEvent::StartSegment { tag: "RFF" }).unwrap();
374 e.emit(EdifactEvent::Element { value: "ON" }).unwrap();
375 e.emit(EdifactEvent::ComponentElement { value: "1" })
376 .unwrap();
377 e.emit(EdifactEvent::RepeatElement { value: "ON" }).unwrap();
378 e.emit(EdifactEvent::ComponentElement { value: "2" })
379 .unwrap();
380 e.emit(EdifactEvent::EndSegment).unwrap();
381 e.finish().unwrap();
382 }
383 assert_eq!(
384 std::str::from_utf8(&buf).unwrap(),
385 "UNA:+.?*'RFF+ON:1*ON:2'"
386 );
387
388 let segments: Vec<_> = crate::from_bytes(&buf)
389 .collect::<Result<Vec<_>, _>>()
390 .unwrap();
391 let element = segments[0].get_element(0).unwrap();
392 assert_eq!(element.repeat_count(), 2);
393 assert_eq!(element.repetition(1).unwrap()[1].0, "2");
394 }
395
396 #[test]
397 fn a_repetition_without_a_declared_separator_is_refused() {
398 let mut e = WriterEmitter::new(Vec::<u8>::new());
399 e.emit(EdifactEvent::StartSegment { tag: "RFF" }).unwrap();
400 e.emit(EdifactEvent::Element { value: "ON" }).unwrap();
401 let err = e
402 .emit(EdifactEvent::RepeatElement { value: "ON" })
403 .unwrap_err();
404 assert!(
405 matches!(err, EdifactError::RepetitionSeparatorNotDeclared),
406 "expected RepetitionSeparatorNotDeclared, got {err:?}"
407 );
408 }
409
410 #[test]
411 fn a_repetition_before_any_element_is_refused() {
412 let ssa = crate::ServiceStringAdvice::from_bytes(b"UNA:+.?*'").unwrap();
413 let mut e = WriterEmitter::with_una(Vec::<u8>::new(), ssa).unwrap();
414 e.emit(EdifactEvent::StartSegment { tag: "RFF" }).unwrap();
415 let err = e
416 .emit(EdifactEvent::RepeatElement { value: "ON" })
417 .unwrap_err();
418 assert!(
419 matches!(err, EdifactError::InvalidEventSequence { .. }),
420 "expected InvalidEventSequence, got {err:?}"
421 );
422 }
423
424 #[test]
427 fn writer_emitter_element_before_start_segment_is_err() {
428 let mut e = WriterEmitter::new(Vec::<u8>::new());
429 let err = e.emit(EdifactEvent::Element { value: "X" }).unwrap_err();
430 assert!(
431 matches!(err, crate::EdifactError::InvalidEventSequence { .. }),
432 "expected InvalidEventSequence, got {err:?}"
433 );
434 }
435
436 #[test]
437 fn writer_emitter_component_before_element_is_err() {
438 let mut e = WriterEmitter::new(Vec::<u8>::new());
439 e.emit(EdifactEvent::StartSegment { tag: "BGM" }).unwrap();
440 let err = e
441 .emit(EdifactEvent::ComponentElement { value: "X" })
442 .unwrap_err();
443 assert!(
444 matches!(err, crate::EdifactError::InvalidEventSequence { .. }),
445 "expected InvalidEventSequence, got {err:?}"
446 );
447 }
448
449 #[test]
450 fn writer_emitter_double_start_segment_is_err() {
451 let mut e = WriterEmitter::new(Vec::<u8>::new());
452 e.emit(EdifactEvent::StartSegment { tag: "BGM" }).unwrap();
453 let err = e
454 .emit(EdifactEvent::StartSegment { tag: "DTM" })
455 .unwrap_err();
456 assert!(
457 matches!(err, crate::EdifactError::InvalidEventSequence { .. }),
458 "expected InvalidEventSequence, got {err:?}"
459 );
460 }
461
462 #[test]
463 fn writer_emitter_end_segment_without_start_is_err() {
464 let mut e = WriterEmitter::new(Vec::<u8>::new());
465 let err = e.emit(EdifactEvent::EndSegment).unwrap_err();
466 assert!(
467 matches!(err, crate::EdifactError::InvalidEventSequence { .. }),
468 "expected InvalidEventSequence, got {err:?}"
469 );
470 }
471}