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
use linkrs_core::{StorageError, StorageResult};
use super::super::{EdgeId, EdgePosition, Nbr, Timestamp, VertexId};
use super::CsrVariant;
impl CsrVariant {
/// Whether this group stores its single scalar inline.
pub fn is_bundled(&self) -> bool {
matches!(self, CsrVariant::Bundled(_))
}
/// Insert one edge carrying its inline value.
///
/// Only the bundled form accepts a value; every other form rejects the
/// call instead of silently dropping the property.
pub fn insert_edge_with_value(
&mut self,
src_vid: u32,
dst: VertexId,
edge_id: EdgeId,
value: Option<u64>,
) -> StorageResult<()> {
match self {
CsrVariant::Bundled(csr) => csr.insert_edge_with_value(src_vid, dst, edge_id, value),
_ => Err(StorageError::invalid_operation(
"inline values require the bundled record form".to_string(),
)),
}
}
/// Read one edge's inline value within its source row.
///
/// Paired value half of a bundled topology walk: resolve the edge id
/// from the topology walk first, then read its value here. Frozen groups
/// packed from a valued bundled group serve their carried values; other
/// forms and unvalued packs report no value.
pub fn bundled_value_by_edge_id(&self, src_vid: u32, edge_id: EdgeId) -> Option<(u64, bool)> {
match self {
CsrVariant::Bundled(csr) => csr.value_by_edge_id(src_vid, edge_id),
CsrVariant::Frozen(csr) => csr.value_by_edge_id(src_vid, edge_id),
_ => None,
}
}
/// Overwrite one edge's inline value within its source row.
pub fn bundled_set_value_by_edge_id(
&mut self,
src_vid: u32,
edge_id: EdgeId,
value: Option<u64>,
) -> bool {
match self {
CsrVariant::Bundled(csr) => csr.set_value_by_edge_id(src_vid, edge_id, value),
_ => false,
}
}
/// Read the inline value of the live edge for one endpoint.
pub fn bundled_value_by_endpoint(&self, src_vid: u32, endpoint: u32) -> Option<(u64, bool)> {
match self {
CsrVariant::Bundled(csr) => csr.value_by_endpoint(src_vid, endpoint),
CsrVariant::Frozen(csr) => csr.value_by_endpoint(src_vid, endpoint),
_ => None,
}
}
/// Overwrite the inline value of the live edge for one endpoint.
pub fn bundled_set_value_by_endpoint(
&mut self,
src_vid: u32,
endpoint: u32,
value: Option<u64>,
) -> bool {
match self {
CsrVariant::Bundled(csr) => csr.set_value_by_endpoint(src_vid, endpoint, value),
_ => false,
}
}
/// Revert a deletion restoring the caller's value alongside the topology.
pub fn bundled_revert_with_value(
&mut self,
src_vid: u32,
position: EdgePosition,
expected: EdgeId,
ts: Timestamp,
value: Option<u64>,
) -> bool {
match self {
CsrVariant::Bundled(csr) => {
csr.revert_delete_at_position_with_value(src_vid, position, expected, ts, value)
}
_ => false,
}
}
/// Visit every physically stored entry of one vertex with its inline
/// value (`None` for NULL slots). Non-bundled forms visit with `None`.
///
/// Paired topology-plus-value walk for bundled rows: this is the only
/// bundled traversal yielding values. Topology-only walks
/// (`visit_physical`, `fill_physical_into`, row iterators) never yield
/// values and must not be paired ad hoc elsewhere. Frozen groups walk
/// their carried value columns the same way.
pub fn visit_physical_with_values<F>(&self, src_vid: u32, mut f: F)
where
F: FnMut(Nbr, Option<u64>) -> bool,
{
match self {
CsrVariant::Bundled(csr) => csr.visit_physical_with_values(src_vid, f),
CsrVariant::Frozen(csr) => csr.visit_physical_with_values(src_vid, f),
_ => self.visit_physical(src_vid, |nbr| f(nbr, None)),
}
}
/// Whether any slot holds a valid inline value.
pub fn bundled_has_valid_values(&self) -> bool {
match self {
CsrVariant::Bundled(csr) => csr.any_valid_values(),
CsrVariant::Frozen(csr) => csr.any_valid_values(),
_ => false,
}
}
/// Fill a caller buffer with paired topology plus inline values.
///
/// Batched counterpart of the paired walk above for scans reusing one
/// buffer across vertices. Non-bundled forms fill with `None` values.
pub fn fill_physical_with_values_into(&self, src_vid: u32, out: &mut Vec<(Nbr, Option<u64>)>) {
out.clear();
self.visit_physical_with_values(src_vid, |nbr, value| {
out.push((nbr, value));
true
});
}
}