Skip to main content

ruvix_types/
region.rs

1//! Memory region types.
2//!
3//! RuVix replaces virtual memory with regions. A region is a contiguous,
4//! capability-protected memory object with one of three policies:
5//! Immutable, AppendOnly, or Slab.
6
7use crate::handle::Handle;
8
9/// Handle to a memory region.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11#[repr(transparent)]
12pub struct RegionHandle(pub Handle);
13
14impl RegionHandle {
15    /// Creates a new region handle.
16    #[inline]
17    #[must_use]
18    pub const fn new(id: u32, generation: u32) -> Self {
19        Self(Handle::new(id, generation))
20    }
21
22    /// Creates a null (invalid) region handle.
23    #[inline]
24    #[must_use]
25    pub const fn null() -> Self {
26        Self(Handle::null())
27    }
28
29    /// Checks if this handle is null.
30    #[inline]
31    #[must_use]
32    pub const fn is_null(&self) -> bool {
33        self.0.is_null()
34    }
35
36    /// Returns the raw handle.
37    #[inline]
38    #[must_use]
39    pub const fn raw(&self) -> Handle {
40        self.0
41    }
42}
43
44impl Default for RegionHandle {
45    fn default() -> Self {
46        Self::null()
47    }
48}
49
50/// Memory region access policy.
51///
52/// RuVix does not implement demand paging. All regions are physically backed
53/// at `region_map` time. This eliminates page faults, swap, and copy-on-write
54/// complexity.
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
56pub enum RegionPolicy {
57    /// Contents are set once at creation and never modified.
58    ///
59    /// The kernel may deduplicate identical immutable regions.
60    /// Ideal for: RVF component code, trained model weights, lookup tables.
61    Immutable,
62
63    /// Contents can only be appended, never overwritten or truncated.
64    ///
65    /// A monotonic write cursor tracks the append position.
66    /// Ideal for: witness logs, event streams, time-series vectors.
67    AppendOnly {
68        /// Maximum size in bytes before the region is considered full.
69        max_size: usize,
70    },
71
72    /// Fixed-size slots allocated from a free list.
73    ///
74    /// Slots can be freed and reused. No fragmentation by construction.
75    /// Ideal for: task control blocks, capability tables, queue ring buffers.
76    Slab {
77        /// Size of each slot in bytes.
78        slot_size: usize,
79        /// Total number of slots.
80        slot_count: usize,
81    },
82}
83
84impl RegionPolicy {
85    /// Returns the policy name as a string.
86    #[inline]
87    #[must_use]
88    pub const fn as_str(&self) -> &'static str {
89        match self {
90            Self::Immutable => "Immutable",
91            Self::AppendOnly { .. } => "AppendOnly",
92            Self::Slab { .. } => "Slab",
93        }
94    }
95
96    /// Returns true if this policy allows writes.
97    #[inline]
98    #[must_use]
99    pub const fn is_writable(&self) -> bool {
100        match self {
101            Self::Immutable => false,
102            Self::AppendOnly { .. } | Self::Slab { .. } => true,
103        }
104    }
105
106    /// Returns true if this policy allows in-place modifications.
107    ///
108    /// Only Slab regions allow overwriting existing data.
109    /// AppendOnly regions only permit appending.
110    #[inline]
111    #[must_use]
112    pub const fn allows_overwrite(&self) -> bool {
113        matches!(self, Self::Slab { .. })
114    }
115
116    /// Returns the total capacity in bytes.
117    #[inline]
118    #[must_use]
119    pub const fn capacity(&self) -> Option<usize> {
120        match self {
121            Self::Immutable => None,
122            Self::AppendOnly { max_size } => Some(*max_size),
123            Self::Slab {
124                slot_size,
125                slot_count,
126            } => Some(*slot_size * *slot_count),
127        }
128    }
129
130    /// Creates an immutable region policy.
131    #[inline]
132    #[must_use]
133    pub const fn immutable() -> Self {
134        Self::Immutable
135    }
136
137    /// Creates an append-only region policy.
138    #[inline]
139    #[must_use]
140    pub const fn append_only(max_size: usize) -> Self {
141        Self::AppendOnly { max_size }
142    }
143
144    /// Creates a slab region policy.
145    #[inline]
146    #[must_use]
147    pub const fn slab(slot_size: usize, slot_count: usize) -> Self {
148        Self::Slab {
149            slot_size,
150            slot_count,
151        }
152    }
153}
154
155impl Default for RegionPolicy {
156    fn default() -> Self {
157        Self::Immutable
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use super::*;
164
165    #[test]
166    fn test_region_handle() {
167        let h = RegionHandle::new(5, 10);
168        assert!(!h.is_null());
169        assert_eq!(h.raw().id, 5);
170    }
171
172    #[test]
173    fn test_region_policy_immutable() {
174        let policy = RegionPolicy::immutable();
175        assert!(!policy.is_writable());
176        assert!(!policy.allows_overwrite());
177        assert!(policy.capacity().is_none());
178    }
179
180    #[test]
181    fn test_region_policy_append_only() {
182        let policy = RegionPolicy::append_only(1024);
183        assert!(policy.is_writable());
184        assert!(!policy.allows_overwrite());
185        assert_eq!(policy.capacity(), Some(1024));
186    }
187
188    #[test]
189    fn test_region_policy_slab() {
190        let policy = RegionPolicy::slab(64, 100);
191        assert!(policy.is_writable());
192        assert!(policy.allows_overwrite());
193        assert_eq!(policy.capacity(), Some(6400));
194    }
195}