1#![no_std]
15
16use core::fmt;
17
18use oxgraph_csr::{CsrEdgeId, CsrGraph, CsrNodeId, CsrSnapshotError, CsrSnapshotIndex};
19use oxgraph_graph::{ElementPredecessors, OutgoingNeighborsGraph, TopologyCounts};
20use oxgraph_layout_util::{NodeAxis, SnapshotWidth};
21use oxgraph_snapshot::Snapshot;
22use oxgraph_topology::TopologyBase;
23
24pub type CscNodeId<N = u32> = oxgraph_layout_util::LocalId<NodeAxis, N>;
33
34#[derive(Debug, Clone, PartialEq, Eq)]
36pub enum CscSnapshotError<N = u32, E = u32> {
37 Layout(CsrSnapshotError<N, E>),
39}
40
41impl<N: fmt::Display, E: fmt::Display> fmt::Display for CscSnapshotError<N, E> {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 match self {
44 Self::Layout(error) => write!(f, "inbound layout error: {error}"),
45 }
46 }
47}
48
49impl<N, E> core::error::Error for CscSnapshotError<N, E>
50where
51 N: fmt::Debug + fmt::Display,
52 E: fmt::Debug + fmt::Display,
53{
54}
55
56impl<N, E> From<CsrSnapshotError<N, E>> for CscSnapshotError<N, E> {
57 fn from(error: CsrSnapshotError<N, E>) -> Self {
58 Self::Layout(error)
59 }
60}
61
62pub type CscInnerGraph<'view, N = u32, E = u32> = CsrGraph<
68 'view,
69 N,
70 E,
71 <E as SnapshotWidth>::LittleEndianWord,
72 <N as SnapshotWidth>::LittleEndianWord,
73>;
74
75#[derive(Clone, Copy)]
84pub struct CscSnapshotGraph<'view, N = u32, E = u32>(CscInnerGraph<'view, N, E>)
85where
86 N: CsrSnapshotIndex,
87 E: CsrSnapshotIndex;
88
89impl<N, E> fmt::Debug for CscSnapshotGraph<'_, N, E>
90where
91 N: CsrSnapshotIndex,
92 E: CsrSnapshotIndex,
93{
94 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
95 formatter
96 .debug_struct("CscSnapshotGraph")
97 .field("node_count", &self.node_count())
98 .field("relation_count", &self.relation_count())
99 .finish()
100 }
101}
102
103impl<'view, N, E> CscSnapshotGraph<'view, N, E>
104where
105 N: CsrSnapshotIndex,
106 E: CsrSnapshotIndex,
107{
108 pub fn from_snapshot_with_kinds(
123 snapshot: &Snapshot<'view>,
124 offsets_kind: u32,
125 targets_kind: u32,
126 version: u32,
127 ) -> Result<Self, CscSnapshotError<N, E>> {
128 let inner = CscInnerGraph::<'view, N, E>::from_snapshot_with_kinds(
129 snapshot,
130 offsets_kind,
131 targets_kind,
132 version,
133 )?;
134 Ok(Self(inner))
135 }
136
137 #[must_use]
139 pub const fn inner(&self) -> &CscInnerGraph<'view, N, E> {
140 &self.0
141 }
142
143 #[must_use]
149 pub fn node_count(&self) -> usize {
150 self.0.element_count()
151 }
152
153 #[must_use]
159 pub fn relation_count(&self) -> usize {
160 self.0.relation_count()
161 }
162
163 pub fn predecessors(
169 &self,
170 target: CscNodeId<N>,
171 ) -> impl ExactSizeIterator<Item = CscNodeId<N>> + '_ {
172 self.0
173 .outgoing_neighbors(CsrNodeId::new(target.get()))
174 .map(|id| CscNodeId::new(id.get()))
175 }
176
177 pub fn for_each_predecessor(
185 &self,
186 target: CscNodeId<N>,
187 mut visit: impl FnMut(CscNodeId<N>) -> bool,
188 ) -> bool {
189 self.0
190 .for_each_out_target(CsrNodeId::new(target.get()), |id| {
191 visit(CscNodeId::new(id.get()))
192 })
193 }
194}
195
196pub struct CscPredecessors<'view, N = u32, E = u32>
198where
199 N: CsrSnapshotIndex + 'view,
200 E: CsrSnapshotIndex + 'view,
201{
202 inner: <CscInnerGraph<'view, N, E> as OutgoingNeighborsGraph>::OutNeighbors<'view>,
204}
205
206impl<N, E> Iterator for CscPredecessors<'_, N, E>
207where
208 N: CsrSnapshotIndex,
209 E: CsrSnapshotIndex,
210{
211 type Item = CscNodeId<N>;
212
213 fn next(&mut self) -> Option<Self::Item> {
214 self.inner.next().map(|id| CscNodeId::new(id.get()))
215 }
216
217 fn size_hint(&self) -> (usize, Option<usize>) {
218 self.inner.size_hint()
219 }
220}
221
222impl<N, E> ExactSizeIterator for CscPredecessors<'_, N, E>
223where
224 N: CsrSnapshotIndex,
225 E: CsrSnapshotIndex,
226{
227}
228
229impl<N, E> TopologyBase for CscSnapshotGraph<'_, N, E>
230where
231 N: CsrSnapshotIndex,
232 E: CsrSnapshotIndex,
233{
234 type ElementId = CscNodeId<N>;
235 type RelationId = CsrEdgeId<E>;
236}
237
238impl<N, E> TopologyCounts for CscSnapshotGraph<'_, N, E>
239where
240 N: CsrSnapshotIndex,
241 E: CsrSnapshotIndex,
242{
243 fn element_count(&self) -> usize {
244 self.0.element_count()
245 }
246
247 fn relation_count(&self) -> usize {
248 self.0.relation_count()
249 }
250}
251
252impl<N, E> ElementPredecessors for CscSnapshotGraph<'_, N, E>
253where
254 N: CsrSnapshotIndex,
255 E: CsrSnapshotIndex,
256{
257 type Predecessors<'view>
258 = CscPredecessors<'view, N, E>
259 where
260 Self: 'view;
261
262 fn element_predecessors(&self, element: CscNodeId<N>) -> Self::Predecessors<'_> {
263 CscPredecessors {
264 inner: self.0.outgoing_neighbors(CsrNodeId::new(element.get())),
265 }
266 }
267}
268
269#[cfg(kani)]
270mod proofs;