pub struct Writer<W: Write> { /* private fields */ }Expand description
Streaming EDIFACT writer.
Wraps any Write implementation and serializes segments one at a time.
Call Writer::finish to flush and get the underlying writer back.
§Wrap unbuffered sinks
Writer issues a separate write for each tag, delimiter, and value chunk, so
a segment costs roughly one write per component. Against an in-memory
Vec<u8> that is free, but against a File or a socket each
one is a syscall.
The writer deliberately does not buffer internally: an internal buffer
would silently discard everything not yet flushed if the writer were dropped
without finish. Wrap the sink instead, which makes the
buffering visible and keeps the flush contract in one place:
use std::io::BufWriter;
use edifact_rs::Writer;
let sink = Vec::new(); // stands in for a File or TcpStream
let mut writer = Writer::new(BufWriter::new(sink));
writer.write_raw("BGM", &["220"])?;
// `finish` flushes the `Writer` and hands the `BufWriter` back.
let buffered = writer.finish()?;
assert_eq!(buffered.into_inner().unwrap(), b"BGM+220'".to_vec());Implementations§
Source§impl<W: Write> Writer<W>
impl<W: Write> Writer<W>
Sourcepub fn with_charset(self, charset: Charset) -> Self
pub fn with_charset(self, charset: Charset) -> Self
Bind this writer to a character repertoire.
Every value is then encoded into charset rather than emitted as UTF-8,
and a character the repertoire cannot carry is rejected with
EdifactError::CharacterNotInRepertoire instead of being written as
bytes the receiver decodes as something else.
This is the write-side counterpart of
decode_interchange: a UNOC interchange
must go out as ISO 8859-1, not UTF-8, or ü arrives as two mojibake
characters.
§Example
use edifact_rs::{Charset, Writer};
let mut writer = Writer::new(Vec::new()).with_charset(Charset::UnoC);
writer.write_composites("NAD", &[&["BY"], &["Müller"]])?;
// `ü` goes out as the single Latin-1 byte 0xFC.
assert_eq!(writer.finish()?, b"NAD+BY+M\xFCller'".to_vec());A value outside the repertoire is refused:
use edifact_rs::{Charset, EdifactError, Writer};
let mut writer = Writer::new(Vec::new()).with_charset(Charset::UnoA);
// Level A is upper-case only.
let err = writer.write_composites("NAD", &[&["BY"], &["Müller"]]).unwrap_err();
assert!(matches!(err, EdifactError::CharacterNotInRepertoire { .. }));Sourcepub fn charset(&self) -> Option<Charset>
pub fn charset(&self) -> Option<Charset>
The repertoire this writer encodes into, if it is bound to one.
Sourcepub fn with_una(
inner: W,
ssa: ServiceStringAdvice,
) -> Result<Self, EdifactError>
pub fn with_una( inner: W, ssa: ServiceStringAdvice, ) -> Result<Self, EdifactError>
Create a writer with custom delimiters and write a UNA segment first.
Sourcepub fn write_segment(&mut self, seg: &Segment<'_>) -> Result<(), EdifactError>
pub fn write_segment(&mut self, seg: &Segment<'_>) -> Result<(), EdifactError>
Write a single segment, including any ISO 9735-4 repetitions.
§Errors
Returns EdifactError::RepetitionSeparatorNotDeclared when the segment
carries a repeating data element but the active service string advice
declares no repetition separator. The check runs before any byte is
written, so a rejected segment leaves nothing behind in the sink — a
half-written RFF+ would otherwise corrupt the interchange for every
caller that recovers from the error and carries on.
Sourcepub fn write_raw(
&mut self,
tag: &str,
elements: &[&str],
) -> Result<(), EdifactError>
pub fn write_raw( &mut self, tag: &str, elements: &[&str], ) -> Result<(), EdifactError>
Write a raw segment from tag + element string slices.
Each element string is split on the active component-separator byte from the
configured ServiceStringAdvice to identify component
boundaries. The default component separator is : (0x3A), but this can differ when a
non-default UNA string was used to construct the writer.
§Delimiter dependency
Callers that embed the literal : character in element strings rely on : being
the component separator. When the writer uses a non-default delimiter set, : will
not be treated as a component boundary and the segment will be written incorrectly.
UTF-8 safety: EDIFACT syntax requires all delimiter bytes to be single-byte ASCII
characters (values 0x00–0x7F). Non-ASCII delimiter bytes would bisect multi-byte UTF-8
sequences in data values and produce malformed output. All fields of
ServiceStringAdvice must therefore hold ASCII byte values.
To produce correct output regardless of the active delimiter, prefer
Self::write_elements — it takes component boundaries explicitly and
handles the mixed simple/composite shape that most real segments have.
Self::write_segment_parts is the equivalent for owned data.
Sourcepub fn write_segment_parts<E>(
&mut self,
tag: &str,
elements: &[E],
) -> Result<(), EdifactError>
pub fn write_segment_parts<E>( &mut self, tag: &str, elements: &[E], ) -> Result<(), EdifactError>
Write a segment from a tag and pre-split element/component data.
elements is a slice of elements; each element is a sequence of component strings.
This avoids the lifetime constraints of Self::write_segment when building
segments from runtime-owned data (e.g. inside crate::WriterEmitter).
Sourcepub fn write_composites(
&mut self,
tag: &str,
elements: &[&[&str]],
) -> Result<(), EdifactError>
pub fn write_composites( &mut self, tag: &str, elements: &[&[&str]], ) -> Result<(), EdifactError>
Write a segment from a tag and borrowed element/component slices.
Unlike Self::write_raw, component boundaries are given explicitly
rather than inferred by splitting on the active component separator, so
values containing a literal separator byte are escaped instead of being
silently reinterpreted as a composite boundary. Unlike
Self::write_segment_parts, no String allocation is required.
§Example
use edifact_rs::Writer;
let mut w = Writer::new(Vec::new());
// The `:` inside the sender id stays part of the value.
w.write_composites("NAD", &[&["MS"][..], &["ACME:INC"][..]])?;
assert_eq!(w.finish()?, b"NAD+MS+ACME?:INC'".to_vec());§Errors
Returns EdifactError if the underlying writer fails.
Sourcepub fn write_elements(
&mut self,
tag: &str,
elements: &[DataElement<'_>],
) -> Result<(), EdifactError>
pub fn write_elements( &mut self, tag: &str, elements: &[DataElement<'_>], ) -> Result<(), EdifactError>
Write a segment whose data elements mix simple and composite shapes.
This is the general form of segment emission and the one that matches
how EDIFACT segments are actually specified: NAD takes a simple
qualifier followed by a composite party identification, DTM takes a
single composite. write_raw (all-simple, with
separators inferred by splitting) and
write_composites (all-composite) are the two
special cases.
Component boundaries are explicit, so a value containing the active component separator is escaped rather than silently promoted to a boundary. Nothing is allocated.
§Example
use edifact_rs::{DataElement, Writer, elements};
let mut w = Writer::new(Vec::new());
// Explicit form …
w.write_elements(
"NAD",
&[DataElement::Simple("MS"), DataElement::Composite(&["ACME:INC", "", "9"])],
)?;
// … or the `elements!` shorthand.
w.write_elements("DTM", elements![["137", "20260101", "102"]])?;
assert_eq!(
w.finish()?,
b"NAD+MS+ACME?:INC::9'DTM+137:20260101:102'".to_vec(),
);§Errors
Returns EdifactError if the underlying writer fails.
Sourcepub fn finish(self) -> Result<W, EdifactError>
pub fn finish(self) -> Result<W, EdifactError>
Flush and return the underlying writer.
Sourcepub fn finish_unt(self, message_ref: &str) -> Result<W, EdifactError>
pub fn finish_unt(self, message_ref: &str) -> Result<W, EdifactError>
Write the UNT segment and return the inner writer.
The count written into UNT DE 0074 covers the current message only:
UNH, every segment written since it, and UNT itself. Segments written
before the message’s UNH — an interchange-level UNB, or a preceding
message — are excluded, as EDIFACT requires.
If no UNH has been written, the count falls back to every segment
written so far plus one.
§Errors
Returns an error if writing fails. Do not call write_raw or
write_segment after finish_unt — the writer is consumed.
Sourcepub fn segment_count(&self) -> u64
pub fn segment_count(&self) -> u64
Returns the total number of segments written so far.
Sourcepub fn service_string_advice(&self) -> ServiceStringAdvice
pub fn service_string_advice(&self) -> ServiceStringAdvice
Returns the active ServiceStringAdvice (delimiter configuration).
Sourcepub fn escape_value<'v>(&self, value: &'v str) -> Cow<'v, str>
pub fn escape_value<'v>(&self, value: &'v str) -> Cow<'v, str>
Escape a value string for inclusion in an EDIFACT segment.
Any character in value that matches the active element separator,
component separator, release character, or segment terminator is escaped
by prefixing it with the release character (default ?).
Returns a borrowed Cow::Borrowed(value) when no escaping is needed,
avoiding an allocation on the fast path.
§Example
let writer = Writer::new(std::io::sink());
// '+' must be escaped since it is the default element separator.
assert_eq!(writer.escape_value("price+tax"), "price?+tax");Sourcepub fn begin_interchange(
&mut self,
syntax_id: &str,
syntax_version: &str,
sender: &str,
recipient: &str,
date: &str,
time: &str,
control_ref: &str,
) -> Result<(), EdifactError>
pub fn begin_interchange( &mut self, syntax_id: &str, syntax_version: &str, sender: &str, recipient: &str, date: &str, time: &str, control_ref: &str, ) -> Result<(), EdifactError>
Write a UNB interchange header segment.
Generates:
UNB+<syntax_id>:<syntax_version>+<sender>+<recipient>+<date>:<time>+<control_ref>'Composite components (S001 syntax identifier/version, S004 date/time) are
passed separately rather than pre-joined with :, so they are written
with the writer’s active component separator and so a literal separator
inside sender, recipient, or control_ref is escaped rather than
silently promoted to a component boundary.
Track the control_ref — it must be repeated in the matching
end_interchange call.
§Example
use edifact_rs::Writer;
let mut w = Writer::new(Vec::new());
w.begin_interchange("UNOA", "1", "SENDER", "RECEIVER", "200101", "0900", "IC1")?;
assert_eq!(
w.finish()?,
b"UNB+UNOA:1+SENDER+RECEIVER+200101:0900+IC1'".to_vec(),
);§Errors
Returns EdifactError if writing fails.
Sourcepub fn begin_message<'w>(
&'w mut self,
message_ref: &str,
message_type: &str,
version: &str,
release: &str,
controlling_agency: &str,
) -> Result<MessageWriter<'w, W>, EdifactError>
pub fn begin_message<'w>( &'w mut self, message_ref: &str, message_type: &str, version: &str, release: &str, controlling_agency: &str, ) -> Result<MessageWriter<'w, W>, EdifactError>
Write a UNH message header and return a MessageWriter guard.
The guard tracks the per-message segment count automatically. Call
MessageWriter::finish when all message segments have been written — this
writes the matching UNT segment with the correct count. If finish is not
called, Drop will attempt to write UNT as a best-effort fallback (errors
are silently discarded on drop; prefer explicit finish).
Generates:
UNH+<message_ref>+<message_type>:<version>:<release>:<controlling_agency>'§Errors
Returns EdifactError if writing the UNH segment fails.
Sourcepub fn end_interchange(
&mut self,
message_count: u32,
control_ref: &str,
) -> Result<(), EdifactError>
pub fn end_interchange( &mut self, message_count: u32, control_ref: &str, ) -> Result<(), EdifactError>
Write a UNZ interchange trailer segment.
message_count is the number of UNH/UNT message pairs in the
interchange. control_ref must match the value passed to
begin_interchange.
If you used begin_message for every message in the
interchange, message_count equals the number of times you called that
method.
§Errors
Returns EdifactError if writing fails.
Auto Trait Implementations§
impl<W> Freeze for Writer<W>where
W: Freeze,
impl<W> RefUnwindSafe for Writer<W>where
W: RefUnwindSafe,
impl<W> Send for Writer<W>where
W: Send,
impl<W> Sync for Writer<W>where
W: Sync,
impl<W> Unpin for Writer<W>where
W: Unpin,
impl<W> UnsafeUnpin for Writer<W>where
W: UnsafeUnpin,
impl<W> UnwindSafe for Writer<W>where
W: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<D> OwoColorize for D
impl<D> OwoColorize for D
Source§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
Source§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
Source§fn black(&self) -> FgColorDisplay<'_, Black, Self>
fn black(&self) -> FgColorDisplay<'_, Black, Self>
Source§fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
Source§fn red(&self) -> FgColorDisplay<'_, Red, Self>
fn red(&self) -> FgColorDisplay<'_, Red, Self>
Source§fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
Source§fn green(&self) -> FgColorDisplay<'_, Green, Self>
fn green(&self) -> FgColorDisplay<'_, Green, Self>
Source§fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
Source§fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
Source§fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
Source§fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
Source§fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
Source§fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
Source§fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
Source§fn white(&self) -> FgColorDisplay<'_, White, Self>
fn white(&self) -> FgColorDisplay<'_, White, Self>
Source§fn on_white(&self) -> BgColorDisplay<'_, White, Self>
fn on_white(&self) -> BgColorDisplay<'_, White, Self>
Source§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
Source§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
Source§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
Source§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
Source§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
Source§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
Source§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
Source§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
Source§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
Source§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
Source§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
Source§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
Source§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
Source§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
Source§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
Source§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
Source§fn bold(&self) -> BoldDisplay<'_, Self>
fn bold(&self) -> BoldDisplay<'_, Self>
Source§fn dimmed(&self) -> DimDisplay<'_, Self>
fn dimmed(&self) -> DimDisplay<'_, Self>
Source§fn italic(&self) -> ItalicDisplay<'_, Self>
fn italic(&self) -> ItalicDisplay<'_, Self>
Source§fn underline(&self) -> UnderlineDisplay<'_, Self>
fn underline(&self) -> UnderlineDisplay<'_, Self>
Source§fn blink(&self) -> BlinkDisplay<'_, Self>
fn blink(&self) -> BlinkDisplay<'_, Self>
Source§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
Source§fn reversed(&self) -> ReversedDisplay<'_, Self>
fn reversed(&self) -> ReversedDisplay<'_, Self>
Source§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
Source§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg or
a color-specific method, such as OwoColorize::green, Read moreSource§fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg or
a color-specific method, such as OwoColorize::on_yellow, Read more