pub struct Region<T: Flat, B: Buf = AlignedBuf<T>> { /* private fields */ }Expand description
An owning, contiguous byte buffer whose root value T starts at byte 0.
All Near and NearList pointers
inside the region are self-relative offsets, so Clone is a plain memcpy
— no fixup needed.
§Memory layout
┌──────────────────────────────────────────────┐
│ Root T (starts at byte 0) │
│ ├── scalar fields (inline) │
│ ├── Near<U> → i32 offset ───────┐ │
│ └── NearList<V> → i32 + u32 ──┐ │ │
│ │ │ │
│ [padding] │ │ │
│ U value ◄──────────────────────│─┘ │
│ [padding] │ │
│ Segment<V> header ◄────────────┘ │
│ V values... │
└──────────────────────────────────────────────┘§Soundness
Ownership: A Region exclusively owns its buffer. There is no
shared mutable state. Clone performs a byte-for-byte copy of the buffer;
all self-relative offsets remain valid because they are position-independent.
Alignment: The buffer base is aligned to max(align_of::<T>(), 8).
Every sub-allocation is padded to the target type’s alignment. A
compile-time assertion ensures no type exceeds the buffer’s base alignment.
Mutation safety: All mutations go through Session,
which holds &mut Region. The branded 'id lifetime on Ref
prevents refs from escaping or crossing sessions.
Send/Sync: Implemented with T: Send + Sync bounds as
defense-in-depth. All Flat types are Send + Sync by construction
(no heap pointers, no interior mutability), but the bounds let the
compiler verify this.
Implementations§
Source§impl<T: Flat> Region<T>
impl<T: Flat> Region<T>
Sourcepub fn new(builder: impl Emit<T>) -> Self
pub fn new(builder: impl Emit<T>) -> Self
Construct a region from a builder using the default AlignedBuf.
The builder emits the root T (and any nested data) into a fresh
emitter, producing an immutable Region.
§Examples
use nearest::{Flat, NearList, Region, empty, list};
#[derive(Flat, Debug)]
struct Node {
id: u32,
children: NearList<u32>,
}
// Build with the derive-generated `Node::make(id, children)` builder.
let region = Region::new(Node::make(1, list([10u32, 20, 30])));
assert_eq!(region.id, 1);
assert_eq!(region.children.len(), 3);
// Build with an empty list.
let region = Region::new(Node::make(2, empty()));
assert_eq!(region.children.len(), 0);Sourcepub fn with_capacity(capacity: u32, builder: impl Emit<T>) -> Self
pub fn with_capacity(capacity: u32, builder: impl Emit<T>) -> Self
Construct a region with a pre-allocated buffer of at least capacity bytes.
Avoids repeated reallocations when the final size is approximately known.
Source§impl<T: Flat, B: Buf> Region<T, B>
impl<T: Flat, B: Buf> Region<T, B>
Sourcepub fn new_in(builder: impl Emit<T>) -> Self
pub fn new_in(builder: impl Emit<T>) -> Self
Construct a region from a builder using an explicit buffer type B.
For the default heap-backed buffer, use Region::new instead.
Sourcepub fn with_capacity_in(capacity: u32, builder: impl Emit<T>) -> Self
pub fn with_capacity_in(capacity: u32, builder: impl Emit<T>) -> Self
Construct a region with a pre-allocated buffer of at least capacity bytes.
Sourcepub fn session<R>(
&mut self,
f: impl for<'id> FnOnce(&mut Session<'id, '_, T, B>) -> R,
) -> R
pub fn session<R>( &mut self, f: impl for<'id> FnOnce(&mut Session<'id, '_, T, B>) -> R, ) -> R
Open a branded session. Refs created inside the closure
cannot escape or be used with a different session — compile-time safety,
zero runtime cost.
§Examples
use nearest::{Flat, NearList, Region, empty, list};
#[derive(Flat, Debug)]
struct Node {
id: u32,
children: NearList<u32>,
}
let mut region = Region::new(Node::make(1, list([10u32, 20])));
// Read and mutate inside a session.
region.session(|s| {
let root = s.root();
assert_eq!(s.at(root).id, 1);
let children = s.nav(root, |n| &n.children);
s.splice_list(children, [99u32]);
});
assert_eq!(region.children.len(), 1);
assert_eq!(region.children[0], 99);Sourcepub fn byte_len(&self) -> usize
pub fn byte_len(&self) -> usize
Returns the total byte length of the region.
§Examples
use nearest::{Flat, NearList, Region, empty};
#[derive(Flat)]
struct Node { id: u32, items: NearList<u32> }
let region = Region::new(Node::make(1, empty()));
assert!(region.byte_len() >= core::mem::size_of::<Node>());Sourcepub fn trim(&mut self)
pub fn trim(&mut self)
Compact this region by re-emitting only reachable data.
After mutations (e.g. splice_list,
push_front), old targets of redirected
Near/NearList pointers become
dead bytes. trim walks the root T and all transitively reachable
data, emitting a fresh compact buffer via Emit<T> for &T deep-copy.
§Examples
use nearest::{Flat, NearList, Region, list};
#[derive(Flat, Debug)]
struct Node { items: NearList<u32> }
let mut region = Region::new(Node::make(list([1u32, 2, 3])));
let before = region.byte_len();
// Mutation leaves dead bytes (old list data).
region.session(|s| {
let items = s.nav(s.root(), |n| &n.items);
s.splice_list(items, [42u32]);
});
assert!(region.byte_len() > before);
// Trim compacts the region.
region.trim();
assert!(region.byte_len() <= before);
assert_eq!(region.items[0], 42);Sourcepub fn as_bytes(&self) -> &[u8]
pub fn as_bytes(&self) -> &[u8]
Return the raw byte contents of this region.
The returned slice can be persisted (e.g. written to a file) and later
restored via from_bytes.
§Examples
use nearest::{Flat, NearList, Region, empty, list};
#[derive(Flat, Debug)]
struct Node {
id: u32,
children: NearList<u32>,
}
let region = Region::new(Node::make(1, list([10u32, 20, 30])));
let bytes = region.as_bytes();
assert!(bytes.len() >= core::mem::size_of::<Node>());Sourcepub fn into_buf(self) -> B
pub fn into_buf(self) -> B
Consume the region and return the underlying buffer.
This is a zero-copy operation — it simply unwraps the inner buffer.
The returned buffer can be passed to from_bytes
(via Buf::as_bytes) for reconstruction, or converted to bytes.
§Examples
use nearest::{Flat, NearList, Region, empty, list};
#[derive(Flat, Debug)]
struct Node {
id: u32,
children: NearList<u32>,
}
let region = Region::new(Node::make(1, list([10u32, 20, 30])));
let buf = region.into_buf();Sourcepub fn into_vec(self) -> Vec<u8>
pub fn into_vec(self) -> Vec<u8>
Consume the region and return its contents as a Vec<u8>.
The returned vector contains the same bytes as as_bytes.
This is useful for APIs that need an owned byte buffer (e.g. I/O,
network transmission, or storage). The bytes can later be restored
via Region::from_bytes.
§Examples
use nearest::{Flat, NearList, Region, list};
#[derive(Flat, Debug)]
struct Node {
id: u32,
children: NearList<u32>,
}
let region = Region::new(Node::make(1, list([10u32, 20, 30])));
let bytes: Vec<u8> = region.into_vec();
let restored: Region<Node> = Region::from_bytes(&bytes).unwrap();
assert_eq!(restored.id, 1);
assert_eq!(restored.children.len(), 3);Sourcepub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidateError>
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ValidateError>
Validate and reconstruct a region from raw bytes.
Copies the bytes into an aligned buffer first, then runs
T::validate on the copy. This copy-then-validate
order means the input is read only once (during the copy), and
validation reads the cache-hot aligned buffer instead.
§Errors
Returns ValidateError if the bytes do not
form a valid representation of T and its transitively reachable data.
§Examples
Round-trip through bytes:
use nearest::{Flat, NearList, Region, empty, list};
#[derive(Flat, Debug)]
struct Node {
id: u32,
children: NearList<u32>,
}
let original = Region::new(Node::make(1, list([10u32, 20, 30])));
let bytes = original.as_bytes();
let restored: Region<Node> = Region::from_bytes(bytes).unwrap();
assert_eq!(restored.id, 1);
assert_eq!(restored.children.len(), 3);Validation catches invalid data — here a bool field with value 2:
use nearest::{Flat, Near, Region, ValidateError, near};
#[derive(Flat, Debug)]
struct Flags {
active: bool,
label: Near<u32>,
}
let region = Region::new(Flags::make(true, near(42u32)));
let mut bytes = region.as_bytes().to_vec();
// Corrupt the bool — its offset is computed from the struct layout.
let bool_offset = core::mem::offset_of!(Flags, active);
bytes[bool_offset] = 2;
assert!(matches!(
Region::<Flags>::from_bytes(&bytes),
Err(ValidateError::InvalidBool { .. })
));Sourcepub unsafe fn from_bytes_unchecked(bytes: &[u8]) -> Self
pub unsafe fn from_bytes_unchecked(bytes: &[u8]) -> Self
Reconstruct a region from raw bytes without validation.
This is the unsafe fast path for deserialization. The bytes are copied into a fresh aligned buffer but no validation is performed — no bounds checks, no pointer validation, no discriminant checks.
For a safe alternative that validates the buffer, use
from_bytes.
§Safety
The caller must guarantee all of the following:
byteswas originally produced byas_byteson a validRegion<T>(or is byte-for-byte identical to such output).- The buffer contains a valid representation of
Tat byte offset 0, with correct size (bytes.len() >= size_of::<T>()). - All
Near<U>self-relative offsets resolve to in-bounds, correctly aligned addresses within the buffer, and the target bytes form a validU. - All
NearList<U>headers have in-bounds segment chains with correct lengths, and every element is a validU. - All enum discriminants are valid for their
#[repr]. - All
boolvalues are0or1. - No
Option<Near<T>>contains a bit pattern that is neitherNonenor a validSome(Near<T>).
Violating any of these preconditions causes undefined behavior on subsequent reads through the region.
§Examples
use nearest::{Flat, NearList, Region, list};
#[derive(Flat, Debug)]
struct Node {
id: u32,
children: NearList<u32>,
}
let original = Region::new(Node::make(1, list([10u32, 20, 30])));
let bytes = original.as_bytes();
// SAFETY: `bytes` was produced by `as_bytes()` on a valid `Region<Node>`.
let restored: Region<Node> = unsafe { Region::from_bytes_unchecked(bytes) };
assert_eq!(restored.id, 1);
assert_eq!(restored.children.len(), 3);Sourcepub unsafe fn from_buf_unchecked(buf: B) -> Self
pub unsafe fn from_buf_unchecked(buf: B) -> Self
Reconstruct a region from a pre-existing buffer without validation.
Unlike from_bytes_unchecked, this takes
an already-allocated buffer B, avoiding an extra copy when the caller
already has an aligned buffer (e.g. memory-mapped I/O with a
FixedBuf).
§Safety
The caller must guarantee all of the following:
bufcontains a valid representation ofTat byte offset 0, withbuf.len() >= size_of::<T>().- The buffer base is aligned to at least
align_of::<T>()(guaranteed by theBuftrait, but the contents must also be valid). - All
Near<U>self-relative offsets resolve to in-bounds, correctly aligned addresses within the buffer, and the target bytes form a validU. - All
NearList<U>headers have in-bounds segment chains with correct lengths, and every element is a validU. - All enum discriminants are valid for their
#[repr]. - All
boolvalues are0or1. - No
Option<Near<T>>contains a bit pattern that is neitherNonenor a validSome(Near<T>).
Violating any of these preconditions causes undefined behavior on subsequent reads through the region.
§Examples
use nearest::{Buf, Flat, NearList, Region, FixedBuf, list};
#[derive(Flat, Debug)]
struct Node {
id: u32,
children: NearList<u32>,
}
let original: Region<Node, FixedBuf<256>> =
Region::new_in(Node::make(1, list([10u32, 20, 30])));
let bytes = original.as_bytes();
let mut buf = FixedBuf::<256>::new();
buf.extend_from_slice(bytes);
// SAFETY: `buf` contains bytes from a valid `Region<Node>`.
let restored: Region<Node, FixedBuf<256>> =
unsafe { Region::from_buf_unchecked(buf) };
assert_eq!(restored.id, 1);
assert_eq!(restored.children.len(), 3);Trait Implementations§
Source§impl<'de, T: Flat, B: Buf> Deserialize<'de> for Region<T, B>
Available on crate feature serde only.
impl<'de, T: Flat, B: Buf> Deserialize<'de> for Region<T, B>
serde only.