Address Ranges
Relevant source files
This document covers the address range functionality provided by the memory_addr
crate, specifically the AddrRange
generic type and its associated operations. Address ranges represent contiguous spans of memory addresses with type safety and comprehensive range manipulation operations.
For information about individual address types and arithmetic operations, see Address Types and Operations. For page iteration over ranges, see Page Iteration.
Address Range Structure
The core of the address range system is the AddrRange<A>
generic struct, where A
implements the MemoryAddr
trait. This provides type-safe representation of memory address ranges with inclusive start bounds and exclusive end bounds.
AddrRange Type Hierarchy
flowchart TD subgraph subGraph2["Address Types"] VA["VirtAddr"] PA["PhysAddr"] UA["usize"] end subgraph subGraph1["Concrete Type Aliases"] VAR["VirtAddrRangeAddrRange<VirtAddr>"] PAR["PhysAddrRangeAddrRange<PhysAddr>"] end subgraph subGraph0["Generic Types"] AR["AddrRange<A>Generic range type"] MA["MemoryAddr traitConstraint for A"] end AR --> MA AR --> UA PA --> MA PAR --> AR PAR --> PA UA --> MA VA --> MA VAR --> AR VAR --> VA
Sources: memory_addr/src/range.rs(L1 - L28) memory_addr/src/range.rs(L365 - L368)
The AddrRange<A>
struct contains two public fields:
start: A
- The lower bound of the range (inclusive)end: A
- The upper bound of the range (exclusive)
Type aliases provide convenient names for common address range types:
VirtAddrRange
=AddrRange<VirtAddr>
PhysAddrRange
=AddrRange<PhysAddr>
Range Construction Methods
Address ranges can be constructed through several methods, each with different safety and error-handling characteristics.
Construction Method Categories
Method | Safety | Overflow Handling | Use Case |
---|---|---|---|
new() | Panics on invalid range | Checked | Safe construction with panic |
try_new() | ReturnsOption | Checked | Fallible construction |
new_unchecked() | Unsafe | Unchecked | Performance-critical paths |
from_start_size() | Panics on overflow | Checked | Size-based construction |
try_from_start_size() | ReturnsOption | Checked | Fallible size-based construction |
from_start_size_unchecked() | Unsafe | Unchecked | Performance-critical size-based |
Sources: memory_addr/src/range.rs(L34 - L193)
Range Construction Flow
flowchart TD subgraph Results["Results"] SUCCESS["AddrRange<A>"] PANIC["Panic"] NONE["None"] ERROR["Error"] end subgraph Validation["Validation"] CHECK["start <= end?"] OVERFLOW["Addition overflow?"] end subgraph subGraph1["Construction Methods"] NEW["new()"] TRYNEW["try_new()"] UNSAFE["new_unchecked()"] FSS["from_start_size()"] TRYFSS["try_from_start_size()"] UNSAFEFSS["from_start_size_unchecked()"] TRYFROM["TryFrom<Range<T>>"] end subgraph subGraph0["Input Types"] SE["start, end addresses"] SS["start address, size"] RNG["Rust Range<T>"] end START["Range Construction Request"] CHECK --> NONE CHECK --> PANIC CHECK --> SUCCESS FSS --> OVERFLOW NEW --> CHECK OVERFLOW --> NONE OVERFLOW --> PANIC OVERFLOW --> SUCCESS RNG --> TRYFROM SE --> NEW SE --> TRYNEW SE --> UNSAFE SS --> FSS SS --> TRYFSS SS --> UNSAFEFSS START --> RNG START --> SE START --> SS TRYFROM --> CHECK TRYFSS --> OVERFLOW TRYNEW --> CHECK UNSAFE --> SUCCESS UNSAFEFSS --> SUCCESS
Sources: memory_addr/src/range.rs(L57 - L193) memory_addr/src/range.rs(L307 - L317)
Range Operations and Relationships
Address ranges support comprehensive operations for checking containment, overlap, and spatial relationships between ranges.
Range Relationship Operations
flowchart TD subgraph Results["Results"] BOOL["bool"] USIZE["usize"] end subgraph subGraph1["Query Operations"] CONTAINS["contains(addr: A)Point containment"] CONTAINSRANGE["contains_range(other)Range containment"] CONTAINEDIN["contained_in(other)Reverse containment"] OVERLAPS["overlaps(other)Range intersection"] ISEMPTY["is_empty()Zero-size check"] SIZE["size()Range size"] end subgraph subGraph0["Range A"] RA["AddrRange<A>"] end CONTAINEDIN --> BOOL CONTAINS --> BOOL CONTAINSRANGE --> BOOL ISEMPTY --> BOOL OVERLAPS --> BOOL RA --> CONTAINEDIN RA --> CONTAINS RA --> CONTAINSRANGE RA --> ISEMPTY RA --> OVERLAPS RA --> SIZE SIZE --> USIZE
Sources: memory_addr/src/range.rs(L228 - L302)
Key Range Operations
The following operations are available on all AddrRange<A>
instances:
- Point Containment:
contains(addr)
checks if a single address falls within the range - Range Containment:
contains_range(other)
checks if another range is entirely within this range - Containment Check:
contained_in(other)
checks if this range is entirely within another range - Overlap Detection:
overlaps(other)
checks if two ranges have any intersection - Empty Range Check:
is_empty()
returns true if start equals end - Size Calculation:
size()
returns the number of bytes in the range
Convenience Macros
The crate provides three macros for convenient address range creation with compile-time type inference and runtime validation.
Macro Overview
Macro | Target Type | Purpose |
---|---|---|
addr_range! | AddrRange(inferred) | Generic range creation |
va_range! | VirtAddrRange | Virtual address range creation |
pa_range! | PhysAddrRange | Physical address range creation |
Sources: memory_addr/src/range.rs(L391 - L448)
Macro Usage Pattern
flowchart TD subgraph subGraph3["Output Types"] GENERICRANGE["AddrRange<A> (inferred)"] VIRTRANGE["VirtAddrRange"] PHYSRANGE["PhysAddrRange"] end subgraph subGraph2["Internal Processing"] TRYFROM["TryFrom<Range<T>>::try_from()"] EXPECT["expect() on Result"] end subgraph subGraph1["Macro Processing"] ADDRRANGE["addr_range!(0x1000..0x2000)"] VARANGE["va_range!(0x1000..0x2000)"] PARANGE["pa_range!(0x1000..0x2000)"] end subgraph subGraph0["Input Syntax"] RANGE["Rust range syntaxstart..end"] end ADDRRANGE --> TRYFROM EXPECT --> GENERICRANGE EXPECT --> PHYSRANGE EXPECT --> VIRTRANGE PARANGE --> TRYFROM RANGE --> ADDRRANGE RANGE --> PARANGE RANGE --> VARANGE TRYFROM --> EXPECT VARANGE --> TRYFROM
Sources: memory_addr/src/range.rs(L391 - L448)
Usage Examples and Patterns
The test suite demonstrates common usage patterns for address ranges, showing both basic operations and complex relationship checking.
Basic Range Operations
// Creating ranges with different methods
let range = VirtAddrRange::new(0x1000.into(), 0x2000.into());
let size_range = VirtAddrRange::from_start_size(0x1000.into(), 0x1000);
// Using macros for convenience
let macro_range = va_range!(0x1000..0x2000);
// Checking basic properties
assert_eq!(range.size(), 0x1000);
assert!(!range.is_empty());
assert!(range.contains(0x1500.into()));
Sources: memory_addr/src/range.rs(L464 - L511)
Range Relationship Testing
The codebase extensively tests range relationships using various scenarios:
// Containment checking
assert!(range.contains_range(va_range!(0x1001..0x1fff)));
assert!(!range.contains_range(va_range!(0xfff..0x2001)));
// Overlap detection
assert!(range.overlaps(va_range!(0x1800..0x2001)));
assert!(!range.overlaps(va_range!(0x2000..0x2800)));
// Spatial relationships
assert!(range.contained_in(va_range!(0xfff..0x2001)));
Sources: memory_addr/src/range.rs(L483 - L505)
Error Handling Patterns
The range system provides both panicking and fallible construction methods:
// Panicking construction (for known-valid ranges)
let valid_range = VirtAddrRange::new(start, end);
// Fallible construction (for potentially invalid input)
if let Some(range) = VirtAddrRange::try_new(start, end) {
// Use the valid range
}
// Size-based construction with overflow handling
let safe_range = VirtAddrRange::try_from_start_size(start, size)?;
Sources: memory_addr/src/range.rs(L58 - L167)