Skip to content

feat(parser): implement quad 64-bit integer type with endian variants#133

Merged
unclesp1d3r merged 13 commits into
mainfrom
36-parser-implement-quad-64-bit-integer-type-with-endian-variants
Mar 2, 2026
Merged

feat(parser): implement quad 64-bit integer type with endian variants#133
unclesp1d3r merged 13 commits into
mainfrom
36-parser-implement-quad-64-bit-integer-type-with-endian-variants

Conversation

@unclesp1d3r
Copy link
Copy Markdown
Member

@unclesp1d3r unclesp1d3r commented Mar 2, 2026

This pull request adds support for 64-bit integer types (quad/uquad) throughout the codebase, including parsing, evaluation, type system, and documentation. It also includes Phase 1 architecture refactoring from the architecture review.

Breaking Changes

Quad (64-bit integer) type support

  • Added TypeKind::Quad { endian, signed } to the type system, enabling parsing and evaluation of 64-bit integers with endianness and signedness options
  • Implemented read_quad for safe reading of 64-bit integers from buffers with endianness and signedness support
  • Updated strength calculation to assign appropriate specificity to quad types
  • Added comprehensive tests for quad type serialization, reading, coercion, and error handling

Architecture refactoring (Phase 1)

  • Extracted type parsing (src/parser/types.rs): Moved type keyword parsing (parse_type_keyword) and type-to-kind conversion (type_keyword_to_kind) from grammar.rs into a focused module, reducing grammar.rs complexity
  • Unified serialization (src/parser/codegen.rs): Consolidated 16 duplicated serialization functions from build.rs and build_helpers.rs into a shared codegen.rs module, eliminating the need to update both files when adding enum variants
  • Renamed evaluator::MatchResult to RuleMatch (issue refactor: rename evaluator::MatchResult to disambiguate from output::MatchResult #60): Resolved naming collision with output::MatchResult

Documentation and roadmap updates

  • Updated AGENTS.md to reflect quad type support, new module structure, and updated architecture constraints
  • Clarified Mergify auto-merge behavior: dependabot/dosubot require full CI, release-plz requires only DCO check
  • Marked quad roadmap item as complete

Other improvements

  • Improved buffer overrun error checking in type reading functions
  • Enhanced value coercion logic to handle quad types

Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
@unclesp1d3r unclesp1d3r self-assigned this Mar 2, 2026
Copilot AI review requested due to automatic review settings March 2, 2026 04:50
@unclesp1d3r unclesp1d3r linked an issue Mar 2, 2026 that may be closed by this pull request
7 tasks
@dosubot dosubot Bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Mar 2, 2026
@dosubot dosubot Bot added evaluator Rule evaluation engine and logic parser Magic file parsing components and grammar labels Mar 2, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 2, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 265a614 and 3c3f8ed.

📒 Files selected for processing (22)
  • AGENTS.md
  • ROADMAP.md
  • build.rs
  • dist-workspace.toml
  • docs/API_REFERENCE.md
  • docs/ARCHITECTURE.md
  • docs/MAGIC_FORMAT.md
  • docs/src/architecture.md
  • docs/src/ast-structures.md
  • src/build_helpers.rs
  • src/evaluator/mod.rs
  • src/evaluator/strength.rs
  • src/evaluator/types.rs
  • src/lib.rs
  • src/output/mod.rs
  • src/parser/ast.rs
  • src/parser/codegen.rs
  • src/parser/grammar.rs
  • src/parser/mod.rs
  • src/parser/types.rs
  • tests/integration_tests.rs
  • tests/property_tests.rs

Summary by CodeRabbit

  • New Features

    • Added 64-bit "quad" integer support (signed/unsigned, native/LE/BE), parsing, matching, and indirect-offset (.q) usage with examples.
  • Breaking Changes

    • Public evaluation result type renamed (API surface updated).
  • Documentation

    • Updated API reference, format docs, architecture, and roadmap to reflect quad support and usage.
  • Tests

    • Added unit, property, and end-to-end tests covering quad parsing, reading, coercion, strength scoring, and matching.
  • Refactor

    • Build-time generation now uses a shared code-generation path for builtin rules.

Walkthrough

Adds a 64-bit integer TypeKind::Quad { endian, signed }, refactors parser into grammar/types/codegen, moves built-in rules generation to parser::codegen for build-time codegen, updates evaluator (read/coerce/strength) for Quad, renames MatchResult→RuleMatch across API, and extends tests/docs for Quad support.

Changes

Cohort / File(s) Summary
Type System
src/parser/ast.rs
Adds public TypeKind::Quad { endian: Endianness, signed: bool }.
Parser: grammar & types
src/parser/grammar.rs, src/parser/types.rs
Introduces unsigned number parsing, parse_type_and_operator, new quad keywords (quad, uquad, lequad, ulequad, bequad, ubequad) and mapping to TypeKind.
Codegen / Build-time serialization
src/parser/codegen.rs, src/parser/mod.rs, build.rs, src/build_helpers.rs
New parser::codegen module exposes generate_builtin_rules; build and helpers now delegate serialization to codegen; large inline serializers removed; codegen made pub(crate) and test re-exports added.
Evaluator: reading, coercion, strength
src/evaluator/types.rs, src/evaluator/strength.rs
Adds read_quad(...) with endian and signed support; integrates Quad into read_typed_value and coerce_value_to_type; adds Quad base specificity in strength calc.
API surface & naming
src/evaluator/mod.rs, src/lib.rs, src/output/mod.rs
Renames public MatchResultRuleMatch and updates re-exports, function signatures, return types, and output conversion sites.
Tests & Integration
tests/integration_tests.rs, tests/property_tests.rs, src/build_helpers.rs (tests)
Adds unit/integration/property tests for Quad parsing, reading, coercion, strength, and build-time serialization coverage.
Docs & Roadmap
AGENTS.md, ROADMAP.md, docs/*
Docs updated to document quad/unsigned variants, examples, architecture notes; roadmap marks Quad complete; CI/merge wording adjusted.
CI config
dist-workspace.toml
Bumps GitHub Action actions/upload-artifact from v6.0.0v7.0.0.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Grammar as Parser::grammar
participant Types as Parser::types
participant Codegen as Parser::codegen
participant Build as build.rs
participant Eval as Evaluator
participant Output as Output
Note over Grammar,Types: Build-time parsing and codegen flow
Grammar->>Types: parse_type_keyword / parse_type_and_operator
Types-->>Grammar: produce TypeKind::Quad (endian, signed)
Grammar->>Codegen: provide parsed AST (MagicRule with Quad)
Codegen->>Build: generate_builtin_rules() -> Rust source
Build->>Codegen: write/include generated source
Note over Build,Eval: runtime compiled artifact
Eval->>Eval: read_quad(buffer, offset, endian, signed)
Eval->>Output: construct RuleMatch results

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I hopped through grammar, nibbling bits of code,
Sixty-four bits snug in my tote, le/BE and signed or not,
Rules baked at build-time, serialized neat,
Tests pass, renames settle—carrot treats for the fleet,
Hop, merge, repeat, the magic feels sweet!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: implementing 64-bit quad integer type support with endian variants.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, covering quad type support, architecture refactoring, and the MatchResult→RuleMatch rename.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 36-parser-implement-quad-64-bit-integer-type-with-endian-variants

Comment @coderabbitai help to get the list of available commands and usage tips.

@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented Mar 2, 2026

Merge Protections

Your pull request matches the following merge protections and will not be merged until they are valid.

🟢 CI must pass

Wonderful, this rule succeeded.

All CI checks must pass. Release-plz PRs are exempt because they only bump versions and changelogs (code was already tested on main), and GITHUB_TOKEN-triggered force-pushes suppress CI.

  • check-success = coverage
  • check-success = quality
  • check-success = test
  • check-success = test-cross-platform (macos-latest, macOS)
  • check-success = test-cross-platform (ubuntu-22.04, Linux)
  • check-success = test-cross-platform (ubuntu-latest, Linux)
  • check-success = test-cross-platform (windows-latest, Windows)

🟢 Do not merge outdated PRs

Wonderful, this rule succeeded.

Make sure PRs are within 10 commits of the base branch before merging

  • #commits-behind <= 3

Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class support for libmagic’s 64-bit integer types (quad / uquad) across parsing, AST/type system, evaluation, and strength scoring, with accompanying tests and documentation updates.

Changes:

  • Extend the type system and parser to recognize quad/uquad with endian variants and full-width &mask parsing.
  • Implement safe 64-bit reads in the evaluator and integrate Quad into typed reads, coercion, and strength scoring.
  • Add/extend unit + integration tests and update roadmap/agent documentation to reflect completed quad support.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/property_tests.rs Generates TypeKind::Quad and endianness variants for proptest coverage.
tests/integration_tests.rs Adds end-to-end tests for lequad/bequad/signed quad and nested-rule offset behavior.
src/parser/grammar.rs Adds unsigned numeric parsing for full u64 literal range; extends type parsing for quad + full-width &mask.
src/parser/ast.rs Introduces TypeKind::Quad { endian, signed } and updates serialization tests.
src/evaluator/types.rs Adds read_quad, strengthens bounds checks, wires quad into typed reads and coercion logic, adds tests.
src/evaluator/strength.rs Assigns default strength for quad types and adds a targeted test.
src/build_helpers.rs Updates build-time serialization helpers + tests for the new TypeKind::Quad variant.
build.rs Mirrors TypeKind::Quad serialization for build-time rule compilation.
ROADMAP.md Marks quad support as completed.
AGENTS.md Documents quad support and updates process/merge-policy notes.

Comment thread AGENTS.md Outdated
@dosubot
Copy link
Copy Markdown
Contributor

dosubot Bot commented Mar 2, 2026

Documentation Updates

11 document(s) were updated by changes in this PR:

api-reference
View Changes
@@ -369,9 +369,31 @@
 | `timeout_ms()` | Get timeout value |
 | `reset()` | Reset to initial state |
 
-### MatchResult (Evaluator)
-
-**Note**: This type was removed in v0.3.0. Match results are handled internally and exposed through the `output::MatchResult` type.
+### RuleMatch (Evaluator)
+
+Internal match result type used during rule evaluation. Renamed from `MatchResult` to `RuleMatch` in v0.3.0 to resolve a naming collision with `output::MatchResult`.
+
+```rust
+use libmagic_rs::RuleMatch;
+```
+
+#### Fields
+
+| Field | Type | Description |
+|-------|------|-------------|
+| `message` | `String` | Rule message |
+| `offset` | `usize` | Match offset |
+| `level` | `u32` | Rule nesting level |
+| `value` | `Value` | Matched value |
+| `confidence` | `f64` | Confidence score (0.0-1.0) |
+
+#### Methods
+
+| Method | Description |
+|--------|-------------|
+| `calculate_confidence(level)` | Calculate confidence from rule depth |
+
+**Note**: This type is used internally by the evaluator. User-facing code should use `output::MatchResult` for formatted output.
 
 ## Output Module
 
@@ -449,7 +471,7 @@
 pub use parser::ast::{Endianness, MagicRule, OffsetSpec, Operator, StrengthModifier, TypeKind, Value};
 
 // Evaluator types
-pub use evaluator::EvaluationContext;
+pub use evaluator::{EvaluationContext, RuleMatch};
 
 // Error types
 pub use error::{EvaluationError, LibmagicError, ParseError};
@@ -472,6 +494,7 @@
 
 - `TypeKind::Quad` variant added to support 64-bit quad integer types (breaking change due to exhaustive enum)
 - `TypeKind::String` discriminant changed from 3 to 4 due to insertion of `Quad` variant
+- `evaluator::MatchResult` renamed to `evaluator::RuleMatch` to resolve naming collision with `output::MatchResult`
 
 ### Breaking Changes in v0.2.0
 
Checked Arithmetic For Buffer Offset Safety
View Changes
@@ -4,7 +4,7 @@
 
 This pattern forms a critical component of libmagic-rs's [defense-in-depth security architecture](https://app.dosu.dev/documents/1fcbd1b5-e08c-4410-9892-4bc89593d6b5), which forbids unsafe code at the workspace level and requires that all library code handle errors gracefully without panicking. When processing potentially malicious file input, unchecked integer arithmetic in offset calculations could allow attackers to craft files that trigger overflow, wrapping offset values to bypass bounds checks and access arbitrary memory. By using `.get()` with range syntax, the pattern leverages Rust's built-in overflow protection—range construction saturates on overflow, creating invalid ranges that `.get()` rejects by returning `None`.
 
-The pattern applies to all [type-read functions in `src/evaluator/types.rs`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/evaluator/types.rs): `read_byte`, `read_short`, `read_long`, and `read_string`. It represents durable architectural knowledge that must be followed by all current and future type readers to maintain the project's memory safety guarantees.
+The pattern applies to all [type-read functions in `src/evaluator/types.rs`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/evaluator/types.rs): `read_byte`, `read_short`, `read_long`, `read_quad`, and `read_string`. It represents durable architectural knowledge that must be followed by all current and future type readers to maintain the project's memory safety guarantees.
 
 ## The Problem: Integer Overflow in Buffer Offset Arithmetic
 
@@ -55,7 +55,9 @@
 
 ### Core Pattern
 
-All type-read functions follow this pattern:
+Type-read functions use one of two patterns depending on implementation needs:
+
+**Pattern 1: Direct Range Construction (used by `read_short` and `read_long` before PR #133)**
 
 ```rust
 pub fn read_short(
@@ -75,15 +77,50 @@
 }
 ```
 
-The key safety properties:
-
-1. **Range saturation**: When `offset + 2` would overflow, Rust's range construction saturates, creating an invalid range (e.g., `usize::MAX..usize::MAX`)
+**Pattern 2: Explicit Checked Addition (used by `read_short`, `read_long`, and `read_quad`)**
+
+```rust
+pub fn read_quad(
+    buffer: &[u8],
+    offset: usize,
+    endian: Endianness,
+    signed: bool,
+) -> Result<Value, TypeReadError> {
+    let end = offset.checked_add(8).ok_or(TypeReadError::BufferOverrun {
+        offset,
+        buffer_len: buffer.len(),
+    })?;
+    let bytes = buffer
+        .get(offset..end)
+        .ok_or(TypeReadError::BufferOverrun {
+            offset,
+            buffer_len: buffer.len(),
+        })?;
+    
+    // Endianness handling...
+}
+```
+
+Both patterns provide equivalent safety guarantees but differ in their approach:
+
+- **Pattern 1** relies on Rust's implicit range saturation: when `offset + N` overflows, the range constructor saturates, creating an invalid range that `.get()` rejects
+- **Pattern 2** uses explicit `checked_add()` to detect overflow before range construction, making the overflow check visible in the code
+
+Pattern 2 is preferred for clarity—it makes the overflow protection explicit rather than relying on implicit saturation behavior. The explicit check also satisfies the `arithmetic_side_effects` lint, which warns about potentially overflowing operations.
+
+The key safety properties (shared by both patterns):
+
+1. **Overflow protection**: Overflow is detected either through explicit `checked_add()` or implicit range saturation
 2. **Bounds validation**: `.get()` checks whether the range is valid and within buffer bounds, returning `None` for invalid ranges
 3. **Error conversion**: The pattern converts `None` to a structured [`TypeReadError::BufferOverrun`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/evaluator/types.rs#L20-L25) error
 4. **No panics**: All error conditions return `Result` types, enabling [graceful error handling](https://app.dosu.dev/documents/e87d2c6e)
 5. **No unsafe code**: The pattern operates entirely within Rust's safe subset
 
-### How Range Saturation Works
+### How Overflow Protection Works
+
+Both patterns protect against integer overflow, but through different mechanisms:
+
+**Implicit Range Saturation (Pattern 1)**
 
 Rust's range expressions use [saturating arithmetic internally](https://doc.rust-lang.org/std/ops/struct.Range.html). When constructing `offset..offset + N`:
 
@@ -92,7 +129,14 @@
 - Such ranges are empty by definition and invalid for indexing
 - `.get()` recognizes the invalid range and returns `None`
 
-This behavior provides automatic overflow protection without explicit checked arithmetic calls.
+**Explicit Checked Addition (Pattern 2)**
+
+The `checked_add()` method explicitly checks for overflow:
+
+- `offset.checked_add(N)` returns `Some(end)` if the addition succeeds
+- Returns `None` if the addition would overflow
+- The overflow is caught before range construction
+- The explicit check makes the safety property visible in code and satisfies linter warnings
 
 ## Implementation in Type-Read Functions
 
@@ -133,8 +177,12 @@
     endian: Endianness,
     signed: bool,
 ) -> Result<Value, TypeReadError> {
+    let end = offset.checked_add(2).ok_or(TypeReadError::BufferOverrun {
+        offset,
+        buffer_len: buffer.len(),
+    })?;
     let bytes = buffer
-        .get(offset..offset + 2)
+        .get(offset..end)
         .ok_or(TypeReadError::BufferOverrun {
             offset,
             buffer_len: buffer.len(),
@@ -154,7 +202,7 @@
 }
 ```
 
-The pattern `offset..offset + 2` safely handles the case where `offset > usize::MAX - 2`, returning `None` instead of wrapping.
+The explicit `checked_add(2)` detects overflow before constructing the range, ensuring that `offset > usize::MAX - 2` is caught and converted to a `BufferOverrun` error.
 
 ### read_long: 32-bit Access
 
@@ -167,8 +215,12 @@
     endian: Endianness,
     signed: bool,
 ) -> Result<Value, TypeReadError> {
+    let end = offset.checked_add(4).ok_or(TypeReadError::BufferOverrun {
+        offset,
+        buffer_len: buffer.len(),
+    })?;
     let bytes = buffer
-        .get(offset..offset + 4)
+        .get(offset..end)
         .ok_or(TypeReadError::BufferOverrun {
             offset,
             buffer_len: buffer.len(),
@@ -187,6 +239,45 @@
     }
 }
 ```
+
+### read_quad: 64-bit Access
+
+[`read_quad`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/evaluator/types.rs) reads eight bytes for 64-bit integer types:
+
+```rust
+pub fn read_quad(
+    buffer: &[u8],
+    offset: usize,
+    endian: Endianness,
+    signed: bool,
+) -> Result<Value, TypeReadError> {
+    let end = offset.checked_add(8).ok_or(TypeReadError::BufferOverrun {
+        offset,
+        buffer_len: buffer.len(),
+    })?;
+    let bytes = buffer
+        .get(offset..end)
+        .ok_or(TypeReadError::BufferOverrun {
+            offset,
+            buffer_len: buffer.len(),
+        })?;
+
+    let value = match endian {
+        Endianness::Little => LittleEndian::read_u64(bytes),
+        Endianness::Big => BigEndian::read_u64(bytes),
+        Endianness::Native => NativeEndian::read_u64(bytes),
+    };
+
+    if signed {
+        #[allow(clippy::cast_possible_wrap)]
+        Ok(Value::Int(value as i64))
+    } else {
+        Ok(Value::Uint(value))
+    }
+}
+```
+
+The quad reader uses the explicit `checked_add` pattern consistently with `read_short` and `read_long`. This two-stage approach—explicit overflow check followed by bounds-checked slice access—makes the safety properties clear and satisfies the `arithmetic_side_effects` lint.
 
 ### read_string: Variable-Length Access
 
@@ -296,27 +387,28 @@
 
 ## Future Applicability
 
-The checked arithmetic pattern represents a durable architectural requirement that must be followed by all type readers, including those not yet implemented. The [current `TypeKind` enum](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/evaluator/types.rs#L364-L369) supports `Byte`, `Short`, `Long`, and `String` types, but future extensions will require additional readers.
+The checked arithmetic pattern represents a durable architectural requirement that must be followed by all type readers. The [current `TypeKind` enum](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/evaluator/types.rs#L364-L369) supports `Byte`, `Short`, `Long`, `Quad`, and `String` types, with future extensions requiring additional readers.
 
 ### Planned Type Readers
 
 Future type readers must follow the same pattern:
 
-- **64-bit integers (quad)**: Would use `buffer.get(offset..offset + 8)`
-- **Floating-point (float)**: Would use `buffer.get(offset..offset + 4)` for IEEE 754 single precision
-- **Double-precision (double)**: Would use `buffer.get(offset..offset + 8)` for IEEE 754 double precision
+- **Floating-point (float)**: Would use `checked_add(4)` for IEEE 754 single precision
+- **Double-precision (double)**: Would use `checked_add(8)` for IEEE 754 double precision
 - **Date types**: Variable size depending on format, would follow `read_string` pattern
 
 ### Pattern Requirements
 
 Any new type reader must:
 
-1. Use `.get()` with range expressions for multi-byte access
-2. Return `TypeReadError::BufferOverrun` on bounds check failure
-3. Avoid explicit checked arithmetic calls (let range construction handle overflow)
+1. Use explicit `checked_add()` for offset arithmetic (preferred) or rely on implicit range saturation
+2. Use `.get()` with range expressions for multi-byte access
+3. Return `TypeReadError::BufferOverrun` on bounds check failure
 4. Return `Result<Value, TypeReadError>` for error handling
 5. Include documentation of security guarantees
 6. Avoid `unwrap()`, `expect()`, or panic calls
+
+The explicit `checked_add()` pattern (Pattern 2) is preferred for clarity and linter compatibility, as demonstrated by `read_quad`, `read_short`, and `read_long`.
 
 ### Enforcement
 
@@ -333,7 +425,7 @@
 
 | File | Purpose | Key Elements |
 |------|---------|--------------|
-| [`src/evaluator/types.rs`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/evaluator/types.rs) | Type-read functions | `read_byte`, `read_short`, `read_long`, `read_string`, `TypeReadError` enum |
+| [`src/evaluator/types.rs`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/evaluator/types.rs) | Type-read functions | `read_byte`, `read_short`, `read_long`, `read_quad`, `read_string`, `TypeReadError` enum |
 | [`Cargo.toml` (lines 32-140)](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/Cargo.toml#L32-L140) | Workspace lint enforcement | [`unsafe_code = "forbid"`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/Cargo.toml#L34), [`indexing_slicing`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/Cargo.toml#L51), [`arithmetic_side_effects`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/Cargo.toml#L52), [`panic = "deny"`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/Cargo.toml#L65), [`unwrap_used = "deny"`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/Cargo.toml#L66) |
 
 ## Related Topics
evaluator
View Changes
@@ -49,12 +49,12 @@
 - `timeout_ms()` - Query configured timeout
 - `reset()` - Reset context state for reuse
 
-### MatchResult (`evaluator/mod.rs`)
+### RuleMatch (`evaluator/mod.rs`)
 
 Represents a successful rule match:
 
 ```rust
-pub struct MatchResult {
+pub struct RuleMatch {
     /// Human-readable description from the matched rule
     pub message: String,
     /// Offset where the match occurred
@@ -93,6 +93,7 @@
 - **Byte**: Single byte values (signed or unsigned)
 - **Short**: 16-bit integers with endianness
 - **Long**: 32-bit integers with endianness
+- **Quad**: 64-bit integers with endianness
 - **String**: Byte sequences with length limits
 - **Bounds checking**: Prevents buffer overruns
 
@@ -165,7 +166,7 @@
 pub fn evaluate_rules(
     rules: &[MagicRule],
     buffer: &[u8],
-) -> Result<Vec<MatchResult>, EvaluationError>
+) -> Result<Vec<RuleMatch>, EvaluationError>
 ```
 
 **Algorithm:**
@@ -281,14 +282,14 @@
     rules: &[MagicRule],
     buffer: &[u8],
     context: &mut EvaluationContext,
-) -> Result<Vec<MatchResult>, LibmagicError>;
+) -> Result<Vec<RuleMatch>, LibmagicError>;
 
 /// Evaluate rules with custom configuration (creates context internally)
 pub fn evaluate_rules_with_config(
     rules: &[MagicRule],
     buffer: &[u8],
     config: &EvaluationConfig,
-) -> Result<Vec<MatchResult>, LibmagicError>;
+) -> Result<Vec<RuleMatch>, LibmagicError>;
 
 /// Evaluate a single rule (used internally and for testing)
 pub fn evaluate_single_rule(
@@ -346,7 +347,7 @@
 
 - [x] Basic evaluation engine structure
 - [x] Offset resolution (absolute, relative, from-end)
-- [x] Type reading with endianness support (Byte, Short, Long, String)
+- [x] Type reading with endianness support (Byte, Short, Long, Quad, String)
 - [x] Operator application (Equal, NotEqual, LessThan, GreaterThan, LessEqual, GreaterEqual, BitwiseAnd, BitwiseAndMask)
 - [x] Hierarchical rule processing with child evaluation
 - [x] Error handling with graceful degradation
GETTING_STARTED
View Changes
@@ -24,7 +24,7 @@
 libmagic-rs = "0.3.0"
 ```
 
-**Note:** Version 0.3.0 introduces breaking changes. If upgrading from 0.2.x, note that a new `TypeKind::Quad` enum variant was added for 64-bit quad integer types with endian variants, `TypeKind::String` variant discriminant changed from 3 to 4, and `MatchResult` struct was removed from `libmagic_rs::evaluator`. Exhaustive pattern matching on `TypeKind` requires updates.
+**Note:** Version 0.3.0 introduces breaking changes. If upgrading from 0.2.x, note that a new `TypeKind::Quad` enum variant was added for 64-bit quad integer types with endian variants, `TypeKind::String` variant discriminant changed from 3 to 4, and `evaluator::MatchResult` was renamed to `evaluator::RuleMatch` to resolve a naming collision with `output::MatchResult`. The public re-export is `RuleMatch`. Exhaustive pattern matching on `TypeKind` requires updates.
 
 Version 0.2.0 introduced breaking changes from 0.1.x: `TypeKind::Byte` changed from a unit variant to a tuple variant, and the `Operator` enum gained new variants (`LessThan`, `GreaterThan`, `LessEqual`, `GreaterEqual`) for comparison operations.
 
library-api
View Changes
@@ -146,7 +146,7 @@
     pub description: String,          // Human-readable file type (or "data" if unknown)
     pub mime_type: Option<String>,    // MIME type (only when enable_mime_types is true)
     pub confidence: f64,              // 0.0 to 1.0, based on match depth
-    pub matches: Vec<MatchResult>,    // Individual rule matches with offset/level/value
+    pub matches: Vec<RuleMatch>,      // Individual rule matches with offset/level/value
     pub metadata: EvaluationMetadata, // Diagnostics (timing, file size, etc.)
 }
 ```
magic-examples
View Changes
@@ -35,6 +35,14 @@
 0    string    \x7fELF    ELF
 >16  leshort   2         executable
 >18  leshort   62        x86-64
+
+# 64-bit file signature matching
+0    lequad    0x1234567890abcdef    Custom format with 64-bit magic
+0    bequad    0xfeedface00000000    Mach-O universal binary signature
+
+# Large integer value checks
+512  uquad     >0x8000000000000000    Large unsigned 64-bit value
+1024 quad      0xffffffffffffffff    Signed 64-bit match
 ```
 
 ## Hierarchical Rules
@@ -79,14 +87,25 @@
 # Little-endian integers
 0    leshort   0x5a4d    MS-DOS executable (little-endian short)
 0    lelong    0x464c457f    ELF (little-endian long)
+0    lequad    0x1234567890abcdef    64-bit little-endian value
 
 # Big-endian integers
 0    beshort   0x4d5a    MS-DOS executable (big-endian short)
 0    belong    0x7f454c46    ELF (big-endian long)
+0    bequad    0xfeedface00000000    64-bit big-endian value
 
 # Native endian (system default)
 0    short     0x5a4d    MS-DOS executable (native endian)
 0    long      0x464c457f    ELF (native endian)
+0    quad      0xffffffffffffffff    64-bit native endian
+
+# Unsigned variants
+0    ubyte     0xff      Unsigned byte
+0    ushort    0xffff    Unsigned short
+0    ulong     0xffffffff    Unsigned long
+0    uquad     0xffffffffffffffff    Unsigned 64-bit value
+0    ulequad   >0x8000000000000000    Unsigned little-endian quad
+0    ubequad   >0x8000000000000000    Unsigned big-endian quad
 ```
 
 ### String Matching
magic-format
View Changes
@@ -101,6 +101,7 @@
 - `.b` - byte (1 byte)
 - `.s` - short (2 bytes)
 - `.l` - long (4 bytes)
+- `.q` - quad (8 bytes)
 
 ### Relative Offset
 
@@ -126,12 +127,22 @@
 | `long` | 4 bytes | native |
 | `lelong` | 4 bytes | little-endian |
 | `belong` | 4 bytes | big-endian |
+| `quad` | 8 bytes | native |
+| `lequad` | 8 bytes | little-endian |
+| `bequad` | 8 bytes | big-endian |
+
+All integer types have unsigned variants prefixed with `u`:
+- `ubyte`, `ushort`, `uleshort`, `ubeshort`
+- `ulong`, `ulelong`, `ubelong`
+- `uquad`, `ulequad`, `ubequad`
 
 Examples:
 ```
 0       byte      0x7f      (byte match)
 0       leshort   0x5a4d    DOS MZ signature
 0       belong    0xcafebabe Java class file
+0       lequad    0x1234567890abcdef  (64-bit little-endian)
+8       uquad     >0x8000000000000000 (unsigned 64-bit check)
 ```
 
 ### String Type
@@ -439,7 +450,7 @@
 - Absolute offsets
 - Relative offsets
 - Indirect offsets (basic)
-- Byte, short, long types
+- Byte, short, long, quad types (8-bit, 16-bit, 32-bit, 64-bit integers)
 - String type
 - Comparison operators (equal, not-equal, less-than, greater-than, less-equal, greater-equal)
 - Bitwise AND operator
@@ -451,12 +462,14 @@
 - Regex patterns
 - Date/time types
 - Float types
+- 128-bit integer types
 - Use/name directives
 - Default rules
 
 ### Recently Added
 
 - **Strength modifiers**: The `!:strength` directive for adjusting rule priority
+- **64-bit integers**: `quad` type family (`quad`, `uquad`, `lequad`, `ulequad`, `bequad`, `ubequad`)
 
 ## Troubleshooting
 
Nom Alt Combinator Branch Limit And Nesting Pattern
View Changes
@@ -4,7 +4,7 @@
 
 The **Nom Alt Combinator Branch Limit And Nesting Pattern** is an architectural design pattern used in parser implementation to address potential scaling constraints when using the [nom parser combinator library](https://github.com/Geal/nom). The pattern involves organizing parser alternatives into hierarchical groups (typically by type family or bit-width) and nesting `alt()` combinators to ensure each individual `alt()` call stays within nom's compile-time limitations while maintaining parser correctness through careful ordering conventions.
 
-In [libmagic-rs](https://github.com/EvilBit-Labs/libmagic-rs), this pattern was identified as a critical architectural consideration for the [parse_type_and_operator function (src/parser/grammar.rs:1549-1643)](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/grammar.rs#L1549-L1643) during planning for type system expansion. The current implementation uses [a single `alt()` with 17 type name branches](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/grammar.rs#L1552-L1570), but [the roadmap targets expansion to ~31 types by v1.0.0](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/ROADMAP.md#L28-L37), which would require restructuring to avoid exceeding tuple size constraints.
+In [libmagic-rs](https://github.com/EvilBit-Labs/libmagic-rs), this pattern was identified as a critical architectural consideration during planning for type system expansion. The current implementation in [src/parser/types.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/types.rs) uses nested `alt()` combinators with 23 type name tokens organized into 5 family groups (64-bit, 32-bit, 16-bit, 8-bit, and string), but [the roadmap targets expansion to ~31 types by v1.0.0](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/ROADMAP.md#L28-L37), which would require adding additional family groups to avoid exceeding tuple size constraints.
 
 The pattern emphasizes two ordering conventions: **longer prefixes before shorter** (to prevent premature matching, e.g., `lelong` before `long`) and **unsigned before signed** (for documentation clarity and consistent family grouping). These conventions ensure correct tokenization when type names share common prefixes and maintain logical organization within type families.
 
@@ -12,11 +12,10 @@
 
 The nom parser combinator library implements `alt()` using Rust tuples, which have compile-time size limits based on trait implementations. While the exact limit varies by nom version and Rust compiler version, **practical limitations typically manifest around 21 alternatives** due to tuple trait bounds in the nom implementation.
 
-**Evidence in libmagic-rs**: No explicit documentation of hitting this limit exists in the current codebase. The [parse_type_and_operator function currently uses 17 branches](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/grammar.rs#L1552-L1570), and the [parse_operator function uses manual `if let` checks rather than `alt()`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/grammar.rs#L173-L248), though this appears to be for explicit precedence control rather than to work around tuple limits.
+**Evidence in libmagic-rs**: No explicit documentation of hitting this limit exists in the current codebase. The type parsing implementation in [src/parser/types.rs uses nested `alt()` calls](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/types.rs#L43-L76) with 23 type name tokens organized into 5 family groups, and the [parse_operator function uses manual `if let` checks rather than `alt()`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/grammar.rs#L173-L248), though this appears to be for explicit precedence control rather than to work around tuple limits.
 
 The constraint becomes relevant when considering the [type system expansion roadmap](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/ROADMAP.md#L28-L37):
-- **Current**: 4 type variants (Byte, Short, Long, String) expanding to 17 type name tokens
-- **v0.2.0**: Add Quad types (6 additional tokens)
+- **Current**: 5 type variants (Byte, Short, Long, Quad, String) expanding to 23 type name tokens
 - **v0.3.0+**: Add Float, Double, Date, Pstring, Regex, Search types with endianness variants (20+ additional tokens)
 - **Target**: ~31 of 33 libmagic types by v1.0.0
 
@@ -28,8 +27,8 @@
 
 The nesting pattern groups types by **bit-width families** to create logical parser organization:
 
-**64-bit Family** (planned for v0.2.0):
-- [Quad types: `quad`, `lequad`, `bequad`, `uquad`, `ulequad`, `ubequad`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/ROADMAP.md#L28)
+**64-bit Family** (currently implemented):
+- [Quad types: `quad`, `lequad`, `bequad`, `uquad`, `ulequad`, `ubequad`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/types.rs#L43-L52)
 
 **32-bit Family** (currently implemented):
 - [Long types: `long`, `lelong`, `belong`, `ulong`, `ulelong`, `ubelong`](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/grammar.rs#L1552-L1570)
@@ -51,35 +50,46 @@
 
 ### Current Implementation Structure
 
-The [current parse_type_and_operator implementation (lines 1549-1643)](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/grammar.rs#L1549-L1643) uses a flat structure:
+The current type parsing implementation (in [src/parser/types.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/types.rs)) uses a nested structure with 23 type name tokens organized into family groups. The quad types (6 variants) were added as a nested `alt()` within the outer structure:
 
 ```rust
-let (input, type_name) = alt((
-    // 32-bit unsigned
-    tag("ubelong"),
-    tag("ulelong"),
-    tag("ulong"),
-    // 16-bit unsigned
-    tag("ubeshort"),
-    tag("uleshort"),
-    tag("ushort"),
-    // 8-bit unsigned
-    tag("ubyte"),
-    // 32-bit signed
-    tag("lelong"),
-    tag("belong"),
-    tag("long"),
-    // 16-bit signed
-    tag("leshort"),
-    tag("beshort"),
-    tag("short"),
-    // 8-bit signed
-    tag("byte"),
-    // String
+alt((
+    // 64-bit types (6 branches)
+    alt((
+        tag("ubequad"),
+        tag("ulequad"),
+        tag("uquad"),
+        tag("bequad"),
+        tag("lequad"),
+        tag("quad"),
+    )),
+    // 32-bit types (6 branches)
+    alt((
+        tag("ubelong"),
+        tag("ulelong"),
+        tag("ulong"),
+        tag("belong"),
+        tag("lelong"),
+        tag("long"),
+    )),
+    // 16-bit types (6 branches)
+    alt((
+        tag("ubeshort"),
+        tag("uleshort"),
+        tag("ushort"),
+        tag("beshort"),
+        tag("leshort"),
+        tag("short"),
+    )),
+    // 8-bit types (2 branches)
+    alt((tag("ubyte"), tag("byte"))),
+    // String types (1 branch)
     tag("string"),
 ))
-.parse(input)?;
-```
+.parse(input)
+```
+
+This structure demonstrates the nesting pattern in action: the 64-bit quad family was added as its own nested `alt()` group, keeping each inner `alt()` to 6 or fewer branches and the outer `alt()` to 5 families.
 
 ### Nested Pattern for Future Expansion
 
@@ -164,6 +174,8 @@
 
 **Correct ordering**:
 ```
+ubequad (7 chars) → bequad (6 chars) → quad (4 chars)
+ulequad (7 chars) → lequad (6 chars) → quad (4 chars)
 ubelong (7 chars) → belong (6 chars) → long (4 chars)
 ulelong (7 chars) → lelong (6 chars) → long (4 chars)
 ubeshort (8 chars) → beshort (7 chars) → short (5 chars)
@@ -172,7 +184,7 @@
 
 ### Unsigned Before Signed Within Families
 
-The current implementation [places unsigned variants (u-prefixed) before signed variants](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/grammar.rs#L1552-L1570) within each bit-width family. This convention provides:
+The current implementation [places unsigned variants (u-prefixed) before signed variants](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/types.rs#L43-L76) within each bit-width family. This convention provides:
 
 1. **Consistent family grouping**: All unsigned variants for a bit-width appear together, then all signed variants
 2. **Documentation clarity**: Readers can quickly identify all variants of each signedness
@@ -206,10 +218,10 @@
 The nesting pattern interacts with the [Enum Extension And Exhaustive Match Synchronization pattern](https://app.dosu.dev/documents/e6db8e51-ec58-458f-893a-e0c04ea79829). When adding a new type variant:
 
 1. **AST Definition**: [Add variant to `TypeKind` enum in src/parser/ast.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/ast.rs#L80-L107)
-2. **Parser Grammar**: Add type name tokens to appropriate family's nested `alt()` in [src/parser/grammar.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/grammar.rs#L1552-L1570), maintaining ordering conventions
+2. **Parser Grammar**: Add type name tokens to appropriate family's nested `alt()` in [src/parser/types.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/types.rs#L43-L76), maintaining ordering conventions
 3. **Type Reading**: Update [read_typed_value() dispatch in src/evaluator/types.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/evaluator/types.rs#L350-L361)
 4. **Strength Scoring**: Update pattern match in `src/evaluator/strength.rs`
-5. **Build-Time Serialization**: Update both `build.rs` and `src/build_helpers.rs`
+5. **Build-Time Serialization**: Update serialization in `src/parser/codegen.rs`
 6. **Property Tests**: Extend test strategies in `tests/property_tests.rs`
 
 [Rust's exhaustive pattern matching and Clippy warnings catch missed updates at compile time](https://github.com/EvilBit-Labs/libmagic-rs/pull/58).
@@ -249,7 +261,7 @@
 ### Extensibility Without Refactoring
 
 The nested pattern allows the type system to scale incrementally:
-- [Adding Quad types (v0.2.0)](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/ROADMAP.md#L28) requires introducing the 64-bit family nested `alt()`
+- Quad types (64-bit) were added using the nested structure, creating a new family group without requiring a full parser refactor
 - [Adding Float/Double types (v0.3.0)](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/ROADMAP.md#L34) requires introducing the floating-point family nested `alt()`
 - Each addition stays within the existing nested structure without requiring a full refactor
 
@@ -297,8 +309,8 @@
 
 | File | Description | Key Lines |
 |------|-------------|-----------|
-| [src/parser/grammar.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/grammar.rs) | Type parsing implementation with current flat `alt()` structure | 1549-1643 |
-| [src/parser/ast.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/ast.rs) | TypeKind enum definition with 4 current variants | 80-107 |
+| [src/parser/types.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/types.rs) | Type parsing implementation with nested `alt()` structure | 43-76 |
+| [src/parser/ast.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/parser/ast.rs) | TypeKind enum definition with 5 current variants including Quad | 80-117 |
 | [src/evaluator/types.rs](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/src/evaluator/types.rs) | Type reading dispatch requiring exhaustive matches | 350-361 |
 | [ROADMAP.md](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/ROADMAP.md) | Type system expansion plan showing 31-type target | 28-37 |
 | [docs/src/magic-format.md](https://github.com/EvilBit-Labs/libmagic-rs/blob/b589ab10df11f7e4d2b14dcb176d561ae25c089d/docs/src/magic-format.md) | Magic file format documentation listing not-yet-supported types | 449-456 |
output
View Changes
@@ -14,7 +14,7 @@
 
 ### `output::MatchResult`
 
-Represents a single magic rule match in the output layer. Created by converting from an evaluator-level `MatchResult`, with additional fields for structured output.
+Represents a single magic rule match in the output layer. Created by converting from an evaluator-level `RuleMatch`, with additional fields for structured output.
 
 ```rust
 pub struct MatchResult {
@@ -32,7 +32,7 @@
 
 - `MatchResult::new(message, offset, value)` -- Creates a match with default confidence of 50.
 - `MatchResult::with_metadata(...)` -- Creates a fully specified match. Confidence is clamped to 100.
-- `MatchResult::from_evaluator_match(m, mime_type)` -- Converts from the evaluator's `MatchResult`. Scales confidence from 0.0--1.0 to 0--100 and extracts rule path tags using the shared `TagExtractor`.
+- `MatchResult::from_evaluator_match(m, mime_type)` -- Converts from the evaluator's `RuleMatch`. Scales confidence from 0.0--1.0 to 0--100 and extracts rule path tags using the shared `TagExtractor`.
 
 ### `output::EvaluationResult`
 
@@ -196,7 +196,7 @@
 The full conversion pipeline from evaluation to output:
 
 ```text
-evaluator::MatchResult ──from_evaluator_match──> output::MatchResult
+evaluator::RuleMatch ──from_evaluator_match──> output::MatchResult
                                                         │
                                           ┌─────────────┼─────────────┐
                                           v             v             v
Performance Optimization Strategy
View Changes
@@ -180,7 +180,7 @@
 2. **Periodic timeout checking**: Check timeout every 16 rules (using bit manipulation for efficiency)
 3. **Evaluate each rule**: Call `evaluate_single_rule` with graceful error handling
 4. **On match found**:
-   - Create `MatchResult` and add to matches vector
+   - Create `RuleMatch` and add to matches vector
    - Recursively evaluate child rules if present
    - Check early exit condition and break if enabled
 5. **Continue to next rule**: If no match or early exit not triggered, proceed to next rule
testing
View Changes
@@ -65,8 +65,10 @@
 - `test_type_kind_byte` - Single byte type handling with signedness
 - `test_type_kind_short` - 16-bit integer types with endianness
 - `test_type_kind_long` - 32-bit integer types with endianness
+- `test_type_kind_quad` - 64-bit integer types with endianness
 - `test_type_kind_string` - String types with length limits
 - `test_type_kind_serialization` - All type serialization including signed/unsigned variants
+- `test_serialize_type_kind_quad` - Quad type serialization (build_helpers.rs)
 
 **Operator Tests:**
 
@@ -130,6 +132,43 @@
 - `test_parse_value_edge_cases` - Boundary conditions
 - `test_parse_value_invalid_input` - Error handling
 
+#### Evaluator Component Tests
+
+**Type Reading Tests:**
+
+- `test_read_byte` - Single byte reading with signedness
+- `test_read_short_endianness_and_signedness` - 16-bit reading with all endian/sign combinations
+- `test_read_short_extreme_values` - 16-bit boundary values
+- `test_read_long_endianness_and_signedness` - 32-bit reading with all endian/sign combinations
+- `test_read_long_buffer_overrun` - 32-bit buffer boundary checking
+- `test_read_quad_endianness_and_signedness` - 64-bit reading with all endian/sign combinations
+- `test_read_quad_buffer_overrun` - 64-bit buffer boundary checking
+- `test_read_quad_at_offset` - 64-bit reading at non-zero offsets
+- `test_read_string` - Null-terminated string reading
+- `test_read_typed_value` - Dispatch to correct type reader
+
+**Value Coercion Tests:**
+
+- `test_coerce_value_to_type` - Type conversion including quad overflow handling
+
+**Strength Calculation Tests:**
+
+- `test_strength_type_byte` - Byte type strength
+- `test_strength_type_short` - 16-bit type strength
+- `test_strength_type_long` - 32-bit type strength
+- `test_strength_type_quad` - 64-bit type strength
+- `test_strength_type_string` - String type strength with/without max_length
+- `test_strength_operator_equal` - Operator strength calculations
+
+#### Integration Tests
+
+**End-to-End Evaluation Tests:**
+
+- `test_quad_lequad_matches_little_endian_value` - LE quad pattern matching
+- `test_quad_bequad_matches_big_endian_value` - BE quad pattern matching
+- `test_quad_signed_negative_one` - Signed 64-bit negative value matching
+- `test_quad_nested_child_rule_with_offset` - Quad types in hierarchical rules
+
 ## Test Categories
 
 ### Unit Tests
@@ -335,6 +374,23 @@
 }
 ```
 
+**Testing 64-bit Integer (Quad) Types:**
+
+```rust
+#[test]
+fn test_read_quad_endianness_and_signedness() {
+    // Little-endian unsigned
+    let buffer = &[0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12];
+    let result = read_quad(buffer, 0, Endianness::Little, false).unwrap();
+    assert_eq!(result, Value::Uint(0x1234_5678_90ab_cdef));
+
+    // Big-endian signed negative
+    let buffer = &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
+    let result = read_quad(buffer, 0, Endianness::Big, true).unwrap();
+    assert_eq!(result, Value::Int(-1));
+}
+```
+
 ### Test Data Management
 
 **Test Fixtures:**

How did I do? Any feedback?  Join Discord

@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented Mar 2, 2026

🧪 CI Insights

Here's what we observed from your CI run for 3c3f8ed.

🟢 All jobs passed!

But CI Insights is watching 👀

@coderabbitai coderabbitai Bot added documentation Improvements or additions to documentation enhancement New feature or request testing Test infrastructure and coverage size:XXL This PR changes 1000+ lines, ignoring generated files. labels Mar 2, 2026
dosubot Bot added a commit that referenced this pull request Mar 2, 2026
@dosubot dosubot Bot mentioned this pull request Mar 2, 2026
dosubot Bot added a commit that referenced this pull request Mar 2, 2026
dosubot Bot added a commit that referenced this pull request Mar 2, 2026
dosubot Bot added a commit that referenced this pull request Mar 2, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 2, 2026

Codecov Report

❌ Patch coverage is 95.67568% with 32 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/parser/codegen.rs 92.20% 17 Missing ⚠️
src/parser/grammar.rs 89.16% 13 Missing ⚠️
src/evaluator/types.rs 99.25% 1 Missing ⚠️
src/parser/types.rs 99.50% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

- Updated all references to MatchResult in the evaluator module
- Adjusted related documentation and tests to reflect the new name
- Ensured consistency across the codebase with the new naming convention

Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. size:XXL This PR changes 1000+ lines, ignoring generated files. labels Mar 2, 2026
dosubot Bot added a commit that referenced this pull request Mar 2, 2026
Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Copilot AI review requested due to automatic review settings March 2, 2026 05:13
Update documentation for
#133

_Generated by [Dosu](https://dosu.dev)_

---------

Co-authored-by: dosubot[bot] <131922026+dosubot[bot]@users.noreply.github.com>
Co-authored-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.

Comment thread src/output/mod.rs
m: &crate::evaluator::MatchResult,
mime_type: Option<&str>,
) -> Self {
pub fn from_evaluator_match(m: &crate::evaluator::RuleMatch, mime_type: Option<&str>) -> Self {
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from_evaluator_match’s rustdoc still refers to an evaluator MatchResult, but the type has been renamed to RuleMatch. Update the documentation text so it matches the new API and keeps doctext accurate.

Copilot uses AI. Check for mistakes.
Comment thread src/output/mod.rs
m: &crate::evaluator::MatchResult,
mime_type: Option<&str>,
) -> Self {
pub fn from_evaluator_match(m: &crate::evaluator::RuleMatch, mime_type: Option<&str>) -> Self {
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from_evaluator_match hard-codes numeric match length to 4 bytes (Value::Uint/Value::Int). With the new quad (u64/i64) type, this metadata becomes incorrect for 64-bit matches. Consider carrying the matched width/type in RuleMatch (e.g., a value_len/type_kind field) so output length can be computed accurately (8 for quad, 4 for long, etc.).

Copilot uses AI. Check for mistakes.
Comment thread src/lib.rs

// Re-export evaluator types for convenience
pub use evaluator::{EvaluationContext, MatchResult};
pub use evaluator::{EvaluationContext, RuleMatch};
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR renames the public evaluator match type from MatchResult to RuleMatch (and updates EvaluationResult.matches accordingly), which is a breaking API change. The PR description/title focus on quad support but don’t mention this rename; please call it out explicitly (or consider keeping a deprecated type alias for backwards compatibility).

Copilot uses AI. Check for mistakes.
coderabbitai[bot]
coderabbitai Bot previously approved these changes Mar 2, 2026
…ut MatchResult

Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
@unclesp1d3r unclesp1d3r enabled auto-merge (squash) March 2, 2026 05:30
@unclesp1d3r unclesp1d3r merged commit 6bea5b8 into main Mar 2, 2026
27 of 28 checks passed
@unclesp1d3r unclesp1d3r deleted the 36-parser-implement-quad-64-bit-integer-type-with-endian-variants branch March 2, 2026 05:32
@github-actions github-actions Bot mentioned this pull request Mar 2, 2026
mergify Bot pushed a commit that referenced this pull request Mar 2, 2026
## 🤖 New release

* `libmagic-rs`: 0.2.1 -> 0.3.0 (⚠ API breaking changes)

### ⚠ `libmagic-rs` breaking changes

```text
--- failure enum_no_repr_variant_discriminant_changed: enum variant had its discriminant change value ---

Description:
The enum's variant had its discriminant value change. This breaks downstream code that used its value via a numeric cast like `as isize`.
        ref: https://doc.rust-lang.org/reference/items/enumerations.html#assigning-discriminant-values
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.46.0/src/lints/enum_no_repr_variant_discriminant_changed.ron

Failed in:
  variant TypeKind::String 3 -> 4 in /tmp/.tmp3M9g71/libmagic-rs/src/parser/ast.rs:119
  variant TypeKind::String 3 -> 4 in /tmp/.tmp3M9g71/libmagic-rs/src/parser/ast.rs:119
  variant TypeKind::String 3 -> 4 in /tmp/.tmp3M9g71/libmagic-rs/src/parser/ast.rs:119

--- failure enum_variant_added: enum variant added on exhaustive enum ---

Description:
A publicly-visible enum without #[non_exhaustive] has a new variant.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#enum-variant-new
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.46.0/src/lints/enum_variant_added.ron

Failed in:
  variant TypeKind:Quad in /tmp/.tmp3M9g71/libmagic-rs/src/parser/ast.rs:112
  variant TypeKind:Quad in /tmp/.tmp3M9g71/libmagic-rs/src/parser/ast.rs:112
  variant TypeKind:Quad in /tmp/.tmp3M9g71/libmagic-rs/src/parser/ast.rs:112

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.46.0/src/lints/struct_missing.ron

Failed in:
  struct libmagic_rs::evaluator::MatchResult, previously in file /tmp/.tmpp8oIWU/libmagic-rs/src/evaluator/mod.rs:207
  struct libmagic_rs::MatchResult, previously in file /tmp/.tmpp8oIWU/libmagic-rs/src/evaluator/mod.rs:207
```

<details><summary><i><b>Changelog</b></i></summary><p>

<blockquote>

## [0.3.0] - 2026-03-02

### Features

- **parser**: Implement quad 64-bit integer type with endian variants
([#133](#133))
<!-- generated by git-cliff -->
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
dosubot Bot added a commit that referenced this pull request Mar 2, 2026
@dosubot dosubot Bot mentioned this pull request Mar 2, 2026
unclesp1d3r added a commit that referenced this pull request Mar 2, 2026
Update documentation for
#133

_Generated by [Dosu](https://dosu.dev)_

Signed-off-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Co-authored-by: dosubot[bot] <131922026+dosubot[bot]@users.noreply.github.com>
Co-authored-by: UncleSp1d3r <unclesp1d3r@evilbitlabs.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request evaluator Rule evaluation engine and logic parser Magic file parsing components and grammar size:XXL This PR changes 1000+ lines, ignoring generated files. testing Test infrastructure and coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parser: implement quad (64-bit integer) type with endian variants

2 participants