Object Protection with WithCap
Relevant source files
Purpose and Scope
This document covers the WithCap<T>
wrapper struct, which serves as the core object protection mechanism in the cap_access library. The WithCap<T>
struct associates any object of type T
with a specific capability (Cap
), providing controlled access to the wrapped object through capability checking.
For details about the underlying capability system and Cap
bitflags, see Capability System. For comprehensive coverage of the access control methods provided by WithCap<T>
, see Access Control Methods.
WithCap Structure Overview
The WithCap<T>
struct provides a simple but powerful abstraction for capability-based object protection. It wraps any object with an associated capability, ensuring that access to the object is mediated through capability checks.
Core Architecture
flowchart TD subgraph AccessMethods["Access Methods"] new["new(inner, cap)"] can_access["can_access(cap)"] access["access(cap)"] access_or_err["access_or_err(cap, err)"] access_unchecked["access_unchecked()"] cap_getter["cap()"] end subgraph CapSystem["Capability System"] READ["Cap::READ"] WRITE["Cap::WRITE"] EXECUTE["Cap::EXECUTE"] COMBINED["Combined Capabilities"] end subgraph WithCap["WithCap<T> Structure"] inner["inner: T"] cap["cap: Cap"] end COMBINED --> cap EXECUTE --> cap READ --> cap WRITE --> cap
Sources: src/lib.rs(L18 - L21) src/lib.rs(L23 - L100)
Struct Definition
The WithCap<T>
struct contains exactly two fields that work together to provide controlled access:
Field | Type | Purpose |
---|---|---|
inner | T | The protected object of arbitrary type |
cap | Cap | The capability bitflags defining allowed access |
The struct is generic over type T
, allowing any object to be protected with capabilities.
Sources: src/lib.rs(L18 - L21)
Object Wrapping Process
Creating Protected Objects
The WithCap::new()
constructor associates an object with specific capabilities, creating an immutable binding between the object and its access permissions.
flowchart TD subgraph Examples["Example Objects"] FileData["File Data"] MemoryRegion["Memory Region"] DeviceHandle["Device Handle"] end subgraph Creation["Object Protection Process"] UnprotectedObj["Unprotected Object"] Capability["Cap Permissions"] Constructor["WithCap::new()"] ProtectedObj["WithCap<T>"] end Capability --> Constructor Constructor --> ProtectedObj DeviceHandle --> UnprotectedObj FileData --> UnprotectedObj MemoryRegion --> UnprotectedObj UnprotectedObj --> Constructor
Sources: src/lib.rs(L24 - L27)
Capability Association
The new()
method permanently associates the provided capability with the object. Once created, the capability cannot be modified, ensuring the integrity of the access control policy.
The constructor signature demonstrates this immutable binding:
pub fn new(inner: T, cap: Cap) -> Self
Sources: src/lib.rs(L24 - L27)
Access Control Implementation
Capability Checking Logic
The core access control mechanism relies on the can_access()
method, which performs bitwise capability checking using the underlying Cap::contains()
operation.
flowchart TD subgraph AccessMethods["Access Method Types"] SafeAccess["access() → Option<&T>"] ErrorAccess["access_or_err() → Result<&T, E>"] UnsafeAccess["access_unchecked() → &T"] end subgraph AccessFlow["Access Control Flow"] Request["Access Request with Cap"] Check["can_access(cap)"] Contains["cap.contains(requested_cap)"] Allow["Grant Access"] Deny["Deny Access"] end Allow --> ErrorAccess Allow --> SafeAccess Check --> Contains Contains --> Allow Contains --> Deny Deny --> ErrorAccess Deny --> SafeAccess Request --> Check UnsafeAccess --> Check
Sources: src/lib.rs(L46 - L48) src/lib.rs(L72 - L78) src/lib.rs(L93 - L99) src/lib.rs(L55 - L57)
Method Categories
The WithCap<T>
struct provides three categories of access methods:
Method Category | Safety | Return Type | Use Case |
---|---|---|---|
Checked Access | Safe | Option<&T> | General-purpose access |
Error-based Access | Safe | Result<&T, E> | When custom error handling needed |
Unchecked Access | Unsafe | &T | Performance-critical code paths |
Sources: src/lib.rs(L72 - L78) src/lib.rs(L93 - L99) src/lib.rs(L55 - L57)
Internal Architecture Details
Capability Storage
The WithCap<T>
struct stores capabilities as Cap
bitflags, enabling efficient bitwise operations for permission checking. The cap()
getter method provides read-only access to the stored capability.
Memory Layout Considerations
The struct maintains a simple memory layout with the protected object and capability stored adjacently. This design minimizes overhead while maintaining clear separation between the object and its access permissions.
flowchart TD subgraph CapabilityBits["Cap Bitfield Structure"] Bit0["Bit 0: READ"] Bit1["Bit 1: WRITE"] Bit2["Bit 2: EXECUTE"] Reserved["Bits 3-31: Reserved"] end subgraph MemoryLayout["WithCap<T> Memory Layout"] InnerData["inner: T(Protected Object)"] CapData["cap: Cap(u32 bitflags)"] end WithCap["WithCap"] CapData --> Bit0 CapData --> Bit1 CapData --> Bit2 CapData --> Reserved CapData --> WithCap InnerData --> WithCap
Sources: src/lib.rs(L18 - L21) src/lib.rs(L29 - L32)
Const Methods
Several methods are declared as const fn
, enabling compile-time evaluation when possible:
cap()
- capability gettercan_access()
- capability checkingaccess()
- checked access
This design supports zero-cost abstractions in performance-critical embedded environments.