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 (E018).
  • 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;
use std::io::Cursor;

let input = b"UNA:;.? 'BGM;220;test?;value'";
let segments = from_reader(Cursor::new(&input[..])).unwrap();
assert_eq!(segments.len(), 1);
assert_eq!(segments[0].tag, "BGM");
assert_eq!(segments[0].elements[0].components[0], "220");
assert_eq!(segments[0].elements[1].components[0], "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::builder("ORDERS-DEMO")
    .for_message_type("ORDERS")
    .with_rule_fn(|segments| {
        let bgm = segments.iter().find(|segment| segment.tag == "BGM")?;
        let document_code = bgm.get_element(0)?.get_component(0)?;
        (document_code == "220").then(|| {
            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 envelope::validate_envelope;
pub use error::EdifactError;
pub use error::IoError;
pub use error::ValidationIssue;
pub use error::ValidationReport;
pub use error::ValidationSeverity;
pub use model::BorrowedElement;
pub use model::BorrowedSegment;
pub use model::Element;
pub use model::OwnedElement;
pub use model::OwnedSegment;
pub use model::Segment;
pub use model::Span;
pub use parser::Parser;
pub use parser::ReaderConfig;
pub use parser::from_bufread;
pub use parser::from_bufread_stream;
pub use parser::from_bufread_stream_with_config;
pub use parser::from_reader_with_config;
pub use tokenizer::ServiceStringAdvice;
pub use tokenizer::Tokenizer;
pub use validator::ProfileRule;
pub use validator::ProfileRulePack;
pub use validator::ValidationContext;
pub use validator::ValidationContextBuilder;
pub use validator::ValidationLayer;
pub use validator::Validator;
pub use validator::validate_each;
pub use writer::Writer;
pub use de::CompositeElement;
pub use de::EdifactCompositeDeserialize;
pub use de::EdifactDeserialize;
pub use de::EdifactSegmentTag;
pub use de::MessageWindowsIter;
pub use de::MessageWindowsSliceIter;
pub use de::SegmentAccessor;
pub use de::composite_element;
pub use de::contiguous_groups_by_qualifier;
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_qualified_segment_owned;
pub use de::find_segment;
pub use de::find_segment_owned;
pub use de::find_segment_typed;
pub use de::find_segments_iter;
pub use de::find_segments_typed;
pub use de::get_components_iter;
pub use de::groups_are_contiguous_by_qualifier;
pub use de::message_windows_bytes;
pub use de::message_windows_from_reader;
pub use de::optional_component;
pub use de::optional_element;
pub use de::qualifier_matches_pattern;
pub use de::required_component;
pub use de::required_element;
pub use event::EdifactEvent;
pub use event::EventEmitter;
pub use event::OwnedEdifactEvent;
pub use event::VecEmitter;
pub use event::WriterEmitter;
pub use ser::EdifactCompositeSerialize;
pub use ser::EdifactSerialize;
pub use ser::to_string;
pub use directory_validator::DirectoryValidator;
pub use directory_validator::ElementRef;
pub use directory_validator::SegmentDefinition;
pub use directory_validator::Status;

Modules§

de
Custom deserialization trait for EDIFACT.
directory_validator
Shared UN/EDIFACT directory validation engine used by D.11A, D.01B and D.96A.
envelope
EDIFACT envelope validation (Story 2.4).
error
Error types and validation reporting primitives.
event
Event model for EDIFACT (de)serialization.
model
Core zero-copy and owned EDIFACT data model types.
parser
Streaming EDIFACT parser — wraps a Tokenizer and assembles Segments.
ser
Custom serialization trait for EDIFACT.
tokenizer
EDIFACT tokenizer — splits raw bytes into typed tokens.
validator
Validation pipeline for structural and semantic EDIFACT checks.
writer
EDIFACT writer — serializes Segments to wire format.

Structs§

FromBytesIter
Iterator returned by from_bytes.
FromReaderIter
Iterator returned by from_reader_iter.

Functions§

from_bytes
Parse input bytes into an iterator of Segments.
from_reader
Parse a reader into owned segments.
from_reader_iter
Parse a reader into owned segments as a streaming iterator.
to_bytes
Serialize segments to an owned Vec<u8>.
to_writer
Serialize segments to an std::io::Write implementation.

Derive Macros§

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