1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
//! Internal helper macros for the typed collection wrappers.
//!
//! None of these are part of the public API — they are `pub(crate)`
//! re-exports usable only inside the `vsdb` crate.
macro_rules! define_map_wrapper {
(
$(#[$struct_doc:meta])*
$vis:vis struct $wrapper_name:ident <$($wrapper_generics:tt),*> {
$inner_vis:vis inner: $inner_type:ty,
$phantom_field:ident: $phantom_type:ty,
}
where $($trait_bounds:tt)+
) => {
$(#[$struct_doc])*
#[derive(PartialEq, Eq, Debug)]
$vis struct $wrapper_name<$($wrapper_generics),*> {
$inner_vis inner: $inner_type,
$phantom_field: $phantom_type,
}
impl<$($wrapper_generics),*> serde::Serialize for $wrapper_name<$($wrapper_generics),*> {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.inner.serialize(serializer)
}
}
impl<'de, $($wrapper_generics),*> serde::Deserialize<'de> for $wrapper_name<$($wrapper_generics),*> {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
<$inner_type as serde::Deserialize>::deserialize(deserializer)
.map(|inner| Self { inner, $phantom_field: std::marker::PhantomData })
}
}
impl<$($wrapper_generics),*> $wrapper_name<$($wrapper_generics),*>
where
$($trait_bounds)+
{
/// # Safety
///
/// Creates a second handle to the same underlying storage, bypassing
/// Rust's aliasing guarantees. The caller **must** enforce
/// Single-Writer-Multiple-Readers (SWMR) for the entire lifetime
/// of the shadow:
///
/// - No `insert`, `remove`, `set_value`, or other mutation may occur
/// on the original **or** any other shadow while the shadow exists.
/// - Multiple concurrent *reads* are permitted.
/// - All shadows must be dropped before the next write.
#[inline(always)]
pub unsafe fn shadow(&self) -> Self {
Self {
// SAFETY: forwards this fn's `unsafe` contract — the
// caller guarantees the SWMR discipline (no concurrent
// writes through the shadow and the original).
inner: unsafe { self.inner.shadow() },
$phantom_field: std::marker::PhantomData,
}
}
/// # Safety
///
/// Reconstructs a handle from a raw byte slice that was previously
/// produced by [`as_bytes`](Self::as_bytes) on a valid instance of
/// the **same type and code version**. Passing any other bytes
/// (corrupted, truncated, from a different type, or from an
/// incompatible code version) is undefined behavior and may cause
/// panics or silent data corruption on subsequent operations.
#[inline(always)]
pub unsafe fn from_bytes(s: impl AsRef<[u8]>) -> Self {
Self {
// SAFETY: forwards this fn's `unsafe` contract — the
// caller guarantees `s` was produced by `as_bytes()` on
// the same type and code version.
inner: unsafe { <$inner_type>::from_bytes(s) },
$phantom_field: std::marker::PhantomData,
}
}
#[inline(always)]
pub fn as_bytes(&self) -> &[u8] {
self.inner.as_bytes()
}
#[inline(always)]
pub fn new() -> Self {
Self {
inner: <$inner_type>::new(),
$phantom_field: std::marker::PhantomData,
}
}
#[inline(always)]
pub fn clear(&mut self) {
self.inner.clear();
}
#[inline(always)]
pub fn is_the_same_instance(&self, other_hdr: &Self) -> bool {
self.inner.is_the_same_instance(&other_hdr.inner)
}
/// Returns the unique instance ID of this data structure.
#[inline(always)]
pub fn instance_id(&self) -> u64 {
let mut bytes = [0u8; 8];
bytes.copy_from_slice(self.as_bytes());
u64::from_le_bytes(bytes)
}
/// Persists this instance's metadata to disk so that it can be
/// recovered later via [`from_meta`](Self::from_meta).
///
/// Returns the `instance_id` that should be passed to `from_meta`.
pub fn save_meta(&self) -> $crate::common::error::Result<u64> {
let id = self.instance_id();
$crate::common::save_instance_meta(id, self)?;
Ok(id)
}
/// Recovers an instance from previously saved metadata.
///
/// The caller must ensure that the underlying VSDB database still
/// contains the data referenced by this instance ID.
pub fn from_meta(instance_id: u64) -> $crate::common::error::Result<Self> {
$crate::common::load_instance_meta(instance_id)
}
}
impl<$($wrapper_generics),*> Clone for $wrapper_name<$($wrapper_generics),*>
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
$phantom_field: std::marker::PhantomData,
}
}
}
impl<$($wrapper_generics),*> Default for $wrapper_name<$($wrapper_generics),*>
where
$($trait_bounds)+
{
fn default() -> Self {
Self::new()
}
}
};
}
pub(crate) use define_map_wrapper;
macro_rules! entry_or_insert_via_mock {
($slf:expr, $hdr_ty:ty, $get_mut_call:ident($($get_mut_args:expr),*), $mock_call:ident($($mock_args:expr),*)) => {{
let hdr = $slf.hdr as *mut $hdr_ty;
// SAFETY: `hdr` is derived from `$slf.hdr: &'a mut $hdr_ty`.
// The two dereferences are in mutually exclusive match arms and
// never coexist; no aliasing occurs.
match unsafe { &mut *hdr }.$get_mut_call($($get_mut_args),*) {
Some(v) => v,
_ => unsafe { &mut *hdr }.$mock_call($($mock_args),*),
}
}};
}
pub(crate) use entry_or_insert_via_mock;
macro_rules! cow_bytes_bounds {
($bounds:expr) => {{
use std::{borrow::Cow, ops::Bound};
// Bind once: evaluating `$bounds` twice could yield inconsistent
// start/end bounds for non-idempotent expressions.
let b = &($bounds);
let l = match b.start_bound() {
Bound::Included(lo) => Bound::Included(Cow::Owned(
$crate::common::ende::KeyEnDeOrdered::to_bytes(lo),
)),
Bound::Excluded(lo) => Bound::Excluded(Cow::Owned(
$crate::common::ende::KeyEnDeOrdered::to_bytes(lo),
)),
Bound::Unbounded => Bound::Unbounded,
};
let h = match b.end_bound() {
Bound::Included(hi) => Bound::Included(Cow::Owned(
$crate::common::ende::KeyEnDeOrdered::to_bytes(hi),
)),
Bound::Excluded(hi) => Bound::Excluded(Cow::Owned(
$crate::common::ende::KeyEnDeOrdered::to_bytes(hi),
)),
Bound::Unbounded => Bound::Unbounded,
};
(l, h)
}};
}
pub(crate) use cow_bytes_bounds;