Expand description
edifact-rs — zero-copy EDIFACT (ISO 9735) tokenizer, parser, writer, typed
(de)serialization, validation engine, and extensible directory support.
§Quick start
use edifact_rs::from_bytes;
let input = b"UNB+UNOA:1+SENDER+RECEIVER+200101:0900+1'UNZ+0+1'";
let segments: Vec<_> = from_bytes(input).collect::<Result<_, _>>().unwrap();
assert_eq!(segments[0].tag, "UNB");§One segment type, borrowed or owned
Segment<'a> holds its text as Cow<'a, str>, which is
what lets a single type cover both parsing modes:
from_bytesborrows straight out of the input — no allocation for segment data — and yieldsSegment<'input>.from_readerhas no buffer to borrow from and yieldsSegment<'static>, aliased asOwnedSegment.
Segment is covariant in 'a, so &[OwnedSegment] is accepted anywhere
&[Segment<'_>] is wanted. Every API in this crate therefore takes one shape
and serves both paths — there are no _owned twins, and no conversion step.
use edifact_rs::{OwnedSegment, Segment};
fn count_bgm(segments: &[Segment<'_>]) -> usize {
segments.iter().filter(|s| s.tag == "BGM").count()
}
let borrowed: Vec<Segment<'_>> =
edifact_rs::from_bytes(b"BGM+220'").collect::<Result<_, _>>()?;
let owned: Vec<OwnedSegment> =
edifact_rs::from_reader(std::io::Cursor::new(b"BGM+220'")).collect::<Result<_, _>>()?;
assert_eq!(count_bgm(&borrowed), 1);
assert_eq!(count_bgm(&owned), 1);§Crate features
derive(enabled by default): re-exports the derive macros fromedifact-rs-derive—EdifactDeserialize/EdifactSerializefor segment and message structs, andEdifactCompositeDeserialize/EdifactCompositeSerializefor the composite-element structs they reference.diagnostics(off by default):EdifactErrorimplementsmiette::Diagnostic, for span-annotated CLI output.serde(off by default):Serialize/DeserializeforValidationReport,ValidationIssue, and the envelope types.
Features are additive and independent: each changes only which trait impls and re-exports exist, never parsing or validation behaviour.
§Parse and text contracts
Parsing in edifact-rs is strict and deterministic:
- A byte order mark and any whitespace before the first service segment are skipped — ISO 9735 authorises neither, but both arrive constantly.
- A segment that ends without its terminator is a truncation (
E010): accepting it would let a file cut off mid-transfer parse as complete. - Segment and element text must decode as UTF-8 (
E003). - A release character must escape exactly one following byte; a trailing
?at end-of-input is rejected (E019). - Every
ReaderConfigbudget reports a violation (E020,E036) rather than ending the iterator, which would be indistinguishable from a clean end of input. - The service characters are discovered the way ISO 9735-1 says a receiver
should discover them: from a leading
UNAif there is one, otherwise the §5.1 defaults with the repetition separator resolved from the syntax version inUNBS001 DE 0002 — active as*for version 4, inactive for versions 1–3, where*is ordinary data. Override both withReaderConfig::with_service_string_advicewhen parsing a fragment that carries neither header. - When the repetition separator is active, repeating data elements are split
into
Element::repetitionsrather than left glued into the value (ISO 9735-1 §8.6).
Every one of these contracts applies identically to slice-based parsing
(from_bytes) and reader-based parsing (from_reader); the two are held
to byte-for-byte agreement by a test that runs the same inputs through both.
use edifact_rs::from_reader;
use std::io::Cursor;
let input = b"UNA:;.? 'BGM;220;test?;value'";
let segments: Vec<_> = from_reader(Cursor::new(&input[..]))
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(segments.len(), 1);
assert_eq!(segments[0].tag, "BGM");
assert_eq!(segments[0].element_str(0), Some("220"));
assert_eq!(segments[0].element_str(1), Some("test;value"));§Validation
ValidationContext runs four layers — envelope, structure, code-list and
profile — into one ValidationReport:
use edifact_rs::{ProfileRulePack, ValidationContext, ValidationIssue, ValidationSeverity, from_bytes};
let pack = ProfileRulePack::new("ORDERS-DEMO")
.for_message_type("ORDERS")
.with_rule_fn(|segments, issues| {
if !segments.iter().any(|s| s.tag == "BGM") {
issues.push(
ValidationIssue::new(ValidationSeverity::Error, "ORDERS requires a BGM")
.with_rule_id("DEMO-P001"),
);
}
});
let segments: Vec<_> = from_bytes(b"UNH+1+ORDERS:D:96A:UN'DTM+137:1:102'UNT+3+1'")
.collect::<Result<_, _>>()?;
let report = ValidationContext::builder().with_profile_pack(pack).build().validate(&segments);
assert_eq!(report.filter_by_rule_prefix("DEMO-").total_issues(), 1);See the validation and profile pack guides for the layers, group-scoped rules, and directory validation.
§Async usage
There is deliberately no native async API: parsing is CPU work over a
buffer, not I/O, so an async parser would add a runtime dependency and a
second copy of every code path to wrap work that never awaits. Read with your
runtime, parse synchronously — see the
async integration guide
for the three patterns, including spawn_blocking for multi-gigabyte files.
let mut buf = Vec::new();
reader.read_to_end(&mut buf).await?;
let segments: Vec<_> = edifact_rs::from_bytes(&buf).collect::<Result<Vec<_>, _>>()?;Re-exports§
pub use charset::Charset;pub use charset::DecodingReader;pub use charset::decode_interchange;pub use charset::decode_reader;pub use charset::sniff_charset;pub use contrl::Action;pub use contrl::Contrl;pub use contrl::ReportingLevel;pub use contrl::SyntaxError;pub use group::Descendants;pub use group::GroupDef;pub use group::SegmentGroupIndexed;pub use group::group_segments_indexed;pub use report::severity_for_error;pub use report::ValidationIssue;pub use report::ValidationReport;pub use report::ValidationSeverity;pub use de::CompositeElement;pub use de::EdifactCompositeDeserialize;pub use de::EdifactDeserialize;pub use de::EdifactSegmentTag;pub use de::MessageWindow;pub use de::MessageWindows;pub use de::OwnedMessageWindow;pub use de::composite_element;pub use de::contiguous_groups;pub use de::deserialize;pub use de::deserialize_each;pub use de::deserialize_each_from_reader;pub use de::deserialize_messages;pub use de::deserialize_messages_from_reader;pub use de::deserialize_str;pub use de::find_qualified_segment;pub use de::find_segment;pub use de::find_segments;pub use de::find_segments_typed;pub use de::message_windows;pub use de::message_windows_from_reader;pub use de::qualifier_matches_pattern;pub use directory_validator::ComponentRef;pub use directory_validator::DirectoryValidator;pub use directory_validator::DirectoryValidatorBuilder;pub use directory_validator::ElementPath;pub use directory_validator::ElementRef;pub use directory_validator::LayoutAudit;pub use directory_validator::LayoutFinding;pub use directory_validator::LayoutSlot;pub use directory_validator::OwnedComponentRef;pub use directory_validator::OwnedElementRef;pub use directory_validator::OwnedSegmentDef;pub use directory_validator::Repr;pub use directory_validator::ReprKind;pub use directory_validator::SegmentDefinition;pub use directory_validator::SegmentLayout;pub use directory_validator::Status;pub use directory_validator::audit_directory;pub use ser::DecimalFloat;pub use ser::EdifactCompositeSerialize;pub use ser::EdifactSerialize;pub use ser::emit_sparse_segment;pub use ser::to_bytes;pub use ser::to_edifact_string;
Modules§
- charset
- EDIFACT character repertoires (
UNBS001 DE 0001) and transcoding. EDIFACT character repertoires — theUNBS001 DE 0001 syntax identifier. - contrl
CONTRL— the ISO 9735-4 syntax and service report message.CONTRL— the syntax and service report message (ISO 9735-4).- de
- Typed deserialization: EDIFACT segments to Rust values.
- directory_
validator - Shared UN/EDIFACT directory validation engine used by D.11A, D.01B and D.96A.
- group
- Segment group tree model for structured EDIFACT message navigation.
- report
- Validation report types:
ValidationSeverity,ValidationIssue,ValidationReport. - ser
- Custom serialization trait for EDIFACT.
- service
- ISO 9735 service-segment definitions (
UNB,UNH,UNT,UNZ,UNG,UNE,UNS). Segment definitions for the ISO 9735 service segments.
Macros§
- elements
- Build a
&[DataElement]from a mix of simple values and component lists.
Structs§
- Charset
Validator - Checks that every value in the message is expressible in the interchange’s
declared character repertoire (
UNBS001 DE 0001). - Decoding
Segment Stream - Lazy iterator returned by
from_reader_decoded. - Element
- A data element, which may have one or more component values.
- Envelope
Validator - Built-in validator for EDIFACT interchange envelope structure.
- From
Bytes Iter - Iterator returned by
from_bytes. - From
Reader Iter - Iterator returned by
from_reader. - Functional
Group Envelope - Extracted data from a single
UNG/UNEfunctional group envelope. - Group
Identifier - Parsed identifier fields from a
UNGsegment. - Interchange
Envelope - Extracted data from the
UNB/UNZinterchange envelope. - IoError
- Wrapper around
std::io::Errorthat implementsPartialEqby comparingstd::io::ErrorKind. - Lenient
Result - Result of a lenient envelope validation — carries both a (possibly partial) interchange and the full list of collected errors.
- Message
Envelope - Extracted data from a single
UNH/UNTmessage envelope. - Message
Identifier - Parsed identifier fields from a
UNHsegment. - Message
Writer - RAII guard for a single EDIFACT message within an interchange.
- Owned
Segment Stream - Streaming iterator over owned segments from a buffered reader.
- Parser
- Streaming parser over a
Tokenizer. - Profile
Rule Pack - A profile/MIG rule pack that can be plugged into
ValidationContext. - Reader
Config - Configuration for reader-based EDIFACT parsers.
- Segment
- A single EDIFACT segment.
- Service
String Advice - EDIFACT service string advice — the six characters of the
UNA(ISO 9735-1 Annex B). - Span
- A half-open byte span within an EDIFACT payload.
- Syntax
Validator - Checks the ISO 9735-1 rules that hold for every interchange, whatever directory or profile it claims.
- Tokenizer
- Zero-copy tokenizer over a byte slice.
- Validated
Interchange - Fully validated interchange structure returned by
validate_envelope. - Validation
Context - Runs the four validation layers over one segment slice, collecting every
issue into a single
ValidationReport. - Validation
Context Builder - Builder for
ValidationContext. - Validation
Rule Context - Typed context injected into profile rule closures at validation time.
- VecEmitter
- Collects events into a
Vec<EdifactEvent<'static>>. - Writer
- Streaming EDIFACT writer.
- Writer
Emitter - Writes EDIFACT events directly to any
Writeimplementation.
Enums§
- Data
Element - One data element of a segment being written: simple or composite.
- Edifact
Error - All errors produced by
edifact-rs. - Edifact
Event - A borrowed EDIFACT event emitted during serialization.
- Insignificant
- Which rule of ISO 9735-1 §9.1 a value violates.
- Token
- Token produced by
Tokenizer. - Validation
Layer - Validation layers used by
ValidationContext.
Traits§
- AsData
Element - Borrow a value as a
DataElement, choosing simple or composite by type. - Event
Emitter - Trait for any sink that can consume
EdifactEvents. - Profile
Rule - A profile rule that can be added to a
ProfileRulePack. - Validator
- Pluggable validator for parsed EDIFACT segments.
Functions§
- from_
bufread - Parse an already-buffered reader into a lazy iterator of
OwnedSegments. - from_
bufread_ with_ config from_bufreadwith explicitReaderConfiglimits.- from_
bytes - Parse
inputbytes into an iterator ofSegments. - from_
bytes_ decoded - Parse a byte slice, decoding it from the repertoire its own
UNBdeclares. - from_
bytes_ decoded_ with_ config from_bytes_decodedwith explicitReaderConfiglimits.- from_
bytes_ with_ config - Parse
inputbytes into an iterator ofSegments with explicit configuration. - from_
reader - Parse a reader into a lazy iterator of
OwnedSegments. - from_
reader_ decoded - Parse a reader, decoding it from the repertoire the stream’s own
UNBdeclares — lazily. - from_
reader_ decoded_ with_ config from_reader_decodedwith explicitReaderConfiglimits.- from_
reader_ with_ config - Parse EDIFACT from an arbitrary reader as a streaming iterator with custom config.
- parse_
ung - Extract identifier fields from a
UNGsegment (zero allocation). - parse_
unh - Extract identifier fields from a
UNHsegment (zero allocation). - segments_
to_ bytes - Serialize
segmentsto an ownedVec<u8>. - to_
writer - Serialize
segmentsto anstd::io::Writeimplementation. - validate_
each - Helper for per-segment validators: iterates
segments, callsffor each one, and converts anyErrinto report entries. - validate_
envelope - Validate the EDIFACT interchange envelope, failing at the first violation.
- validate_
envelope_ lenient - Validate the EDIFACT envelope and collect all errors rather than stopping at the first failure (borrowed-segment path).
Type Aliases§
- Components
- Components of one occurrence of a data element, each paired with its span.
- Owned
Element - An
Elementthat owns all of its text. SeeOwnedSegment. - Owned
Segment - A
Segmentthat owns all of its text.
Derive Macros§
- Edifact
Composite Deserialize derive - Derive
edifact_rs::EdifactCompositeDeserializefor a composite-element struct. - Edifact
Composite Serialize derive - Derive
edifact_rs::EdifactCompositeSerializefor a composite-element struct. - Edifact
Deserialize derive - Derive
edifact_rs::EdifactDeserializefor segment or message structs. - Edifact
Serialize derive - Derive
edifact_rs::EdifactSerializefor segment or message structs.