Skip to main content

linkrs_storage/edge/csr_variant/
values.rs

1use linkrs_core::{StorageError, StorageResult};
2
3use super::super::{EdgeId, EdgePosition, Nbr, Timestamp, VertexId};
4use super::CsrVariant;
5
6impl CsrVariant {
7    /// Whether this group stores its single scalar inline.
8    pub fn is_bundled(&self) -> bool {
9        matches!(self, CsrVariant::Bundled(_))
10    }
11
12    /// Insert one edge carrying its inline value.
13    ///
14    /// Only the bundled form accepts a value; every other form rejects the
15    /// call instead of silently dropping the property.
16    pub fn insert_edge_with_value(
17        &mut self,
18        src_vid: u32,
19        dst: VertexId,
20        edge_id: EdgeId,
21        value: Option<u64>,
22    ) -> StorageResult<()> {
23        match self {
24            CsrVariant::Bundled(csr) => csr.insert_edge_with_value(src_vid, dst, edge_id, value),
25            _ => Err(StorageError::invalid_operation(
26                "inline values require the bundled record form".to_string(),
27            )),
28        }
29    }
30
31    /// Read one edge's inline value within its source row.
32    ///
33    /// Paired value half of a bundled topology walk: resolve the edge id
34    /// from the topology walk first, then read its value here. Frozen groups
35    /// packed from a valued bundled group serve their carried values; other
36    /// forms and unvalued packs report no value.
37    pub fn bundled_value_by_edge_id(&self, src_vid: u32, edge_id: EdgeId) -> Option<(u64, bool)> {
38        match self {
39            CsrVariant::Bundled(csr) => csr.value_by_edge_id(src_vid, edge_id),
40            CsrVariant::Frozen(csr) => csr.value_by_edge_id(src_vid, edge_id),
41            _ => None,
42        }
43    }
44
45    /// Overwrite one edge's inline value within its source row.
46    pub fn bundled_set_value_by_edge_id(
47        &mut self,
48        src_vid: u32,
49        edge_id: EdgeId,
50        value: Option<u64>,
51    ) -> bool {
52        match self {
53            CsrVariant::Bundled(csr) => csr.set_value_by_edge_id(src_vid, edge_id, value),
54            _ => false,
55        }
56    }
57
58    /// Read the inline value of the live edge for one endpoint.
59    pub fn bundled_value_by_endpoint(&self, src_vid: u32, endpoint: u32) -> Option<(u64, bool)> {
60        match self {
61            CsrVariant::Bundled(csr) => csr.value_by_endpoint(src_vid, endpoint),
62            CsrVariant::Frozen(csr) => csr.value_by_endpoint(src_vid, endpoint),
63            _ => None,
64        }
65    }
66
67    /// Overwrite the inline value of the live edge for one endpoint.
68    pub fn bundled_set_value_by_endpoint(
69        &mut self,
70        src_vid: u32,
71        endpoint: u32,
72        value: Option<u64>,
73    ) -> bool {
74        match self {
75            CsrVariant::Bundled(csr) => csr.set_value_by_endpoint(src_vid, endpoint, value),
76            _ => false,
77        }
78    }
79
80    /// Revert a deletion restoring the caller's value alongside the topology.
81    pub fn bundled_revert_with_value(
82        &mut self,
83        src_vid: u32,
84        position: EdgePosition,
85        expected: EdgeId,
86        ts: Timestamp,
87        value: Option<u64>,
88    ) -> bool {
89        match self {
90            CsrVariant::Bundled(csr) => {
91                csr.revert_delete_at_position_with_value(src_vid, position, expected, ts, value)
92            }
93            _ => false,
94        }
95    }
96
97    /// Visit every physically stored entry of one vertex with its inline
98    /// value (`None` for NULL slots). Non-bundled forms visit with `None`.
99    ///
100    /// Paired topology-plus-value walk for bundled rows: this is the only
101    /// bundled traversal yielding values. Topology-only walks
102    /// (`visit_physical`, `fill_physical_into`, row iterators) never yield
103    /// values and must not be paired ad hoc elsewhere. Frozen groups walk
104    /// their carried value columns the same way.
105    pub fn visit_physical_with_values<F>(&self, src_vid: u32, mut f: F)
106    where
107        F: FnMut(Nbr, Option<u64>) -> bool,
108    {
109        match self {
110            CsrVariant::Bundled(csr) => csr.visit_physical_with_values(src_vid, f),
111            CsrVariant::Frozen(csr) => csr.visit_physical_with_values(src_vid, f),
112            _ => self.visit_physical(src_vid, |nbr| f(nbr, None)),
113        }
114    }
115
116    /// Whether any slot holds a valid inline value.
117    pub fn bundled_has_valid_values(&self) -> bool {
118        match self {
119            CsrVariant::Bundled(csr) => csr.any_valid_values(),
120            CsrVariant::Frozen(csr) => csr.any_valid_values(),
121            _ => false,
122        }
123    }
124
125    /// Fill a caller buffer with paired topology plus inline values.
126    ///
127    /// Batched counterpart of the paired walk above for scans reusing one
128    /// buffer across vertices. Non-bundled forms fill with `None` values.
129    pub fn fill_physical_with_values_into(&self, src_vid: u32, out: &mut Vec<(Nbr, Option<u64>)>) {
130        out.clear();
131        self.visit_physical_with_values(src_vid, |nbr, value| {
132            out.push((nbr, value));
133            true
134        });
135    }
136}