Skip to main content

Crate edifact_rs

Crate edifact_rs 

Source
Expand description

edifact-rs — zero-copy EDIFACT tokenizer, parser, writer, serde traits, validation engine, and extensible directory support.

edifact-rs is the main entry point of this workspace. The core parsing, writing, and validation infrastructure is always available. Custom directory validators can be implemented by downstream crates or generated through external build tooling.

§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");

§Crate features

  • derive (enabled by default): re-exports the derive macros from edifact-rs-derive.
  • diagnostics (disabled by default): enables rich diagnostic output via miette. When enabled, errors implement miette::Diagnostic for enhanced error reporting. This feature adds an optional dependency and has no impact on parsing performance.

The crate is expected to compile both with defaults and with --no-default-features for consumers who only want the core parsing and writing functionality.

§Feature matrix workflows

  • default features: cargo test -p edifact-rs
  • no default features: cargo test -p edifact-rs --no-default-features
  • all features: cargo test -p edifact-rs --all-features

§Diagnostic Feature

When the diagnostics feature is enabled, EdifactError gains additional traits and methods that enable rich, human-readable error output:

Error: invalid delimiter byte 0xAB at offset 42

 ╭─ input.edi:2:3
 │
 2 │ UNB+UNOA:1+....[invalid]...
 │         ^^^ invalid byte here
 │
Error Code: E002
Help: The byte 0xAB is not a valid delimiter. Check UNA configuration

This feature is useful for CLI tools and error reporting, but is not required for applications that handle errors programmatically.

§Parse And Text Contracts

Parsing in edifact-rs is strict and deterministic:

  • Segment and element text must decode as UTF-8 (E003 on failure).
  • Release characters must escape exactly one following byte. A trailing ? at end-of-input is rejected (E019).
  • Malformed delimiters and truncated segments are reported with stable error codes rather than panicking.

These contracts apply to both slice-based parsing (from_bytes) and reader-based parsing (from_reader).

use edifact_rs::from_reader_collect;
use std::io::Cursor;

let input = b"UNA:;.? 'BGM;220;test?;value'";
let segments = from_reader_collect(Cursor::new(&input[..])).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 Quick Start

The Validator trait and ValidationContext provide a flexible framework for building custom validators. Users can generate validators from official UNECE sources or implement their own.

See the Validator trait documentation and the cookbook_fixture_validation.rs example for details on creating custom validators.

§Custom Profile Packs

ProfileRulePack is the extension point for downstream MIG/profile crates. Packs can be authored with public APIs only and plugged into a ValidationContext:

use edifact_rs::{
    from_bytes, ProfileRulePack, ValidationContext, ValidationIssue, ValidationSeverity,
};

let segments: Vec<_> = from_bytes(b"UNH+1+ORDERS:D:96A:UN'BGM+220+PO123+9'UNT+3+1'")
    .collect::<Result<_, _>>()?;

let pack = ProfileRulePack::new("ORDERS-DEMO")
    .for_message_type("ORDERS")
    .with_stateless_rule_fn(|segments, issues| {
        if let Some(bgm) = segments.iter().find(|segment| segment.tag == "BGM") {
            if let Some(code) = bgm.get_element(0).and_then(|e| e.get_component(0)) {
                if code == "220" {
                    issues.push(
                        ValidationIssue::new(
                            ValidationSeverity::Warning,
                            "demo pack rejects BGM 220 for illustration",
                        )
                        .with_rule_id("DEMO-P001")
                        .with_segment("BGM")
                        .with_element_index(0),
                    );
                }
            }
        }
    });

let report = ValidationContext::builder()
    .with_profile_pack(pack)
    .build()
    .validate_lenient(&segments);

assert!(report.has_warnings());
let partner_report = report.filter_by_rule_prefix("DEMO-");
assert!(partner_report.total_issues() >= 1);

§Async Usage

edifact-rs does not provide a native async API. All parsing is synchronous and driven by the standard std::io::Read / std::io::BufRead traits. The recommended integration pattern with async runtimes is:

  1. Use your async runtime’s read utilities to read the entire message into a Vec<u8> (e.g. tokio::io::AsyncReadExt::read_to_end).
  2. Parse the in-memory slice with from_bytes.
// With tokio:
// let mut buf = Vec::new();
// reader.read_to_end(&mut buf).await?;
// let segments: Vec<_> = edifact_rs::from_bytes(&buf).collect::<Result<_, _>>()?;

A native zero-copy streaming async API is tracked as a future roadmap item.

Re-exports§

pub use group::GroupDef;
pub use group::SegmentGroup;
pub use group::SegmentGroupIndexed;
pub use group::group_owned_segments;
pub use group::group_owned_segments_indexed;
pub use group::group_segments;
pub use group::group_segments_indexed;
pub use de::CompositeElement;
pub use de::DispatchedMessage;
pub use de::EdifactCompositeDeserialize;
pub use de::EdifactDeserialize;
pub use de::EdifactSegmentTag;
pub use de::MessageDispatch;
pub use de::MessageWindow;
pub use de::MessageWindowsIter;
pub use de::MessageWindowsSliceIter;
pub use de::OwnedMessageWindow;
pub use de::SegmentAccessor;
pub use de::deserialize;
pub use de::deserialize_all_from_reader;
pub use de::deserialize_all_streaming;
pub use de::deserialize_first_from_reader;
pub use de::deserialize_first_streaming;
pub use de::deserialize_messages_bytes;
pub use de::deserialize_messages_from_reader;
pub use de::deserialize_str;
pub use de::element_str;
pub use de::find_qualified_segment;
pub use de::find_segment;
pub use de::groups_are_contiguous_by_qualifier;
pub use de::message_windows_from_reader;
pub use de::optional_element;
pub use de::required_element;
pub use de::message_windows_bytes as from_bytes_windows;
pub use directory_validator::DirectoryValidator;
pub use directory_validator::DirectoryValidatorBuilder;
pub use directory_validator::ElementRef;
pub use directory_validator::OwnedElementRef;
pub use directory_validator::OwnedSegmentDef;
pub use directory_validator::SegmentDefinition;
pub use directory_validator::Status;
pub use ser::DecimalFloat;
pub use ser::DecimalFloatDisplay;
pub use ser::EdifactCompositeSerialize;
pub use ser::EdifactSerialize;
pub use ser::to_bytes;
pub use ser::to_edifact_string;

Modules§

de
Custom deserialization trait for EDIFACT.
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.
helpers
Segment-navigation helpers for working with parsed EDIFACT segments.
ser
Custom serialization trait for EDIFACT.

Structs§

BorrowedElement
Zero-allocation view of an OwnedElement.
BorrowedSegment
Zero-allocation view of an OwnedSegment.
Element
A data element, which may have one or more component values.
EnvelopeValidator
Built-in validator for EDIFACT interchange envelope structure.
FromBytesIter
Iterator returned by from_bytes.
FromReaderIter
Iterator returned by from_reader.
InterchangeEnvelope
Extracted data from the UNB / UNZ interchange envelope.
IoError
Wrapper around std::io::Error that implements PartialEq by comparing std::io::ErrorKind.
MessageEnvelope
Extracted data from a single UNH / UNT message envelope.
MessageIdentifier
Parsed identifier fields from a UNH segment.
OwnedElement
Owned data element used by reader-based parsing APIs.
OwnedSegment
Owned segment used by reader-based parsing APIs.
Parser
Streaming parser over a Tokenizer.
ProfileRulePack
A profile/MIG rule pack that can be plugged into ValidationContext.
ReaderConfig
Configuration for reader-based EDIFACT parsers.
Segment
A single EDIFACT segment, borrowing its data from the source input.
ServiceStringAdvice
EDIFACT service string advice (UNA segment).
Span
A half-open byte span within an EDIFACT payload.
Tokenizer
Zero-copy tokenizer over a byte slice.
ValidationContext
Runtime validation context for progressive layered validation.
ValidationContextBuilder
Builder for ValidationContext.
ValidationIssue
A structured validation issue.
ValidationReport
A collection of validation results: errors, warnings, and info.
ValidationRuleContext
Typed context injected into profile rule closures at validation time.
VecEmitter
Collects events into a Vec<OwnedEdifactEvent>.
Writer
Streaming EDIFACT writer.
WriterEmitter
Writes EDIFACT events directly to any Write implementation.

Enums§

EdifactError
All errors produced by edifact-rs.
EdifactEvent
A borrowed EDIFACT event emitted during serialization.
OwnedEdifactEvent
An owned EDIFACT event — for collection and testing (no borrowed lifetimes).
ValidationLayer
Validation layers used by ValidationContext.
ValidationSeverity
Priority level for a validation error or warning.

Traits§

EventEmitter
Trait for any sink that can consume EdifactEvents.
ProfileRule
A profile rule that can be added to a ProfileRulePack.
Validator
Pluggable validator for parsed EDIFACT segments.

Functions§

from_bufread
Parse EDIFACT from a buffered reader.
from_bufread_stream
Parse EDIFACT from a buffered reader as a streaming iterator.
from_bufread_stream_with_config
Parse EDIFACT from a buffered reader as a streaming iterator with custom config.
from_bytes
Parse input bytes into an iterator of Segments.
from_bytes_owned
Parse input bytes eagerly into an iterator of OwnedSegments.
from_bytes_owned_with_config
Parse input bytes eagerly into an iterator of OwnedSegments with a custom ReaderConfig.
from_bytes_with_config
Parse input bytes into an iterator of Segments with explicit configuration.
from_reader
Parse a reader into a lazy iterator of OwnedSegments.
from_reader_collect
Parse a reader into an owned Vec of all segments.
from_reader_with_config
Parse EDIFACT from an arbitrary reader as a streaming iterator with custom config.
parse_unh
Extract identifier fields from a UNH segment.
segments_to_bytes
Serialize segments to an owned Vec<u8>.
segments_to_bytes_owned
Serialize a slice of OwnedSegments to an owned Vec<u8>.
to_writer
Serialize segments to an std::io::Write implementation.
validate_each
Helper for per-segment validators: iterates segments, calls f for each one, and converts any Err into report entries.
validate_envelope
Validates the EDIFACT interchange envelope for the given segments.
validate_envelope_from_owned
Validate the EDIFACT interchange envelope for an owned-segment slice.
validate_envelope_lenient
Validate the EDIFACT envelope structure and collect all errors rather than stopping at the first failure.
validate_envelope_lenient_from_owned
Lenient validation over an owned-segment slice — collects all errors.
validate_envelope_lenient_owned
Lenient envelope validation over owned segments — collects all errors.
validate_envelope_owned
Validate the envelope structure of an owned-segment slice.

Derive Macros§

EdifactDeserializederive
Derive edifact_rs::EdifactDeserialize for segment or message structs.
EdifactSerializederive
Derive edifact_rs::EdifactSerialize for segment or message structs.