raphtory_storage/graph/
graph.rs

1use super::{
2    edges::{edge_entry::EdgeStorageEntry, unlocked::UnlockedEdges},
3    nodes::node_entry::NodeStorageEntry,
4};
5use crate::graph::{
6    edges::edges::{EdgesStorage, EdgesStorageRef},
7    locked::LockedGraph,
8    nodes::{nodes::NodesStorage, nodes_ref::NodesStorageEntry},
9};
10use raphtory_api::core::entities::{properties::meta::Meta, LayerIds, LayerVariants, EID, VID};
11use raphtory_core::entities::{
12    graph::tgraph::TemporalGraph, nodes::node_ref::NodeRef, properties::graph_meta::GraphMeta,
13};
14use serde::{Deserialize, Serialize};
15use std::{fmt::Debug, iter, sync::Arc};
16use thiserror::Error;
17
18#[cfg(feature = "storage")]
19use crate::disk::{
20    storage_interface::{
21        edges::DiskEdges, edges_ref::DiskEdgesRef, node::DiskNode, nodes::DiskNodesOwned,
22        nodes_ref::DiskNodesRef,
23    },
24    DiskGraphStorage,
25};
26use crate::mutation::MutationError;
27
28#[derive(Clone, Debug, Serialize, Deserialize)]
29pub enum GraphStorage {
30    Mem(LockedGraph),
31    Unlocked(Arc<TemporalGraph>),
32    #[cfg(feature = "storage")]
33    Disk(Arc<DiskGraphStorage>),
34}
35
36#[derive(Error, Debug)]
37pub enum Immutable {
38    #[error("The graph is locked and cannot be mutated")]
39    ReadLockedImmutable,
40    #[cfg(feature = "storage")]
41    #[error("DiskGraph cannot be mutated")]
42    DiskGraphImmutable,
43}
44
45impl From<TemporalGraph> for GraphStorage {
46    fn from(value: TemporalGraph) -> Self {
47        Self::Unlocked(Arc::new(value))
48    }
49}
50
51#[cfg(feature = "storage")]
52impl From<DiskGraphStorage> for GraphStorage {
53    fn from(value: DiskGraphStorage) -> Self {
54        Self::Disk(Arc::new(value))
55    }
56}
57
58impl Default for GraphStorage {
59    fn default() -> Self {
60        GraphStorage::Unlocked(Arc::new(TemporalGraph::default()))
61    }
62}
63
64impl std::fmt::Display for GraphStorage {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        write!(
67            f,
68            "Graph(num_nodes={}, num_edges={})",
69            self.unfiltered_num_nodes(),
70            self.unfiltered_num_edges(),
71        )
72    }
73}
74
75impl GraphStorage {
76    /// Check if two storage instances point at the same underlying storage
77    pub fn ptr_eq(&self, other: &Self) -> bool {
78        match self {
79            GraphStorage::Mem(LockedGraph {
80                graph: this_graph, ..
81            })
82            | GraphStorage::Unlocked(this_graph) => match other {
83                GraphStorage::Mem(LockedGraph {
84                    graph: other_graph, ..
85                })
86                | GraphStorage::Unlocked(other_graph) => Arc::ptr_eq(this_graph, other_graph),
87                #[cfg(feature = "storage")]
88                _ => false,
89            },
90            #[cfg(feature = "storage")]
91            GraphStorage::Disk(this_graph) => match other {
92                GraphStorage::Disk(other_graph) => Arc::ptr_eq(this_graph, other_graph),
93                _ => false,
94            },
95        }
96    }
97
98    pub fn mutable(&self) -> Result<&Arc<TemporalGraph>, MutationError> {
99        match self {
100            GraphStorage::Mem(_) => Err(Immutable::ReadLockedImmutable)?,
101            GraphStorage::Unlocked(graph) => Ok(graph),
102            #[cfg(feature = "storage")]
103            GraphStorage::Disk(_) => Err(Immutable::DiskGraphImmutable)?,
104        }
105    }
106
107    #[inline(always)]
108    pub fn is_immutable(&self) -> bool {
109        match self {
110            GraphStorage::Mem(_) => true,
111            GraphStorage::Unlocked(_) => false,
112            #[cfg(feature = "storage")]
113            GraphStorage::Disk(_) => true,
114        }
115    }
116
117    #[inline(always)]
118    pub fn lock(&self) -> Self {
119        match self {
120            GraphStorage::Unlocked(storage) => {
121                let locked = LockedGraph::new(storage.clone());
122                GraphStorage::Mem(locked)
123            }
124            _ => self.clone(),
125        }
126    }
127
128    #[inline(always)]
129    pub fn nodes(&self) -> NodesStorageEntry<'_> {
130        match self {
131            GraphStorage::Mem(storage) => NodesStorageEntry::Mem(&storage.nodes),
132            GraphStorage::Unlocked(storage) => {
133                NodesStorageEntry::Unlocked(storage.storage.nodes.read_lock())
134            }
135            #[cfg(feature = "storage")]
136            GraphStorage::Disk(storage) => {
137                NodesStorageEntry::Disk(DiskNodesRef::new(&storage.inner))
138            }
139        }
140    }
141
142    #[inline(always)]
143    pub fn internalise_node(&self, v: NodeRef) -> Option<VID> {
144        match v {
145            NodeRef::Internal(vid) => Some(vid),
146            node_ref => match self {
147                GraphStorage::Mem(locked) => locked.graph.resolve_node_ref(node_ref),
148                GraphStorage::Unlocked(unlocked) => unlocked.resolve_node_ref(node_ref),
149                #[cfg(feature = "storage")]
150                GraphStorage::Disk(storage) => match v {
151                    NodeRef::External(id) => storage.inner.find_node(id),
152                    _ => unreachable!("VID is handled above!"),
153                },
154            },
155        }
156    }
157
158    #[inline(always)]
159    pub fn unfiltered_num_nodes(&self) -> usize {
160        match self {
161            GraphStorage::Mem(storage) => storage.nodes.len(),
162            GraphStorage::Unlocked(storage) => storage.internal_num_nodes(),
163            #[cfg(feature = "storage")]
164            GraphStorage::Disk(storage) => storage.inner.num_nodes(),
165        }
166    }
167
168    #[inline(always)]
169    pub fn unfiltered_num_edges(&self) -> usize {
170        match self {
171            GraphStorage::Mem(storage) => storage.edges.len(),
172            GraphStorage::Unlocked(storage) => storage.storage.edges_len(),
173            #[cfg(feature = "storage")]
174            GraphStorage::Disk(storage) => storage.inner.count_edges(),
175        }
176    }
177
178    #[inline(always)]
179    pub fn unfiltered_num_layers(&self) -> usize {
180        match self {
181            GraphStorage::Mem(storage) => storage.graph.num_layers(),
182            GraphStorage::Unlocked(storage) => storage.num_layers(),
183            #[cfg(feature = "storage")]
184            GraphStorage::Disk(storage) => storage.inner.layers().len(),
185        }
186    }
187
188    #[inline(always)]
189    pub fn core_nodes(&self) -> NodesStorage {
190        match self {
191            GraphStorage::Mem(storage) => NodesStorage::Mem(storage.nodes.clone()),
192            GraphStorage::Unlocked(storage) => {
193                NodesStorage::Mem(LockedGraph::new(storage.clone()).nodes.clone())
194            }
195            #[cfg(feature = "storage")]
196            GraphStorage::Disk(storage) => {
197                NodesStorage::Disk(DiskNodesOwned::new(storage.inner.clone()))
198            }
199        }
200    }
201
202    #[inline(always)]
203    pub fn core_node<'a>(&'a self, vid: VID) -> NodeStorageEntry<'a> {
204        match self {
205            GraphStorage::Mem(storage) => NodeStorageEntry::Mem(storage.nodes.get_entry(vid)),
206            GraphStorage::Unlocked(storage) => {
207                NodeStorageEntry::Unlocked(storage.storage.get_node(vid))
208            }
209            #[cfg(feature = "storage")]
210            GraphStorage::Disk(storage) => {
211                NodeStorageEntry::Disk(DiskNode::new(&storage.inner, vid))
212            }
213        }
214    }
215
216    /// Try to get a node that may not be initialised yet
217    pub fn try_core_node<'a>(&'a self, vid: VID) -> Option<NodeStorageEntry<'a>> {
218        match self {
219            GraphStorage::Mem(storage) => {
220                storage.nodes.try_get_entry(vid).map(NodeStorageEntry::Mem)
221            }
222            GraphStorage::Unlocked(storage) => storage
223                .storage
224                .nodes
225                .try_entry(vid)
226                .map(NodeStorageEntry::Unlocked),
227            #[cfg(feature = "storage")]
228            GraphStorage::Disk(storage) => {
229                if vid.index() < storage.inner().num_nodes() {
230                    Some(NodeStorageEntry::Disk(DiskNode::new(storage.inner(), vid)))
231                } else {
232                    None
233                }
234            }
235        }
236    }
237
238    #[inline(always)]
239    pub fn edges(&self) -> EdgesStorageRef<'_> {
240        match self {
241            GraphStorage::Mem(storage) => EdgesStorageRef::Mem(&storage.edges),
242            GraphStorage::Unlocked(storage) => {
243                EdgesStorageRef::Unlocked(UnlockedEdges(&storage.storage))
244            }
245            #[cfg(feature = "storage")]
246            GraphStorage::Disk(storage) => EdgesStorageRef::Disk(DiskEdgesRef::new(&storage.inner)),
247        }
248    }
249
250    #[inline(always)]
251    pub fn owned_edges(&self) -> EdgesStorage {
252        match self {
253            GraphStorage::Mem(storage) => EdgesStorage::Mem(storage.edges.clone()),
254            GraphStorage::Unlocked(storage) => {
255                GraphStorage::Mem(LockedGraph::new(storage.clone())).owned_edges()
256            }
257            #[cfg(feature = "storage")]
258            GraphStorage::Disk(storage) => EdgesStorage::Disk(DiskEdges::new(storage)),
259        }
260    }
261
262    #[inline(always)]
263    pub fn edge_entry(&self, eid: EID) -> EdgeStorageEntry<'_> {
264        match self {
265            GraphStorage::Mem(storage) => EdgeStorageEntry::Mem(storage.edges.get_mem(eid)),
266            GraphStorage::Unlocked(storage) => {
267                EdgeStorageEntry::Unlocked(storage.storage.edge_entry(eid))
268            }
269            #[cfg(feature = "storage")]
270            GraphStorage::Disk(storage) => EdgeStorageEntry::Disk(storage.inner.edge(eid)),
271        }
272    }
273
274    pub fn layer_ids_iter(&self, layer_ids: &LayerIds) -> impl Iterator<Item = usize> {
275        match layer_ids {
276            LayerIds::None => LayerVariants::None(iter::empty()),
277            LayerIds::All => LayerVariants::All(0..self.unfiltered_num_layers()),
278            LayerIds::One(id) => LayerVariants::One(iter::once(*id)),
279            LayerIds::Multiple(ids) => LayerVariants::Multiple(ids.into_iter()),
280        }
281    }
282    //
283    // pub fn into_nodes_iter<'graph, G: GraphViewOps<'graph>>(
284    //     self,
285    //     view: G,
286    //     node_list: NodeList,
287    //     type_filter: Option<Arc<[bool]>>,
288    // ) -> BoxedLIter<'graph, VID> {
289    //     node_list
290    //         .into_iter()
291    //         .filter(move |&vid| {
292    //             let node = self.node_entry(vid);
293    //             type_filter
294    //                 .as_ref()
295    //                 .map_or(true, |type_filter| type_filter[node.node_type_id()])
296    //                 && view.filter_node(node.as_ref())
297    //         })
298    //         .into_dyn_boxed()
299    // }
300    //
301    // pub fn nodes_par<'a, 'graph: 'a, G: GraphViewOps<'graph>>(
302    //     &'a self,
303    //     view: &'a G,
304    //     type_filter: Option<&'a Arc<[bool]>>,
305    // ) -> impl ParallelIterator<Item = VID> + 'a {
306    //     let nodes = self.nodes();
307    //     view.node_list().into_par_iter().filter(move |&vid| {
308    //         let node = nodes.node(vid);
309    //         type_filter.map_or(true, |type_filter| type_filter[node.node_type_id()])
310    //             && view.filter_node(node)
311    //     })
312    // }
313    //
314    // pub fn into_nodes_par<'graph, G: GraphViewOps<'graph>>(
315    //     self,
316    //     view: G,
317    //     node_list: NodeList,
318    //     type_filter: Option<Arc<[bool]>>,
319    // ) -> impl ParallelIterator<Item = VID> + 'graph {
320    //     node_list.into_par_iter().filter(move |&vid| {
321    //         let node = self.node_entry(vid);
322    //         type_filter
323    //             .as_ref()
324    //             .map_or(true, |type_filter| type_filter[node.node_type_id()])
325    //             && view.filter_node(node.as_ref())
326    //     })
327    // }
328    //
329    // pub fn edges_iter<'graph, G: GraphViewOps<'graph>>(
330    //     &'graph self,
331    //     view: &'graph G,
332    // ) -> impl Iterator<Item = EdgeRef> + Send + 'graph {
333    //     let iter = self.edges().iter(view.layer_ids());
334    //
335    //     let filtered = match view.filter_state() {
336    //         FilterState::Neither => FilterVariants::Neither(iter),
337    //         FilterState::Both => {
338    //             let nodes = self.nodes();
339    //             FilterVariants::Both(iter.filter(move |e| {
340    //                 view.filter_edge(e.as_ref(), view.layer_ids())
341    //                     && view.filter_node(nodes.node(e.src()))
342    //                     && view.filter_node(nodes.node(e.dst()))
343    //             }))
344    //         }
345    //         FilterState::Nodes => {
346    //             let nodes = self.nodes();
347    //             FilterVariants::Nodes(iter.filter(move |e| {
348    //                 view.filter_node(nodes.node(e.src())) && view.filter_node(nodes.node(e.dst()))
349    //             }))
350    //         }
351    //         FilterState::Edges | FilterState::BothIndependent => FilterVariants::Edges(
352    //             iter.filter(|e| view.filter_edge(e.as_ref(), view.layer_ids())),
353    //         ),
354    //     };
355    //     filtered.map(|e| e.out_ref())
356    // }
357    //
358    // pub fn into_edges_iter<'graph, G: GraphViewOps<'graph>>(
359    //     self,
360    //     view: G,
361    // ) -> impl Iterator<Item = EdgeRef> + Send + 'graph {
362    //     match view.node_list() {
363    //         NodeList::List { elems } => {
364    //             return elems
365    //                 .into_iter()
366    //                 .flat_map(move |v| {
367    //                     self.clone()
368    //                         .into_node_edges_iter(v, Direction::OUT, view.clone())
369    //                 })
370    //                 .into_dyn_boxed()
371    //         }
372    //         _ => {}
373    //     }
374    //     let edges = self.owned_edges();
375    //     let nodes = self.owned_nodes();
376    //
377    //     match edges {
378    //         EdgesStorage::Mem(edges) => {
379    //             let iter = (0..edges.len()).map(EID);
380    //             let filtered = match view.filter_state() {
381    //                 FilterState::Neither => {
382    //                     FilterVariants::Neither(iter.map(move |eid| edges.get_mem(eid).out_ref()))
383    //                 }
384    //                 FilterState::Both => FilterVariants::Both(iter.filter_map(move |e| {
385    //                     let e = EdgeStorageRef::Mem(edges.get_mem(e));
386    //                     (view.filter_edge(e, view.layer_ids())
387    //                         && view.filter_node(nodes.node_entry(e.src()))
388    //                         && view.filter_node(nodes.node_entry(e.dst())))
389    //                     .then(|| e.out_ref())
390    //                 })),
391    //                 FilterState::Nodes => FilterVariants::Nodes(iter.filter_map(move |e| {
392    //                     let e = EdgeStorageRef::Mem(edges.get_mem(e));
393    //                     (view.filter_node(nodes.node_entry(e.src()))
394    //                         && view.filter_node(nodes.node_entry(e.dst())))
395    //                     .then(|| e.out_ref())
396    //                 })),
397    //                 FilterState::Edges | FilterState::BothIndependent => {
398    //                     FilterVariants::Edges(iter.filter_map(move |e| {
399    //                         let e = EdgeStorageRef::Mem(edges.get_mem(e));
400    //                         view.filter_edge(e, view.layer_ids()).then(|| e.out_ref())
401    //                     }))
402    //                 }
403    //             };
404    //             filtered.into_dyn_boxed()
405    //         }
406    //         #[cfg(feature = "storage")]
407    //         EdgesStorage::Disk(edges) => {
408    //             let edges_clone = edges.clone();
409    //             let iter = edges_clone.into_iter_refs(view.layer_ids().clone());
410    //             let filtered = match view.filter_state() {
411    //                 FilterState::Neither => FilterVariants::Neither(iter),
412    //                 FilterState::Both => FilterVariants::Both(iter.filter_map(move |e| {
413    //                     let edge = EdgeStorageRef::Disk(edges.get(e.pid()));
414    //                     if !view.filter_edge(edge, view.layer_ids()) {
415    //                         return None;
416    //                     }
417    //                     let src = nodes.node_entry(e.src());
418    //                     if !view.filter_node(src) {
419    //                         return None;
420    //                     }
421    //                     let dst = nodes.node_entry(e.dst());
422    //                     if !view.filter_node(dst) {
423    //                         return None;
424    //                     }
425    //                     Some(e)
426    //                 })),
427    //                 FilterState::Nodes => FilterVariants::Nodes(iter.filter_map(move |e| {
428    //                     let src = nodes.node_entry(e.src());
429    //                     if !view.filter_node(src) {
430    //                         return None;
431    //                     }
432    //                     let dst = nodes.node_entry(e.dst());
433    //                     if !view.filter_node(dst) {
434    //                         return None;
435    //                     }
436    //                     Some(e)
437    //                 })),
438    //                 FilterState::Edges | FilterState::BothIndependent => {
439    //                     FilterVariants::Edges(iter.filter_map(move |e| {
440    //                         let edge = EdgeStorageRef::Disk(edges.get(e.pid()));
441    //                         if !view.filter_edge(edge, view.layer_ids()) {
442    //                             return None;
443    //                         }
444    //                         Some(e)
445    //                     }))
446    //                 }
447    //             };
448    //             filtered.into_dyn_boxed()
449    //         }
450    //     }
451    // }
452    //
453    // pub fn edges_par<'graph, G: GraphViewOps<'graph>>(
454    //     &'graph self,
455    //     view: &'graph G,
456    // ) -> impl ParallelIterator<Item = EdgeRef> + 'graph {
457    //     self.edges()
458    //         .par_iter(view.layer_ids())
459    //         .filter(|edge| match view.filter_state() {
460    //             FilterState::Neither => true,
461    //             FilterState::Both => {
462    //                 let src = self.node_entry(edge.src());
463    //                 let dst = self.node_entry(edge.dst());
464    //                 view.filter_edge(edge.as_ref(), view.layer_ids())
465    //                     && view.filter_node(src.as_ref())
466    //                     && view.filter_node(dst.as_ref())
467    //             }
468    //             FilterState::Nodes => {
469    //                 let src = self.node_entry(edge.src());
470    //                 let dst = self.node_entry(edge.dst());
471    //                 view.filter_node(src.as_ref()) && view.filter_node(dst.as_ref())
472    //             }
473    //             FilterState::Edges | FilterState::BothIndependent => {
474    //                 view.filter_edge(edge.as_ref(), view.layer_ids())
475    //             }
476    //         })
477    //         .map(|e| e.out_ref())
478    // }
479    //
480    // pub fn into_edges_par<'graph, G: GraphViewOps<'graph>>(
481    //     self,
482    //     view: G,
483    // ) -> impl ParallelIterator<Item = EdgeRef> + 'graph {
484    //     let edges = self.owned_edges();
485    //     let nodes = self.owned_nodes();
486    //
487    //     match edges {
488    //         EdgesStorage::Mem(edges) => {
489    //             let iter = (0..edges.len()).into_par_iter().map(EID);
490    //             let filtered = match view.filter_state() {
491    //                 FilterState::Neither => FilterVariants::Neither(
492    //                     iter.map(move |eid| edges.get_mem(eid).as_edge_ref()),
493    //                 ),
494    //                 FilterState::Both => FilterVariants::Both(iter.filter_map(move |e| {
495    //                     let e = EdgeStorageRef::Mem(edges.get_mem(e));
496    //                     (view.filter_edge(e, view.layer_ids())
497    //                         && view.filter_node(nodes.node_entry(e.src()))
498    //                         && view.filter_node(nodes.node_entry(e.dst())))
499    //                     .then(|| e.out_ref())
500    //                 })),
501    //                 FilterState::Nodes => FilterVariants::Nodes(iter.filter_map(move |e| {
502    //                     let e = EdgeStorageRef::Mem(edges.get_mem(e));
503    //                     (view.filter_node(nodes.node_entry(e.src()))
504    //                         && view.filter_node(nodes.node_entry(e.dst())))
505    //                     .then(|| e.out_ref())
506    //                 })),
507    //                 FilterState::Edges | FilterState::BothIndependent => {
508    //                     FilterVariants::Edges(iter.filter_map(move |e| {
509    //                         let e = EdgeStorageRef::Mem(edges.get_mem(e));
510    //                         view.filter_edge(e, view.layer_ids()).then(|| e.out_ref())
511    //                     }))
512    //                 }
513    //             };
514    //             #[cfg(feature = "storage")]
515    //             {
516    //                 StorageVariants::Mem(filtered)
517    //             }
518    //             #[cfg(not(feature = "storage"))]
519    //             {
520    //                 filtered
521    //             }
522    //         }
523    //         #[cfg(feature = "storage")]
524    //         EdgesStorage::Disk(edges) => {
525    //             let edges_clone = edges.clone();
526    //             let iter = edges_clone.into_par_iter_refs(view.layer_ids().clone());
527    //             let filtered = match view.filter_state() {
528    //                 FilterState::Neither => FilterVariants::Neither(
529    //                     iter.map(move |eid| EdgeStorageRef::Disk(edges.get(eid)).out_ref()),
530    //                 ),
531    //                 FilterState::Both => FilterVariants::Both(iter.filter_map(move |eid| {
532    //                     let e = EdgeStorageRef::Disk(edges.get(eid));
533    //                     if !view.filter_edge(e, view.layer_ids()) {
534    //                         return None;
535    //                     }
536    //                     let src = nodes.node_entry(e.src());
537    //                     if !view.filter_node(src) {
538    //                         return None;
539    //                     }
540    //                     let dst = nodes.node_entry(e.dst());
541    //                     if !view.filter_node(dst) {
542    //                         return None;
543    //                     }
544    //                     Some(e.out_ref())
545    //                 })),
546    //                 FilterState::Nodes => FilterVariants::Nodes(iter.filter_map(move |eid| {
547    //                     let e = EdgeStorageRef::Disk(edges.get(eid));
548    //                     let src = nodes.node_entry(e.src());
549    //                     if !view.filter_node(src) {
550    //                         return None;
551    //                     }
552    //                     let dst = nodes.node_entry(e.dst());
553    //                     if !view.filter_node(dst) {
554    //                         return None;
555    //                     }
556    //                     Some(e.out_ref())
557    //                 })),
558    //                 FilterState::Edges | FilterState::BothIndependent => {
559    //                     FilterVariants::Edges(iter.filter_map(move |eid| {
560    //                         let e = EdgeStorageRef::Disk(edges.get(eid));
561    //                         if !view.filter_edge(e, view.layer_ids()) {
562    //                             return None;
563    //                         }
564    //                         Some(e.out_ref())
565    //                     }))
566    //                 }
567    //             };
568    //             StorageVariants::Disk(filtered)
569    //         }
570    //     }
571    // }
572    //
573    // pub fn node_neighbours_iter<'a, 'graph: 'a, G: GraphViewOps<'graph>>(
574    //     &'a self,
575    //     node: VID,
576    //     dir: Direction,
577    //     view: &'a G,
578    // ) -> impl Iterator<Item = VID> + Send + 'a {
579    //     self.node_edges_iter(node, dir, view)
580    //         .map(|e| e.remote())
581    //         .dedup()
582    // }
583    //
584    // pub fn into_node_neighbours_iter<'graph, G: GraphViewOps<'graph>>(
585    //     self,
586    //     node: VID,
587    //     dir: Direction,
588    //     view: G,
589    // ) -> impl Iterator<Item = VID> + 'graph {
590    //     self.into_node_edges_iter(node, dir, view)
591    //         .map(|e| e.remote())
592    //         .dedup()
593    // }
594    //
595    // #[inline]
596    // pub fn node_degree<'graph, G: GraphViewOps<'graph>>(
597    //     &self,
598    //     node: VID,
599    //     dir: Direction,
600    //     view: &G,
601    // ) -> usize {
602    //     if matches!(view.filter_state(), FilterState::Neither) {
603    //         self.node_entry(node).degree(view.layer_ids(), dir)
604    //     } else {
605    //         self.node_neighbours_iter(node, dir, view).count()
606    //     }
607    // }
608    //
609    // pub fn node_edges_iter<'a, 'graph: 'a, G: GraphViewOps<'graph>>(
610    //     &'a self,
611    //     node: VID,
612    //     dir: Direction,
613    //     view: &'a G,
614    // ) -> impl Iterator<Item = EdgeRef> + 'a {
615    //     let source = self.node_entry(node);
616    //     let layers = view.layer_ids();
617    //     let iter = source.into_edges_iter(layers, dir);
618    //     match view.filter_state() {
619    //         FilterState::Neither => FilterVariants::Neither(iter),
620    //         FilterState::Both => FilterVariants::Both(iter.filter(|&e| {
621    //             view.filter_edge(self.edge_entry(e.pid()).as_ref(), view.layer_ids())
622    //                 && view.filter_node(self.node_entry(e.remote()).as_ref())
623    //         })),
624    //         FilterState::Nodes => FilterVariants::Nodes(
625    //             iter.filter(|e| view.filter_node(self.node_entry(e.remote()).as_ref())),
626    //         ),
627    //         FilterState::Edges | FilterState::BothIndependent => {
628    //             FilterVariants::Edges(iter.filter(|&e| {
629    //                 view.filter_edge(self.edge_entry(e.pid()).as_ref(), view.layer_ids())
630    //             }))
631    //         }
632    //     }
633    // }
634    //
635    // pub fn into_node_edges_iter<'graph, G: GraphViewOps<'graph>>(
636    //     self,
637    //     node: VID,
638    //     dir: Direction,
639    //     view: G,
640    // ) -> impl Iterator<Item = EdgeRef> + 'graph {
641    //     let layers = view.layer_ids().clone();
642    //     let local = self.owned_node(node);
643    //     let iter = local.into_edges_iter(layers, dir);
644    //
645    //     match view.filter_state() {
646    //         FilterState::Neither => FilterVariants::Neither(iter),
647    //         FilterState::Both => FilterVariants::Both(iter.filter(move |&e| {
648    //             view.filter_edge(self.edge_entry(e.pid()).as_ref(), view.layer_ids())
649    //                 && view.filter_node(self.node_entry(e.remote()).as_ref())
650    //         })),
651    //         FilterState::Nodes => FilterVariants::Nodes(
652    //             iter.filter(move |e| view.filter_node(self.node_entry(e.remote()).as_ref())),
653    //         ),
654    //         FilterState::Edges | FilterState::BothIndependent => {
655    //             FilterVariants::Edges(iter.filter(move |&e| {
656    //                 view.filter_edge(self.edge_entry(e.pid()).as_ref(), view.layer_ids())
657    //             }))
658    //         }
659    //     }
660    // }
661
662    pub fn node_meta(&self) -> &Meta {
663        match self {
664            GraphStorage::Mem(storage) => &storage.graph.node_meta,
665            GraphStorage::Unlocked(storage) => &storage.node_meta,
666            #[cfg(feature = "storage")]
667            GraphStorage::Disk(storage) => storage.node_meta(),
668        }
669    }
670
671    pub fn edge_meta(&self) -> &Meta {
672        match self {
673            GraphStorage::Mem(storage) => &storage.graph.edge_meta,
674            GraphStorage::Unlocked(storage) => &storage.edge_meta,
675            #[cfg(feature = "storage")]
676            GraphStorage::Disk(storage) => storage.edge_meta(),
677        }
678    }
679
680    pub fn graph_meta(&self) -> &GraphMeta {
681        match self {
682            GraphStorage::Mem(storage) => &storage.graph.graph_meta,
683            GraphStorage::Unlocked(storage) => &storage.graph_meta,
684            #[cfg(feature = "storage")]
685            GraphStorage::Disk(storage) => storage.graph_meta(),
686        }
687    }
688}