Skip to main content

MagicRule

Struct MagicRule 

Source
pub struct MagicRule {
    pub offset: OffsetSpec,
    pub typ: TypeKind,
    pub op: Operator,
    pub value: Value,
    pub message: String,
    pub children: Vec<MagicRule>,
    pub level: u32,
    pub strength_modifier: Option<StrengthModifier>,
    pub value_transform: Option<ValueTransform>,
}
Expand description

Magic rule representation in the AST

Fields§

§offset: OffsetSpec

Offset specification for where to read data

§typ: TypeKind

Type of data to read and interpret

§op: Operator

Comparison operator to apply

§value: Value

Expected value for comparison

§message: String

Human-readable message for this rule

§children: Vec<MagicRule>

Child rules that are evaluated if this rule matches

§level: u32

Indentation level for hierarchical rules

§strength_modifier: Option<StrengthModifier>

Optional strength modifier from !:strength directive

§value_transform: Option<ValueTransform>

Optional pre-comparison value transform from a magic-file type-suffix like lelong+1 or ulequad/1073741824. When set, the read value is transformed before op is evaluated and before the message’s %-format substitution, so format specifiers see the post-transform number.

#[serde(default)] keeps existing serialized AST snapshots (which never had this field) round-tripping correctly: missing fields deserialize to None, which means “no transform” – the historical behavior.

Implementations§

Source§

impl MagicRule

Source

pub const MAX_LEVEL: u32 = 1000

Hard structural ceiling on rule level.

This is a conservative upper bound enforced by MagicRule::validate to keep the AST shape sane: real magic files in the wild rarely exceed ~10 levels of nesting, so rejecting rules with level > 1000 catches obviously pathological input at construction time without constraining any legitimate rule.

This ceiling is independent of the evaluator’s EvaluationConfig::max_recursion_depth (default 20), which is the runtime recursion guard applied during rule evaluation. The evaluator limit is the first one that fires in practice – a rule tree with 50 levels passes this structural check but is aborted by the evaluator long before reaching MAX_LEVEL. The two limits serve different purposes: MAX_LEVEL is an AST-shape sanity check, and max_recursion_depth is a per-evaluation resource bound.

Source

pub fn new( offset: OffsetSpec, typ: TypeKind, op: Operator, value: Value, message: String, ) -> Self

Construct a top-level rule with no children and no strength modifier.

This is the most common constructor for programmatically building rules outside the parser. To add children, mutate MagicRule::children directly, or use MagicRule::with_children. To set a strength modifier, use MagicRule::with_strength_modifier.

§Examples
use libmagic_rs::{MagicRule, OffsetSpec, Operator, TypeKind, Value};

let rule = MagicRule::new(
    OffsetSpec::Absolute(0),
    TypeKind::Byte { signed: false },
    Operator::Equal,
    Value::Uint(0x7f),
    "ELF magic byte".to_string(),
);
assert_eq!(rule.level, 0);
assert!(rule.children.is_empty());
assert!(rule.validate().is_ok());
Source

pub fn with_children(self, children: Vec<MagicRule>) -> Self

Replace self.children with the given children and return the modified rule. Builder-style for chaining.

Source

pub const fn with_strength_modifier(self, modifier: StrengthModifier) -> Self

Set self.strength_modifier to the given value and return the modified rule. Builder-style for chaining.

Source

pub const fn with_level(self, level: u32) -> Self

Set self.level to the given value and return the modified rule. Builder-style for chaining; typically used only when constructing child rules programmatically.

Source

pub fn validate(&self) -> Result<(), MagicRuleValidationError>

Validate structural invariants of the rule.

This checks invariants that the parser enforces automatically but that programmatic constructors (especially via serde deserialize) can violate:

  • Message must not be empty.
  • level must not exceed Self::MAX_LEVEL.
  • Every child’s level must be strictly greater than self.level, and each child must recursively validate.

This does not validate that value is shape-compatible with typ (e.g., a Value::Uint against a TypeKind::String); such mismatches are coerced or rejected by the evaluator at match time.

§Errors

Returns MagicRuleValidationError describing the first invariant violation encountered.

§Examples
use libmagic_rs::{MagicRule, OffsetSpec, Operator, TypeKind, Value};

let rule = MagicRule::new(
    OffsetSpec::Absolute(0),
    TypeKind::Byte { signed: false },
    Operator::Equal,
    Value::Uint(0),
    "zero byte".to_string(),
);
assert!(rule.validate().is_ok());

Trait Implementations§

Source§

impl Clone for MagicRule

Source§

fn clone(&self) -> MagicRule

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for MagicRule

Source§

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

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

impl<'de> Deserialize<'de> for MagicRule

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for MagicRule

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

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<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 = Infallible

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.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,