raphtory_api/core/entities/
mod.rs

1use super::input::input_node::parse_u64_strict;
2use bytemuck::{Pod, Zeroable};
3use edges::edge_ref::EdgeRef;
4use num_traits::ToPrimitive;
5use rayon::prelude::*;
6use serde::{Deserialize, Serialize};
7use std::{
8    borrow::Cow,
9    fmt::{Display, Formatter},
10    sync::Arc,
11};
12
13pub mod edges;
14pub mod properties;
15
16// The only reason this is public is because the physical IDs of the nodes don’t move.
17#[repr(transparent)]
18#[derive(
19    Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Deserialize, Serialize, Pod, Zeroable,
20)]
21pub struct VID(pub usize);
22
23impl Default for VID {
24    fn default() -> Self {
25        VID(usize::MAX)
26    }
27}
28
29impl VID {
30    pub fn index(&self) -> usize {
31        self.0
32    }
33
34    pub fn as_u64(&self) -> u64 {
35        self.0 as u64
36    }
37}
38
39impl From<usize> for VID {
40    fn from(id: usize) -> Self {
41        VID(id)
42    }
43}
44
45impl From<VID> for usize {
46    fn from(id: VID) -> Self {
47        id.0
48    }
49}
50
51#[repr(transparent)]
52#[derive(
53    Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Deserialize, Serialize, Pod, Zeroable,
54)]
55pub struct EID(pub usize);
56
57impl Default for EID {
58    fn default() -> Self {
59        EID(usize::MAX)
60    }
61}
62
63impl EID {
64    pub fn as_u64(self) -> u64 {
65        self.0 as u64
66    }
67}
68
69impl From<EID> for usize {
70    fn from(id: EID) -> Self {
71        id.0
72    }
73}
74
75impl From<usize> for EID {
76    fn from(id: usize) -> Self {
77        EID(id)
78    }
79}
80
81impl EID {
82    pub fn from_u64(id: u64) -> Self {
83        EID(id as usize)
84    }
85}
86
87#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
88pub enum GID {
89    U64(u64),
90    Str(String),
91}
92impl PartialEq<str> for GID {
93    fn eq(&self, other: &str) -> bool {
94        match self {
95            GID::U64(_) => false,
96            GID::Str(id) => id == other,
97        }
98    }
99}
100
101impl PartialEq<String> for GID {
102    fn eq(&self, other: &String) -> bool {
103        match self {
104            GID::U64(_) => false,
105            GID::Str(id) => id == other,
106        }
107    }
108}
109
110impl PartialEq<u64> for GID {
111    fn eq(&self, other: &u64) -> bool {
112        match self {
113            GID::Str(_) => false,
114            GID::U64(id) => id == other,
115        }
116    }
117}
118
119impl Default for GID {
120    fn default() -> Self {
121        GID::U64(u64::MAX)
122    }
123}
124
125impl Display for GID {
126    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
127        match self {
128            GID::U64(v) => write!(f, "{}", v),
129            GID::Str(v) => write!(f, "{}", v),
130        }
131    }
132}
133
134impl GID {
135    pub fn dtype(&self) -> GidType {
136        match self {
137            GID::U64(_) => GidType::U64,
138            GID::Str(_) => GidType::Str,
139        }
140    }
141    pub fn into_str(self) -> Option<String> {
142        match self {
143            GID::Str(v) => Some(v),
144            _ => None,
145        }
146    }
147
148    pub fn into_u64(self) -> Option<u64> {
149        match self {
150            GID::U64(v) => Some(v),
151            _ => None,
152        }
153    }
154
155    pub fn as_str(&self) -> Option<&str> {
156        match self {
157            GID::Str(v) => Some(v.as_str()),
158            _ => None,
159        }
160    }
161
162    pub fn as_u64(&self) -> Option<u64> {
163        match self {
164            GID::U64(v) => Some(*v),
165            _ => None,
166        }
167    }
168
169    pub fn to_str(&self) -> Cow<str> {
170        match self {
171            GID::U64(v) => Cow::Owned(v.to_string()),
172            GID::Str(v) => Cow::Borrowed(v),
173        }
174    }
175
176    pub fn to_i64(&self) -> Option<i64> {
177        match self {
178            GID::U64(v) => v.to_i64(),
179            GID::Str(v) => parse_u64_strict(v)?.to_i64(),
180        }
181    }
182
183    pub fn to_u64(&self) -> Option<u64> {
184        match self {
185            GID::U64(v) => Some(*v),
186            GID::Str(v) => parse_u64_strict(v),
187        }
188    }
189
190    pub fn as_ref(&self) -> GidRef {
191        match self {
192            GID::U64(v) => GidRef::U64(*v),
193            GID::Str(v) => GidRef::Str(v),
194        }
195    }
196}
197
198impl From<u64> for GID {
199    fn from(id: u64) -> Self {
200        Self::U64(id)
201    }
202}
203
204impl From<String> for GID {
205    fn from(id: String) -> Self {
206        Self::Str(id)
207    }
208}
209
210impl From<&str> for GID {
211    fn from(id: &str) -> Self {
212        Self::Str(id.to_string())
213    }
214}
215
216impl<'a> From<GidRef<'a>> for GID {
217    fn from(value: GidRef<'a>) -> Self {
218        match value {
219            GidRef::U64(v) => GID::U64(v),
220            GidRef::Str(v) => GID::Str(v.to_owned()),
221        }
222    }
223}
224
225#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
226pub enum GidRef<'a> {
227    U64(u64),
228    Str(&'a str),
229}
230
231#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
232pub enum GidType {
233    U64,
234    Str,
235}
236
237impl Display for GidType {
238    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
239        match self {
240            GidType::U64 => {
241                write!(f, "Numeric")
242            }
243            GidType::Str => {
244                write!(f, "String")
245            }
246        }
247    }
248}
249
250impl Display for GidRef<'_> {
251    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
252        match self {
253            GidRef::U64(v) => write!(f, "{}", v),
254            GidRef::Str(v) => write!(f, "{}", v),
255        }
256    }
257}
258
259impl<'a> From<&'a GID> for GidRef<'a> {
260    fn from(value: &'a GID) -> Self {
261        match value {
262            GID::U64(v) => GidRef::U64(*v),
263            GID::Str(v) => GidRef::Str(v),
264        }
265    }
266}
267
268impl<'a> From<&'a str> for GidRef<'a> {
269    fn from(value: &'a str) -> Self {
270        GidRef::Str(value)
271    }
272}
273
274impl<'a> GidRef<'a> {
275    pub fn dtype(self) -> GidType {
276        match self {
277            GidRef::U64(_) => GidType::U64,
278            GidRef::Str(_) => GidType::Str,
279        }
280    }
281    pub fn as_str(self) -> Option<&'a str> {
282        match self {
283            GidRef::Str(s) => Some(s),
284            _ => None,
285        }
286    }
287
288    pub fn as_u64(self) -> Option<u64> {
289        match self {
290            GidRef::U64(v) => Some(v),
291            _ => None,
292        }
293    }
294
295    pub fn to_owned(self) -> GID {
296        match self {
297            GidRef::U64(v) => GID::U64(v),
298            GidRef::Str(v) => GID::Str(v.to_owned()),
299        }
300    }
301
302    pub fn to_str(self) -> Cow<'a, str> {
303        match self {
304            GidRef::U64(v) => Cow::Owned(v.to_string()),
305            GidRef::Str(v) => Cow::Borrowed(v),
306        }
307    }
308
309    pub fn to_i64(self) -> Option<i64> {
310        match self {
311            GidRef::U64(v) => v.to_i64(),
312            GidRef::Str(v) => parse_u64_strict(v)?.to_i64(),
313        }
314    }
315
316    pub fn to_u64(self) -> Option<u64> {
317        match self {
318            GidRef::U64(v) => Some(v),
319            GidRef::Str(v) => parse_u64_strict(v),
320        }
321    }
322}
323
324#[derive(Clone, Debug)]
325pub enum LayerIds {
326    None,
327    All,
328    One(usize),
329    Multiple(Multiple),
330}
331
332#[derive(Clone, Debug, Default)]
333pub struct Multiple(pub Arc<[usize]>);
334
335impl Multiple {
336    #[inline]
337    pub fn binary_search(&self, pos: &usize) -> Option<usize> {
338        self.0.binary_search(pos).ok()
339    }
340
341    #[inline]
342    pub fn into_iter(&self) -> impl Iterator<Item = usize> {
343        let ids = self.0.clone();
344        (0..ids.len()).map(move |i| ids[i])
345    }
346
347    #[inline]
348    pub fn iter(&self) -> impl Iterator<Item = usize> + '_ {
349        self.0.iter().copied()
350    }
351
352    #[inline]
353    pub fn find(&self, id: usize) -> Option<usize> {
354        self.0.get(id).copied()
355    }
356
357    #[inline]
358    pub fn par_iter(&self) -> impl rayon::iter::ParallelIterator<Item = usize> {
359        let bit_vec = self.0.clone();
360        (0..bit_vec.len()).into_par_iter().map(move |i| bit_vec[i])
361    }
362
363    #[inline]
364    pub fn len(&self) -> usize {
365        self.0.len()
366    }
367}
368
369impl FromIterator<usize> for Multiple {
370    fn from_iter<I: IntoIterator<Item = usize>>(iter: I) -> Self {
371        Multiple(iter.into_iter().collect())
372    }
373}
374
375impl From<Vec<usize>> for Multiple {
376    fn from(v: Vec<usize>) -> Self {
377        v.into_iter().collect()
378    }
379}
380
381#[cfg(test)]
382mod test {
383    use crate::core::entities::Multiple;
384
385    #[test]
386    fn empty_bit_multiple() {
387        let bm = super::Multiple::default();
388        let actual = bm.into_iter().collect::<Vec<_>>();
389        let expected: Vec<usize> = vec![];
390        assert_eq!(actual, expected);
391    }
392
393    #[test]
394    fn set_one() {
395        let bm: Multiple = [1].into_iter().collect();
396        let actual = bm.into_iter().collect::<Vec<_>>();
397        assert_eq!(actual, vec![1usize]);
398    }
399
400    #[test]
401    fn set_two() {
402        let bm: Multiple = [1, 67].into_iter().collect();
403
404        let actual = bm.into_iter().collect::<Vec<_>>();
405        assert_eq!(actual, vec![1usize, 67]);
406    }
407}
408
409impl LayerIds {
410    pub fn find(&self, layer_id: usize) -> Option<usize> {
411        match self {
412            LayerIds::All => Some(layer_id),
413            LayerIds::One(id) => {
414                if *id == layer_id {
415                    Some(layer_id)
416                } else {
417                    None
418                }
419            }
420            LayerIds::Multiple(ids) => ids.binary_search(&layer_id).map(|_| layer_id),
421            LayerIds::None => None,
422        }
423    }
424
425    pub fn intersect(&self, other: &LayerIds) -> LayerIds {
426        match (self, other) {
427            (LayerIds::None, _) => LayerIds::None,
428            (_, LayerIds::None) => LayerIds::None,
429            (LayerIds::All, other) => other.clone(),
430            (this, LayerIds::All) => this.clone(),
431            (LayerIds::One(id), other) => {
432                if other.contains(id) {
433                    LayerIds::One(*id)
434                } else {
435                    LayerIds::None
436                }
437            }
438            (LayerIds::Multiple(ids), other) => {
439                let ids: Vec<usize> = ids.iter().filter(|id| other.contains(id)).collect();
440                match ids.len() {
441                    0 => LayerIds::None,
442                    1 => LayerIds::One(ids[0]),
443                    _ => LayerIds::Multiple(ids.into()),
444                }
445            }
446        }
447    }
448
449    pub fn constrain_from_edge(&self, e: EdgeRef) -> Cow<LayerIds> {
450        match e.layer() {
451            None => Cow::Borrowed(self),
452            Some(l) => self
453                .find(l)
454                .map(|id| Cow::Owned(LayerIds::One(id)))
455                .unwrap_or(Cow::Owned(LayerIds::None)),
456        }
457    }
458
459    pub fn contains(&self, layer_id: &usize) -> bool {
460        self.find(*layer_id).is_some()
461    }
462
463    pub fn is_none(&self) -> bool {
464        matches!(self, LayerIds::None)
465    }
466}
467
468impl From<Vec<usize>> for LayerIds {
469    fn from(mut v: Vec<usize>) -> Self {
470        match v.len() {
471            0 => LayerIds::All,
472            1 => LayerIds::One(v[0]),
473            _ => {
474                v.sort_unstable();
475                v.dedup();
476                LayerIds::Multiple(v.into())
477            }
478        }
479    }
480}
481
482impl<const N: usize> From<[usize; N]> for LayerIds {
483    fn from(v: [usize; N]) -> Self {
484        match v.len() {
485            0 => LayerIds::All,
486            1 => LayerIds::One(v[0]),
487            _ => {
488                let mut v = v.to_vec();
489                v.sort_unstable();
490                v.dedup();
491                LayerIds::Multiple(v.into())
492            }
493        }
494    }
495}
496
497impl From<usize> for LayerIds {
498    fn from(id: usize) -> Self {
499        LayerIds::One(id)
500    }
501}