Skip to main content

ProfileRulePack

Struct ProfileRulePack 

Source
pub struct ProfileRulePack { /* private fields */ }
Expand description

A profile/MIG rule pack that can be plugged into ValidationContext.

Implementations§

Source§

impl ProfileRulePack

Source

pub fn new(name: impl Into<String>) -> Self

Create an empty rule pack.

Source

pub fn name(&self) -> &str

Return the pack name.

Source

pub fn message_types(&self) -> impl Iterator<Item = &str>

Return the message types this pack is scoped to.

Source

pub fn rule_count(&self) -> usize

Return the number of rules in this pack.

Source

pub fn named_rule_count(&self) -> usize

Return the number of named rules (those with a stable identifier).

Source

pub fn anonymous_rule_count(&self) -> usize

Return the number of anonymous rules (those without a stable identifier).

Source

pub fn rule_ids(&self) -> impl Iterator<Item = &str>

Iterate over the stable identifiers of all named rules in this pack.

Source

pub fn release(&self) -> Option<&str>

Return the association-assigned release code this pack is bound to, if any.

Source

pub fn for_message_type(self, message_type: impl Into<String>) -> Self

Restrict this pack to one or more EDIFACT message types from the UNH segment.

Source

pub fn for_release(self, release: impl Into<String>) -> Self

Bind this pack to a specific association-assigned code (DE 0057).

Source

pub fn with_bail_on_first_error(self, bail: bool) -> Self

Stop evaluating rules in this pack after the first Error- or Critical-severity finding.

Source

pub fn with_max_issues_per_rule(self, limit: impl Into<Option<usize>>) -> Self

Cap the number of issues any single rule may emit per evaluation pass.

Excess issues are discarded, keeping one noisy rule from flooding the report.

The cap is per rule per call — not globally, and not per group: a group rule’s budget is spent across the whole tree walk rather than reset at each occurrence, and a rule that has spent it is not called again on that pass.

None removes the cap.

§Example
use edifact_rs::{ProfileRulePack, ValidationIssue, ValidationSeverity, from_bytes};

let pack = ProfileRulePack::new("NOISY")
    .with_max_issues_per_rule(2)
    .with_rule_fn(|segments, issues| {
        for segment in segments {
            issues.push(ValidationIssue::new(
                ValidationSeverity::Warning,
                format!("saw {}", segment.tag()),
            ));
        }
    });

let segments: Vec<_> = from_bytes(b"BGM+1'DTM+2'RFF+3'NAD+4'")
    .collect::<Result<Vec<_>, _>>()?;
let report = edifact_rs::ValidationContext::builder()
    .with_profile_pack(pack)
    .build()
    .validate(&segments);

assert_eq!(report.total_issues(), 2); // four segments, capped at two
Source

pub fn with_rule_fn<F>(self, rule: F) -> Self
where F: for<'a> Fn(&[Segment<'a>], &mut Vec<ValidationIssue>) + Send + Sync + 'static,

Add a rule closure.

The closure receives the segments and a Vec to push issues into. This is the everyday form; reach for with_contextual_rule_fn only when the rule needs the per-call ValidationRuleContext.

The rule is anonymous, so merge_with_override cannot replace it — use with_named_rule_fn for anything a downstream pack may need to override.

§Example
use edifact_rs::{ProfileRulePack, ValidationIssue, ValidationSeverity};

let pack = ProfileRulePack::new("ORDERS").with_rule_fn(|segments, issues| {
    if !segments.iter().any(|segment| segment.tag == "BGM") {
        issues.push(ValidationIssue::new(
            ValidationSeverity::Error,
            "ORDERS requires a BGM",
        ));
    }
});
assert_eq!(pack.rule_count(), 1);
Source

pub fn with_named_rule_fn<F>(self, id: impl Into<Arc<str>>, rule: F) -> Self
where F: for<'a> Fn(&[Segment<'a>], &mut Vec<ValidationIssue>) + Send + Sync + 'static,

Add a rule closure with a stable identifier.

The identifier is what merge_with_override matches on, so name every rule a downstream pack may need to replace.

Source

pub fn with_contextual_rule_fn<F>(self, rule: F) -> Self
where F: for<'a> Fn(&[Segment<'a>], &ValidationRuleContext<'_>, &mut Vec<ValidationIssue>) + Send + Sync + 'static,

Add a rule closure that also receives the ValidationRuleContext.

The context carries the message reference, the message type, and any typed metadata passed to validate_with. When the rule does not need it, with_rule_fn is the shorter form.

Source

pub fn with_named_contextual_rule_fn<F>( self, id: impl Into<Arc<str>>, rule: F, ) -> Self
where F: for<'a> Fn(&[Segment<'a>], &ValidationRuleContext<'_>, &mut Vec<ValidationIssue>) + Send + Sync + 'static,

Add a context-aware rule closure with a stable identifier.

with_contextual_rule_fn plus the override identifier described on with_named_rule_fn.

Source

pub fn require_segment( self, tag: &'static str, rule_id: impl Into<Arc<str>>, ) -> Self

Add a rule that asserts segment tag is present at least once.

Emits an Error-severity issue when no segment with tag is found.

§Example
let pack = ProfileRulePack::new("MY-PROFILE")
    .require_segment("BGM", "MY-BGM-M")
    .require_segment("DTM", "MY-DTM-M");
Source

pub fn forbid_segment( self, tag: &'static str, rule_id: impl Into<Arc<str>>, ) -> Self

Add a rule that asserts segment tag does not appear.

Emits an Error-severity issue for each occurrence found.

Source

pub fn require_qualifier( self, tag: &'static str, element: u8, component: u8, qualifier: &'static str, rule_id: impl Into<Arc<str>>, ) -> Self

Add a rule that asserts data element de_qualifier at (element, component) equals qualifier for every occurrence of tag.

Source

pub fn with_group_rule_fn<F>(self, rule: F) -> Self
where F: Fn(&SegmentGroupIndexed<'_>, &[Segment<'_>], &ValidationRuleContext<'_>, &mut Vec<ValidationIssue>) + Send + Sync + 'static,

Add a group-aware rule closure that fires for every group node in the DFS traversal of the segment-group tree.

The closure receives:

  • group: &SegmentGroupIndexed — the current tree node (with definition, total_span, children).
  • group_segments: &[Segment<'_>] — all segments in this group’s subtree (all_segments[group.total_span.clone()]).
  • context: &ValidationRuleContext<'_> — per-call metadata and message info.
  • issues: &mut Vec<ValidationIssue> — push violations here.
§Group-name scoping

Use with_scoped_group_rule_fn when you only want the rule to fire for a specific group definition (e.g. "SG5").

Source

pub fn with_named_group_rule_fn<F>( self, id: impl Into<Arc<str>>, rule: F, ) -> Self
where F: Fn(&SegmentGroupIndexed<'_>, &[Segment<'_>], &ValidationRuleContext<'_>, &mut Vec<ValidationIssue>) + Send + Sync + 'static,

Add a named group-aware rule closure that fires for every group node.

Source

pub fn with_scoped_group_rule_fn<F>( self, group_scope: impl Into<Arc<str>>, id: impl Into<Arc<str>>, rule: F, ) -> Self
where F: Fn(&SegmentGroupIndexed<'_>, &[Segment<'_>], &ValidationRuleContext<'_>, &mut Vec<ValidationIssue>) + Send + Sync + 'static,

Add a named group-aware rule closure scoped to a specific group definition.

The closure is called only when the DFS traversal enters a group whose SegmentGroupIndexed::definition equals group_scope (e.g. "SG5").

Accepts any impl Into<Arc<str>> as group_scope, so both &'static str literals and owned Strings are valid.

§Example
let pack = ProfileRulePack::new("PROFILE-ORDERS")
    .with_scoped_group_rule_fn("SG5", "SG5-CAV-M", |_group, segs, _ctx, issues| {
        if !segs.iter().any(|s| s.tag == "CAV") {
            issues.push(
                ValidationIssue::new(ValidationSeverity::Error, "CAV missing in SG5")
                    .with_segment("CAV")
                    .with_rule_id("SG5-CAV-M"),
            );
        }
    });
Source

pub fn require_segment_in_group( self, group_scope: impl Into<Arc<str>>, tag: &'static str, rule_id: impl Into<Arc<str>>, ) -> Self

Assert segment tag is present in every occurrence of group group_scope.

For example, require_segment_in_group("SG5", "LOC", "SG5-LOC-M") fires once per SG5 instance that contains no LOC segment.

Issues are automatically annotated with the group name.

Accepts any impl Into<Arc<str>> as group_scope.

Source

pub fn forbid_segment_in_group( self, group_scope: impl Into<Arc<str>>, tag: &'static str, rule_id: impl Into<Arc<str>>, ) -> Self

Assert segment tag does not appear in any occurrence of group group_scope.

Emits an Error-severity issue for each occurrence found.

Accepts any impl Into<Arc<str>> as group_scope.

Source

pub fn require_qualifier_in_group( self, group_scope: impl Into<Arc<str>>, tag: &'static str, element: u8, component: u8, qualifier: &'static str, rule_id: impl Into<Arc<str>>, ) -> Self

Assert qualifier qualifier at (element, component) in segment tag is present in every occurrence of group group_scope.

Accepts any impl Into<Arc<str>> as group_scope.

Source

pub fn group_rule_count(&self) -> usize

Return the number of group-scoped rules in this pack.

Source

pub fn with_rule(self, rule: impl ProfileRule + 'static) -> Self

Add a rule that implements ProfileRule.

Source

pub fn with_named_rule( self, id: impl Into<Arc<str>>, rule: impl ProfileRule + 'static, ) -> Self

Add a named rule that implements ProfileRule.

Source

pub fn extend_from(self, base: &ProfileRulePack) -> Result<Self, EdifactError>

Prepend all rules from base to this pack.

Rules from base are shared (via Arc cloning) and run first. Message-type restrictions from base are also merged. The resulting release scope must be compatible with both packs.

§Errors

Returns EdifactError::IncompatibleReleaseScopes if both packs specify different release scopes.

§Example
let base = ProfileRulePack::new("MIG-BASE")
    .with_rule_fn(/* mandatory segment rules */);

let profile_4711 = ProfileRulePack::new("PROFILE-4711")
    .extend_from(&base)?
    .with_rule_fn(/* 4711-specific rules */);

When your base pack is wrapped in an Arc you can dereference it:

use std::sync::Arc;

let base: Arc<ProfileRulePack> = Arc::new(
    ProfileRulePack::new("BASE").with_rule_fn(/* … */),
);

let derived = ProfileRulePack::new("DERIVED")
    .extend_from(&*base)?          // deref Arc<T> to &T
    .with_rule_fn(/* … */);
Source

pub fn merge_with_override(self, other: Self) -> Result<Self, EdifactError>

Merge other into self, with other taking precedence for any rule whose id already exists in self.

  • Rules in other that have a stable id matching a rule in self replace the rule at the same position in self.
  • Rules in other with no id, or with an id not present in self, are appended to self.
  • Rules present only in self (no matching override in other) are retained unchanged.
§Errors

Returns EdifactError::IncompatibleReleaseScopes if both packs specify different release scopes.

§Example
let base = ProfileRulePack::new("MIG-5.4")
    .with_named_rule_fn("PROFILE-4711-BGM-M", |segs, _issues| { /* old */ });

let delta = ProfileRulePack::new("MIG-5.5-delta")
    .with_named_rule_fn("PROFILE-4711-BGM-M", |segs, _issues| { /* updated */ });

// `result` runs the updated BGM-M rule only once:
let result = base.merge_with_override(delta)?;
assert_eq!(result.rule_count(), 1);

Trait Implementations§

Source§

impl Clone for ProfileRulePack

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ProfileRulePack

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Validator for ProfileRulePack

Source§

fn validate_batch( &self, segments: &[Segment<'_>], report: &mut ValidationReport, context: &ValidationRuleContext<'_>, )

Validate a full segment set and append issues to report.
Source§

fn validate_group_batch( &self, root: &SegmentGroupIndexed<'_>, all_segments: &[Segment<'_>], report: &mut ValidationReport, context: &ValidationRuleContext<'_>, )

Validate a segment-group tree and append issues to report. Read more
Source§

fn has_group_rules(&self) -> bool

Returns true if this validator has any group-scoped rules. Read more
Source§

fn fork(&self) -> Option<Box<dyn Validator + Send + Sync>>

Create a Box<dyn Validator> clone of this validator for context forking. Read more
Source§

fn set_message_type(&mut self, _message_type: Option<&str>)

Configure message-type metadata for validators that support explicit scoping.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<D> OwoColorize for D

Source§

fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>
where C: Color,

Set the foreground color generically Read more
Source§

fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>
where C: Color,

Set the background color generically. Read more
Source§

fn black(&self) -> FgColorDisplay<'_, Black, Self>

Change the foreground color to black
Source§

fn on_black(&self) -> BgColorDisplay<'_, Black, Self>

Change the background color to black
Source§

fn red(&self) -> FgColorDisplay<'_, Red, Self>

Change the foreground color to red
Source§

fn on_red(&self) -> BgColorDisplay<'_, Red, Self>

Change the background color to red
Source§

fn green(&self) -> FgColorDisplay<'_, Green, Self>

Change the foreground color to green
Source§

fn on_green(&self) -> BgColorDisplay<'_, Green, Self>

Change the background color to green
Source§

fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>

Change the foreground color to yellow
Source§

fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>

Change the background color to yellow
Source§

fn blue(&self) -> FgColorDisplay<'_, Blue, Self>

Change the foreground color to blue
Source§

fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>

Change the background color to blue
Source§

fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>

Change the foreground color to magenta
Source§

fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>

Change the background color to magenta
Source§

fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>

Change the foreground color to purple
Source§

fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>

Change the background color to purple
Source§

fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>

Change the foreground color to cyan
Source§

fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>

Change the background color to cyan
Source§

fn white(&self) -> FgColorDisplay<'_, White, Self>

Change the foreground color to white
Source§

fn on_white(&self) -> BgColorDisplay<'_, White, Self>

Change the background color to white
Source§

fn default_color(&self) -> FgColorDisplay<'_, Default, Self>

Change the foreground color to the terminal default
Source§

fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>

Change the background color to the terminal default
Source§

fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>

Change the foreground color to bright black
Source§

fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>

Change the background color to bright black
Source§

fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>

Change the foreground color to bright red
Source§

fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>

Change the background color to bright red
Source§

fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>

Change the foreground color to bright green
Source§

fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>

Change the background color to bright green
Source§

fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>

Change the foreground color to bright yellow
Source§

fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>

Change the background color to bright yellow
Source§

fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>

Change the foreground color to bright blue
Source§

fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>

Change the background color to bright blue
Source§

fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>

Change the foreground color to bright magenta
Source§

fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>

Change the background color to bright magenta
Source§

fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>

Change the foreground color to bright purple
Source§

fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>

Change the background color to bright purple
Source§

fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>

Change the foreground color to bright cyan
Source§

fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>

Change the background color to bright cyan
Source§

fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>

Change the foreground color to bright white
Source§

fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>

Change the background color to bright white
Source§

fn bold(&self) -> BoldDisplay<'_, Self>

Make the text bold
Source§

fn dimmed(&self) -> DimDisplay<'_, Self>

Make the text dim
Source§

fn italic(&self) -> ItalicDisplay<'_, Self>

Make the text italicized
Source§

fn underline(&self) -> UnderlineDisplay<'_, Self>

Make the text underlined
Make the text blink
Make the text blink (but fast!)
Source§

fn reversed(&self) -> ReversedDisplay<'_, Self>

Swap the foreground and background colors
Source§

fn hidden(&self) -> HiddenDisplay<'_, Self>

Hide the text
Source§

fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>

Cross out the text
Source§

fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>
where Color: DynColor,

Set the foreground color at runtime. Only use if you do not know which color will be used at compile-time. If the color is constant, use either OwoColorize::fg or a color-specific method, such as OwoColorize::green, Read more
Source§

fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>
where Color: DynColor,

Set the background color at runtime. Only use if you do not know what color to use at compile-time. If the color is constant, use either OwoColorize::bg or a color-specific method, such as OwoColorize::on_yellow, Read more
Source§

fn fg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> FgColorDisplay<'_, CustomColor<R, G, B>, Self>

Set the foreground color to a specific RGB value.
Source§

fn bg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> BgColorDisplay<'_, CustomColor<R, G, B>, Self>

Set the background color to a specific RGB value.
Source§

fn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self>

Sets the foreground color to an RGB value.
Source§

fn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self>

Sets the background color to an RGB value.
Source§

fn style(&self, style: Style) -> Styled<&Self>

Apply a runtime-determined style
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.