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 EndSegment,
33}
34
35#[derive(Debug, Clone, PartialEq, Eq)]
37#[non_exhaustive]
38pub enum OwnedEdifactEvent {
39 StartSegment {
41 tag: String,
43 },
44 Element {
46 value: String,
48 },
49 ComponentElement {
51 value: String,
53 },
54 EndSegment,
56}
57
58impl<'a> EdifactEvent<'a> {
59 pub fn into_owned(self) -> OwnedEdifactEvent {
61 match self {
62 Self::StartSegment { tag } => OwnedEdifactEvent::StartSegment {
63 tag: tag.to_owned(),
64 },
65 Self::Element { value } => OwnedEdifactEvent::Element {
66 value: value.to_owned(),
67 },
68 Self::ComponentElement { value } => OwnedEdifactEvent::ComponentElement {
69 value: value.to_owned(),
70 },
71 Self::EndSegment => OwnedEdifactEvent::EndSegment,
72 }
73 }
74}
75
76pub trait EventEmitter {
80 fn emit(&mut self, event: EdifactEvent<'_>) -> Result<(), EdifactError>;
82}
83
84#[derive(Debug, Default)]
90pub struct VecEmitter {
91 pub events: Vec<OwnedEdifactEvent>,
93}
94
95impl EventEmitter for VecEmitter {
96 fn emit(&mut self, event: EdifactEvent<'_>) -> Result<(), EdifactError> {
97 self.events.push(event.into_owned());
98 Ok(())
99 }
100}
101
102pub struct WriterEmitter<W: Write> {
118 writer: crate::Writer<W>,
119 #[cfg(debug_assertions)]
120 in_segment: bool,
121}
122
123impl<W: Write> WriterEmitter<W> {
124 pub fn new(inner: W) -> Self {
126 Self {
127 writer: crate::Writer::new(inner),
128 #[cfg(debug_assertions)]
129 in_segment: false,
130 }
131 }
132
133 pub fn finish(self) -> Result<W, EdifactError> {
135 self.writer.finish()
136 }
137
138 pub fn segment_count(&self) -> u32 {
140 self.writer.segment_count()
141 }
142}
143
144impl<W: Write> EventEmitter for WriterEmitter<W> {
145 fn emit(&mut self, event: EdifactEvent<'_>) -> Result<(), EdifactError> {
146 match event {
147 EdifactEvent::StartSegment { tag } => {
148 #[cfg(debug_assertions)]
149 {
150 assert!(
151 !self.in_segment,
152 "WriterEmitter: StartSegment emitted while a segment is already open (missing EndSegment)"
153 );
154 self.in_segment = true;
155 }
156 self.writer.write_tag_only(tag)?;
157 }
158 EdifactEvent::Element { value } => {
159 #[cfg(debug_assertions)]
160 assert!(
161 self.in_segment,
162 "WriterEmitter: Element emitted outside of a segment (missing StartSegment)"
163 );
164 self.writer.write_element_sep()?;
165 self.writer.write_escaped(value)?;
166 }
167 EdifactEvent::ComponentElement { value } => {
168 #[cfg(debug_assertions)]
169 assert!(
170 self.in_segment,
171 "WriterEmitter: ComponentElement emitted outside of a segment (missing StartSegment)"
172 );
173 self.writer.write_component_sep()?;
174 self.writer.write_escaped(value)?;
175 }
176 EdifactEvent::EndSegment => {
177 #[cfg(debug_assertions)]
178 {
179 assert!(
180 self.in_segment,
181 "WriterEmitter: EndSegment emitted while no segment is open (missing StartSegment)"
182 );
183 self.in_segment = false;
184 }
185 self.writer.write_segment_term_and_count()?;
186 }
187 }
188 Ok(())
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use super::*;
195
196 #[test]
197 fn vec_emitter_no_memory_leak() {
198 let mut e = VecEmitter::default();
199 e.emit(EdifactEvent::StartSegment { tag: "BGM" }).unwrap();
200 e.emit(EdifactEvent::Element { value: "E03" }).unwrap();
201 e.emit(EdifactEvent::EndSegment).unwrap();
202 assert_eq!(
203 e.events[0],
204 OwnedEdifactEvent::StartSegment {
205 tag: "BGM".to_owned()
206 }
207 );
208 assert_eq!(
209 e.events[1],
210 OwnedEdifactEvent::Element {
211 value: "E03".to_owned()
212 }
213 );
214 }
215
216 #[test]
217 fn writer_emitter_produces_valid_edifact() {
218 let mut buf = Vec::new();
219 {
220 let mut e = WriterEmitter::new(&mut buf);
221 e.emit(EdifactEvent::StartSegment { tag: "BGM" }).unwrap();
222 e.emit(EdifactEvent::Element { value: "E03" }).unwrap();
223 e.emit(EdifactEvent::Element { value: "11042" }).unwrap();
224 e.emit(EdifactEvent::EndSegment).unwrap();
225 e.finish().unwrap();
226 }
227 assert_eq!(buf, b"BGM+E03+11042'");
228 }
229
230 #[test]
231 fn writer_emitter_handles_components() {
232 let mut buf = Vec::new();
233 {
234 let mut e = WriterEmitter::new(&mut buf);
235 e.emit(EdifactEvent::StartSegment { tag: "NAD" }).unwrap();
236 e.emit(EdifactEvent::Element { value: "MS" }).unwrap();
237 e.emit(EdifactEvent::Element {
238 value: "9900112233445",
239 })
240 .unwrap();
241 e.emit(EdifactEvent::ComponentElement { value: "" })
242 .unwrap();
243 e.emit(EdifactEvent::ComponentElement { value: "293" })
244 .unwrap();
245 e.emit(EdifactEvent::EndSegment).unwrap();
246 e.finish().unwrap();
247 }
248 let s = std::str::from_utf8(&buf).unwrap();
249 assert_eq!(s, "NAD+MS+9900112233445::293'");
250 }
251}