Address Types and Operations
Relevant source files
This document covers the foundational address handling types and operations provided by the memory_addr crate. These types provide type-safe abstractions for physical and virtual memory addresses, along with comprehensive alignment and arithmetic operations. For information about address ranges and iteration, see Address Ranges and Page Iteration.
Core Architecture
The address system is built around the MemoryAddr trait, which provides a common interface for all memory address types. The crate includes two concrete address types (PhysAddr and VirtAddr) and utilities for creating custom address types.
Address Type Hierarchy
classDiagram
note for MemoryAddr "Auto-implemented for types that are:Copy + From + Into + Ord"
class MemoryAddr {
<<trait>>
+align_down(align) Self
+align_up(align) Self
+align_offset(align) usize
+is_aligned(align) bool
+align_down_4k() Self
+align_up_4k() Self
+offset(offset) Self
+add(rhs) Self
+sub(rhs) Self
+checked_add(rhs) Option~Self~
+checked_sub(rhs) Option~Self~
}
class PhysAddr {
-usize: usize
+from_usize(addr) PhysAddr
+as_usize() usize
}
class VirtAddr {
-usize: usize
+from_usize(addr) VirtAddr
+as_usize() usize
+from_ptr_of~T~(*const T) VirtAddr
+as_ptr() *const u8
+as_ptr_of~T~() *const T
+as_mut_ptr() *mut u8
}
MemoryAddr ..|> PhysAddr : implements
MemoryAddr ..|> VirtAddr : implements
Sources: memory_addr/src/addr.rs(L12 - L263) memory_addr/src/addr.rs(L450 - L461)
Address Types
PhysAddr
PhysAddr represents a physical memory address. It is a transparent wrapper around usize that provides type safety to prevent mixing physical and virtual addresses.
| Method | Description | Return Type |
|---|---|---|
| from_usize(addr) | Creates from raw address value | PhysAddr |
| as_usize() | Converts to raw address value | usize |
| pa!(addr) | Convenience macro for creation | PhysAddr |
VirtAddr
VirtAddr represents a virtual memory address with additional pointer conversion capabilities beyond the base MemoryAddr trait.
| Method | Description | Return Type |
|---|---|---|
| from_ptr_of | Creates from typed pointer | VirtAddr |
| from_mut_ptr_of | Creates from mutable pointer | VirtAddr |
| as_ptr() | Converts to byte pointer | *const u8 |
| as_ptr_of | Converts to typed pointer | *const T |
| as_mut_ptr() | Converts to mutable byte pointer | *mut u8 |
| as_mut_ptr_of | Converts to mutable typed pointer | *mut T |
| va!(addr) | Convenience macro for creation | VirtAddr |
Sources: memory_addr/src/addr.rs(L450 - L461) memory_addr/src/addr.rs(L463 - L500) memory_addr/src/addr.rs(L502 - L516)
Address Type Operations Flow
flowchart TD
subgraph Results["Results"]
new_addr["New Address"]
offset_val["usize offset"]
ptr_result["*const/*mut T"]
bool_result["bool"]
end
subgraph Operations["Operations"]
align["Alignment Operations"]
arith["Arithmetic Operations"]
convert["Conversion Operations"]
end
subgraph subGraph1["Address Types"]
PhysAddr["PhysAddr"]
VirtAddr["VirtAddr"]
end
subgraph Creation["Creation"]
usize["usize value"]
ptr["*const/*mut T"]
macro_pa["pa!(0x1000)"]
macro_va["va!(0x2000)"]
end
PhysAddr --> align
PhysAddr --> arith
VirtAddr --> align
VirtAddr --> arith
VirtAddr --> convert
align --> bool_result
align --> new_addr
align --> offset_val
arith --> new_addr
arith --> offset_val
convert --> ptr_result
macro_pa --> PhysAddr
macro_va --> VirtAddr
ptr --> VirtAddr
usize --> PhysAddr
usize --> VirtAddr
Sources: memory_addr/src/addr.rs(L450 - L500) memory_addr/src/addr.rs(L502 - L516)
Alignment Operations
The MemoryAddr trait provides comprehensive alignment functionality for working with page boundaries and custom alignments.
Core Alignment Methods
| Method | Description | Example Usage |
|---|---|---|
| align_down(align) | Rounds down to alignment boundary | addr.align_down(0x1000) |
| align_up(align) | Rounds up to alignment boundary | addr.align_up(0x1000) |
| align_offset(align) | Returns offset within alignment | addr.align_offset(0x1000) |
| is_aligned(align) | Checks if address is aligned | addr.is_aligned(0x1000) |
4K Page Alignment Shortcuts
| Method | Description | Equivalent To |
|---|---|---|
| align_down_4k() | Aligns down to 4K boundary | align_down(4096) |
| align_up_4k() | Aligns up to 4K boundary | align_up(4096) |
| align_offset_4k() | Offset within 4K page | align_offset(4096) |
| is_aligned_4k() | Checks 4K alignment | is_aligned(4096) |
Alignment Operation Examples
flowchart TD
subgraph align_up_4k()["align_up_4k()"]
result4["0x3000"]
result5["0x3000"]
result6["0x4000"]
end
subgraph align_down_4k()["align_down_4k()"]
result1["0x2000"]
result2["0x3000"]
result3["0x3000"]
end
subgraph subGraph0["Input Addresses"]
addr1["0x2fff"]
addr2["0x3000"]
addr3["0x3001"]
end
addr1 --> result1
addr1 --> result4
addr2 --> result2
addr2 --> result5
addr3 --> result3
addr3 --> result6
Sources: memory_addr/src/addr.rs(L27 - L94)
Arithmetic Operations
The trait provides extensive arithmetic operations with multiple overflow handling strategies.
Basic Arithmetic
| Method | Description | Overflow Behavior |
|---|---|---|
| offset(isize) | Signed offset addition | Panics |
| add(usize) | Unsigned addition | Panics |
| sub(usize) | Unsigned subtraction | Panics |
| sub_addr(Self) | Address difference | Panics |
Wrapping Arithmetic
| Method | Description | Overflow Behavior |
|---|---|---|
| wrapping_offset(isize) | Signed offset addition | Wraps around |
| wrapping_add(usize) | Unsigned addition | Wraps around |
| wrapping_sub(usize) | Unsigned subtraction | Wraps around |
| wrapping_sub_addr(Self) | Address difference | Wraps around |
Checked Arithmetic
| Method | Description | Return Type |
|---|---|---|
| checked_add(usize) | Safe addition | Option |
| checked_sub(usize) | Safe subtraction | Option |
| checked_sub_addr(Self) | Safe address difference | Option |
Overflowing Arithmetic
| Method | Description | Return Type |
|---|---|---|
| overflowing_add(usize) | Addition with overflow flag | (Self, bool) |
| overflowing_sub(usize) | Subtraction with overflow flag | (Self, bool) |
| overflowing_sub_addr(Self) | Address difference with overflow flag | (usize, bool) |
Arithmetic Operations Decision Tree
flowchart TD start["Need Address Arithmetic?"] signed["Signed Offset?"] overflow["Overflow Handling?"] offset_op["offset(isize)wrapping_offset(isize)"] panic_ops["add(usize)sub(usize)sub_addr(Self)"] wrap_ops["wrapping_add(usize)wrapping_sub(usize)wrapping_sub_addr(Self)"] check_ops["checked_add(usize)checked_sub(usize)checked_sub_addr(Self)"] over_ops["overflowing_add(usize)overflowing_sub(usize)overflowing_sub_addr(Self)"] overflow --> check_ops overflow --> over_ops overflow --> panic_ops overflow --> wrap_ops signed --> offset_op signed --> overflow start --> signed
Sources: memory_addr/src/addr.rs(L99 - L258)
Address Type Creation
The crate provides macros for creating custom address types with the same capabilities as PhysAddr and VirtAddr.
def_usize_addr! Macro
The def_usize_addr! macro generates new address types with automatic implementations:
- Basic traits:
Copy,Clone,Default,Ord,PartialOrd,Eq,PartialEq - Conversion traits:
From<usize>,Into<usize> - Arithmetic operators:
Add<usize>,Sub<usize>,Sub<Self> - Utility methods:
from_usize(),as_usize()
def_usize_addr_formatter! Macro
The def_usize_addr_formatter! macro generates formatting implementations:
Debugtrait with custom format stringLowerHexandUpperHextraits
Custom Address Type Creation Flow
sequenceDiagram
participant Developer as "Developer"
participant def_usize_addr as "def_usize_addr!"
participant def_usize_addr_formatter as "def_usize_addr_formatter!"
participant CustomAddressType as "Custom Address Type"
Developer ->> def_usize_addr: "Define type CustomAddr"
def_usize_addr ->> CustomAddressType: "Generate struct with usize field"
def_usize_addr ->> CustomAddressType: "Implement required traits"
def_usize_addr ->> CustomAddressType: "Add conversion methods"
def_usize_addr ->> CustomAddressType: "Add arithmetic operators"
Developer ->> def_usize_addr_formatter: "Set format string"
def_usize_addr_formatter ->> CustomAddressType: "Implement Debug trait"
def_usize_addr_formatter ->> CustomAddressType: "Implement Hex traits"
CustomAddressType ->> Developer: "Ready for use with MemoryAddr"
Sources: memory_addr/src/addr.rs(L302 - L448)
MemoryAddr Trait Implementation
The MemoryAddr trait is automatically implemented for any type meeting the required bounds, providing a blanket implementation that enables consistent behavior across all address types.
Automatic Implementation Requirements
flowchart TD
subgraph Result["Result"]
unified["Unified Interface"]
type_safety["Type Safety"]
rich_api["Rich API"]
end
subgraph subGraph1["Automatic Implementation"]
memory_addr["MemoryAddr trait"]
alignment["Alignment Methods"]
arithmetic["Arithmetic Methods"]
end
subgraph subGraph0["Required Bounds"]
copy["Copy"]
from_usize["From"]
into_usize["Into"]
ord["Ord"]
end
alignment --> unified
arithmetic --> type_safety
copy --> memory_addr
from_usize --> memory_addr
into_usize --> memory_addr
memory_addr --> alignment
memory_addr --> arithmetic
ord --> memory_addr
unified --> rich_api
Sources: memory_addr/src/addr.rs(L261 - L263)