1use crate::EdifactError;
9use std::borrow::Cow;
10use std::io::Write;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
16#[non_exhaustive]
17pub enum EdifactEvent<'a> {
18 StartSegment {
20 tag: Cow<'a, str>,
22 },
23 Element {
25 value: Cow<'a, str>,
27 },
28 ComponentElement {
30 value: Cow<'a, str>,
32 },
33 RepeatElement {
47 value: Cow<'a, str>,
49 },
50 EndSegment,
52}
53
54impl<'a> EdifactEvent<'a> {
55 #[inline]
57 #[must_use]
58 pub fn start(tag: impl Into<Cow<'a, str>>) -> Self {
59 Self::StartSegment { tag: tag.into() }
60 }
61
62 #[inline]
64 #[must_use]
65 pub fn element(value: impl Into<Cow<'a, str>>) -> Self {
66 Self::Element {
67 value: value.into(),
68 }
69 }
70
71 #[inline]
73 #[must_use]
74 pub fn component(value: impl Into<Cow<'a, str>>) -> Self {
75 Self::ComponentElement {
76 value: value.into(),
77 }
78 }
79
80 #[inline]
82 #[must_use]
83 pub fn repeat(value: impl Into<Cow<'a, str>>) -> Self {
84 Self::RepeatElement {
85 value: value.into(),
86 }
87 }
88}
89
90impl EdifactEvent<'_> {
91 #[must_use]
93 pub fn into_owned(self) -> EdifactEvent<'static> {
94 match self {
95 Self::StartSegment { tag } => EdifactEvent::start(Cow::Owned(tag.into_owned())),
96 Self::Element { value } => EdifactEvent::element(Cow::Owned(value.into_owned())),
97 Self::ComponentElement { value } => {
98 EdifactEvent::component(Cow::Owned(value.into_owned()))
99 }
100 Self::RepeatElement { value } => EdifactEvent::repeat(Cow::Owned(value.into_owned())),
101 Self::EndSegment => EdifactEvent::EndSegment,
102 }
103 }
104}
105
106pub trait EventEmitter {
110 fn emit(&mut self, event: EdifactEvent<'_>) -> Result<(), EdifactError>;
112
113 #[inline]
123 fn decimal_mark(&self) -> u8 {
124 b'.'
125 }
126}
127
128#[derive(Debug, Default)]
134pub struct VecEmitter {
135 pub events: Vec<EdifactEvent<'static>>,
137}
138
139impl EventEmitter for VecEmitter {
140 fn emit(&mut self, event: EdifactEvent<'_>) -> Result<(), EdifactError> {
141 self.events.push(event.into_owned());
142 Ok(())
143 }
144}
145
146#[derive(Debug, Clone, Copy, PartialEq, Eq)]
150enum EmitterState {
151 Idle,
153 InSegment,
155 InElement,
157}
158
159pub struct WriterEmitter<W: Write> {
175 writer: crate::Writer<W>,
176 state: EmitterState,
177}
178
179impl<W: Write> WriterEmitter<W> {
180 pub fn new(inner: W) -> Self {
182 Self {
183 writer: crate::Writer::new(inner),
184 state: EmitterState::Idle,
185 }
186 }
187
188 pub fn with_una(
194 inner: W,
195 ssa: crate::tokenizer::ServiceStringAdvice,
196 ) -> Result<Self, crate::EdifactError> {
197 Ok(Self {
198 writer: crate::Writer::with_una(inner, ssa)?,
199 state: EmitterState::Idle,
200 })
201 }
202
203 #[must_use]
224 pub fn with_charset(mut self, charset: crate::Charset) -> Self {
225 self.writer = self.writer.with_charset(charset);
226 self
227 }
228
229 pub fn finish(self) -> Result<W, EdifactError> {
231 self.writer.finish()
232 }
233
234 pub fn segment_count(&self) -> u64 {
236 self.writer.segment_count()
237 }
238
239 pub fn service_string_advice(&self) -> crate::tokenizer::ServiceStringAdvice {
244 self.writer.service_string_advice()
245 }
246}
247
248impl<W: Write> EventEmitter for WriterEmitter<W> {
249 #[inline]
250 fn decimal_mark(&self) -> u8 {
251 self.writer.service_string_advice().decimal_mark
252 }
253
254 fn emit(&mut self, event: EdifactEvent<'_>) -> Result<(), EdifactError> {
255 match event {
256 EdifactEvent::StartSegment { tag } => {
257 if self.state != EmitterState::Idle {
258 return Err(EdifactError::InvalidEventSequence {
259 message: "StartSegment emitted while a segment is already open; emit EndSegment first",
260 });
261 }
262 self.state = EmitterState::InSegment;
263 self.writer.write_tag_only(&tag)?;
264 }
265 EdifactEvent::Element { value } => {
266 if self.state == EmitterState::Idle {
267 return Err(EdifactError::InvalidEventSequence {
268 message: "Element emitted outside of a segment; emit StartSegment first",
269 });
270 }
271 self.state = EmitterState::InElement;
272 self.writer.write_element_sep()?;
273 self.writer.write_escaped(&value)?;
274 }
275 EdifactEvent::ComponentElement { value } => {
276 if self.state != EmitterState::InElement {
277 return Err(EdifactError::InvalidEventSequence {
278 message: "ComponentElement emitted without a preceding Element in the same segment",
279 });
280 }
281 self.writer.write_component_sep()?;
282 self.writer.write_escaped(&value)?;
283 }
284 EdifactEvent::RepeatElement { value } => {
285 if self.state != EmitterState::InElement {
286 return Err(EdifactError::InvalidEventSequence {
287 message: "RepeatElement emitted without a preceding Element in the same segment",
288 });
289 }
290 self.writer.write_repetition_sep()?;
293 self.writer.write_escaped(&value)?;
294 }
295 EdifactEvent::EndSegment => {
296 if self.state == EmitterState::Idle {
297 return Err(EdifactError::InvalidEventSequence {
298 message: "EndSegment emitted while no segment is open; emit StartSegment first",
299 });
300 }
301 self.state = EmitterState::Idle;
302 self.writer.write_segment_term_and_count()?;
303 }
304 }
305 Ok(())
306 }
307}
308
309#[cfg(test)]
310mod tests {
311 use super::*;
312
313 #[test]
314 fn vec_emitter_no_memory_leak() {
315 let mut e = VecEmitter::default();
316 e.emit(EdifactEvent::start("BGM")).unwrap();
317 e.emit(EdifactEvent::element("E03")).unwrap();
318 e.emit(EdifactEvent::EndSegment).unwrap();
319 assert_eq!(e.events[0], EdifactEvent::start("BGM".to_owned()));
320 assert_eq!(e.events[1], EdifactEvent::element("E03".to_owned()));
321 }
322
323 #[test]
324 fn writer_emitter_produces_valid_edifact() {
325 let mut buf = Vec::new();
326 {
327 let mut e = WriterEmitter::new(&mut buf);
328 e.emit(EdifactEvent::start("BGM")).unwrap();
329 e.emit(EdifactEvent::element("E03")).unwrap();
330 e.emit(EdifactEvent::element("11042")).unwrap();
331 e.emit(EdifactEvent::EndSegment).unwrap();
332 e.finish().unwrap();
333 }
334 assert_eq!(buf, b"BGM+E03+11042'");
335 }
336
337 #[test]
338 fn writer_emitter_handles_components() {
339 let mut buf = Vec::new();
340 {
341 let mut e = WriterEmitter::new(&mut buf);
342 e.emit(EdifactEvent::start("NAD")).unwrap();
343 e.emit(EdifactEvent::element("MS")).unwrap();
344 e.emit(EdifactEvent::element("9900112233445")).unwrap();
345 e.emit(EdifactEvent::component("")).unwrap();
346 e.emit(EdifactEvent::component("293")).unwrap();
347 e.emit(EdifactEvent::EndSegment).unwrap();
348 e.finish().unwrap();
349 }
350 let s = std::str::from_utf8(&buf).unwrap();
351 assert_eq!(s, "NAD+MS+9900112233445::293'");
352 }
353
354 #[test]
355 fn repetitions_round_trip_through_the_event_layer() {
356 let ssa = crate::ServiceStringAdvice::from_bytes(b"UNA:+.?*'").unwrap();
360 let mut buf = Vec::new();
361 {
362 let mut e = WriterEmitter::with_una(&mut buf, ssa).unwrap();
363 e.emit(EdifactEvent::start("RFF")).unwrap();
364 e.emit(EdifactEvent::element("ON")).unwrap();
365 e.emit(EdifactEvent::component("1")).unwrap();
366 e.emit(EdifactEvent::repeat("ON")).unwrap();
367 e.emit(EdifactEvent::component("2")).unwrap();
368 e.emit(EdifactEvent::EndSegment).unwrap();
369 e.finish().unwrap();
370 }
371 assert_eq!(
372 std::str::from_utf8(&buf).unwrap(),
373 "UNA:+.?*'RFF+ON:1*ON:2'"
374 );
375
376 let segments: Vec<_> = crate::from_bytes(&buf)
377 .collect::<Result<Vec<_>, _>>()
378 .unwrap();
379 let element = segments[0].get_element(0).unwrap();
380 assert_eq!(element.repeat_count(), 2);
381 assert_eq!(element.repetition(1).unwrap()[1].0, "2");
382 }
383
384 #[test]
385 fn a_repetition_without_a_declared_separator_is_refused() {
386 let mut e = WriterEmitter::new(Vec::<u8>::new());
387 e.emit(EdifactEvent::start("RFF")).unwrap();
388 e.emit(EdifactEvent::element("ON")).unwrap();
389 let err = e.emit(EdifactEvent::repeat("ON")).unwrap_err();
390 assert!(
391 matches!(err, EdifactError::RepetitionSeparatorNotDeclared),
392 "expected RepetitionSeparatorNotDeclared, got {err:?}"
393 );
394 }
395
396 #[test]
397 fn a_repetition_before_any_element_is_refused() {
398 let ssa = crate::ServiceStringAdvice::from_bytes(b"UNA:+.?*'").unwrap();
399 let mut e = WriterEmitter::with_una(Vec::<u8>::new(), ssa).unwrap();
400 e.emit(EdifactEvent::start("RFF")).unwrap();
401 let err = e.emit(EdifactEvent::repeat("ON")).unwrap_err();
402 assert!(
403 matches!(err, EdifactError::InvalidEventSequence { .. }),
404 "expected InvalidEventSequence, got {err:?}"
405 );
406 }
407
408 #[test]
411 fn writer_emitter_element_before_start_segment_is_err() {
412 let mut e = WriterEmitter::new(Vec::<u8>::new());
413 let err = e.emit(EdifactEvent::element("X")).unwrap_err();
414 assert!(
415 matches!(err, crate::EdifactError::InvalidEventSequence { .. }),
416 "expected InvalidEventSequence, got {err:?}"
417 );
418 }
419
420 #[test]
421 fn writer_emitter_component_before_element_is_err() {
422 let mut e = WriterEmitter::new(Vec::<u8>::new());
423 e.emit(EdifactEvent::start("BGM")).unwrap();
424 let err = e.emit(EdifactEvent::component("X")).unwrap_err();
425 assert!(
426 matches!(err, crate::EdifactError::InvalidEventSequence { .. }),
427 "expected InvalidEventSequence, got {err:?}"
428 );
429 }
430
431 #[test]
432 fn writer_emitter_double_start_segment_is_err() {
433 let mut e = WriterEmitter::new(Vec::<u8>::new());
434 e.emit(EdifactEvent::start("BGM")).unwrap();
435 let err = e.emit(EdifactEvent::start("DTM")).unwrap_err();
436 assert!(
437 matches!(err, crate::EdifactError::InvalidEventSequence { .. }),
438 "expected InvalidEventSequence, got {err:?}"
439 );
440 }
441
442 #[test]
443 fn writer_emitter_end_segment_without_start_is_err() {
444 let mut e = WriterEmitter::new(Vec::<u8>::new());
445 let err = e.emit(EdifactEvent::EndSegment).unwrap_err();
446 assert!(
447 matches!(err, crate::EdifactError::InvalidEventSequence { .. }),
448 "expected InvalidEventSequence, got {err:?}"
449 );
450 }
451}