1use super::input::input_node::parse_u64_strict;
2use crate::iter::IntoDynBoxed;
3use bytemuck::{Pod, Zeroable};
4use itertools::Itertools;
5use num_traits::ToPrimitive;
6use serde::{Deserialize, Serialize};
7use std::{
8 borrow::Cow,
9 fmt::{Debug, Display, Formatter},
10 iter,
11};
12
13pub mod edges;
14pub mod layers;
15pub mod properties;
16
17use crate::core::entities::properties::prop::PropType;
18pub use layers::*;
19
20#[repr(transparent)]
22#[derive(
23 Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Deserialize, Serialize, Pod, Zeroable,
24)]
25pub struct VID(pub usize);
26
27impl Default for VID {
28 fn default() -> Self {
29 VID(usize::MAX)
30 }
31}
32
33impl VID {
34 pub fn index(&self) -> usize {
35 self.0
36 }
37
38 pub fn as_u64(&self) -> u64 {
39 self.0 as u64
40 }
41
42 #[inline]
44 pub fn is_initialised(&self) -> bool {
45 self.0 != usize::MAX
46 }
47
48 #[inline]
49 pub fn or_init(self, init: impl FnOnce() -> VID) -> Self {
51 if self.is_initialised() {
52 self
53 } else {
54 init()
55 }
56 }
57
58 #[inline]
59 pub fn or_maybe_init(self, init: impl FnOnce() -> Option<VID>) -> Option<Self> {
61 if self.is_initialised() {
62 Some(self)
63 } else {
64 init()
65 }
66 }
67
68 #[inline]
69 pub fn into_option(self) -> Option<Self> {
71 self.is_initialised().then_some(self)
72 }
73}
74
75impl From<usize> for VID {
76 fn from(id: usize) -> Self {
77 VID(id)
78 }
79}
80
81impl From<VID> for usize {
82 fn from(id: VID) -> Self {
83 id.0
84 }
85}
86
87#[repr(transparent)]
88#[derive(
89 Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Deserialize, Serialize, Pod, Zeroable,
90)]
91pub struct EID(pub usize);
92
93impl Default for EID {
94 fn default() -> Self {
95 EID(usize::MAX)
96 }
97}
98
99impl EID {
100 pub fn index(&self) -> usize {
101 self.0
102 }
103
104 pub fn as_u64(self) -> u64 {
105 self.0 as u64
106 }
107
108 pub fn with_layer(self, layer: LayerId) -> ELID {
109 ELID::new(self, layer)
110 }
111
112 pub fn with_layer_deletion(self, layer: LayerId) -> ELID {
113 ELID::new_deletion(self, layer)
114 }
115}
116
117impl From<EID> for usize {
118 fn from(id: EID) -> Self {
119 id.0
120 }
121}
122
123impl From<usize> for EID {
124 fn from(id: usize) -> Self {
125 EID(id)
126 }
127}
128
129impl EID {
130 pub fn from_u64(id: u64) -> Self {
131 EID(id as usize)
132 }
133}
134
135impl From<ELID> for EID {
136 fn from(elid: ELID) -> Self {
137 elid.eid()
138 }
139}
140
141#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
142pub struct ELID {
143 edge_and_deletion: EDID,
144 layer: LayerId,
145}
146
147#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)]
149pub struct EDID(pub usize);
150
151impl Debug for EDID {
152 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
153 f.debug_struct("EDID")
154 .field("edge", &self.eid())
155 .field("deletion", &self.is_deletion())
156 .finish()
157 }
158}
159
160impl EDID {
161 pub fn new(edge: EID) -> Self {
162 EDID(edge.0)
163 }
164
165 pub fn new_deletion(edge: EID) -> Self {
166 EDID(edge.0 | DELETION_FLAG)
167 }
168
169 pub fn eid(&self) -> EID {
170 EID(self.0 & !DELETION_FLAG)
171 }
172
173 pub fn is_deletion(&self) -> bool {
174 self.0 & DELETION_FLAG != 0
175 }
176
177 pub fn into_deletion(mut self) -> Self {
178 self.0 = self.0 | DELETION_FLAG;
179 self
180 }
181}
182
183impl Debug for ELID {
184 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
185 f.debug_struct("ELID")
186 .field("edge", &self.edge_and_deletion)
187 .field("layer", &self.layer())
188 .field("deletion", &self.is_deletion())
189 .finish()
190 }
191}
192
193const DELETION_FLAG: usize = 1usize.reverse_bits();
194pub const MAX_EID: usize = usize::MAX & !DELETION_FLAG;
195
196impl ELID {
197 pub fn new(edge: EID, layer: LayerId) -> Self {
198 ELID {
199 edge_and_deletion: EDID::new(edge),
200 layer,
201 }
202 }
203
204 pub fn new_flagged(edge_and_deletion: EDID, layer: LayerId) -> Self {
205 ELID {
206 edge_and_deletion,
207 layer,
208 }
209 }
210
211 pub fn new_deletion(edge: EID, layer: LayerId) -> Self {
212 ELID {
213 edge_and_deletion: EDID::new_deletion(edge),
214 layer,
215 }
216 }
217
218 pub fn layer(&self) -> LayerId {
219 self.layer
220 }
221
222 pub fn eid(&self) -> EID {
223 self.edge_and_deletion.eid()
224 }
225
226 pub fn eid_and_flag(&self) -> EDID {
227 self.edge_and_deletion
228 }
229
230 pub fn is_deletion(&self) -> bool {
231 self.edge_and_deletion.is_deletion()
232 }
233
234 pub fn into_deletion(mut self) -> Self {
235 self.edge_and_deletion = self.edge_and_deletion.into_deletion();
236 self
237 }
238}
239
240#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
241pub enum GID {
242 U64(u64),
243 Str(String),
244}
245
246impl PartialEq<str> for GID {
247 fn eq(&self, other: &str) -> bool {
248 match self {
249 GID::U64(_) => false,
250 GID::Str(id) => id == other,
251 }
252 }
253}
254
255impl PartialEq<String> for GID {
256 fn eq(&self, other: &String) -> bool {
257 match self {
258 GID::U64(_) => false,
259 GID::Str(id) => id == other,
260 }
261 }
262}
263
264impl PartialEq<u64> for GID {
265 fn eq(&self, other: &u64) -> bool {
266 match self {
267 GID::Str(_) => false,
268 GID::U64(id) => id == other,
269 }
270 }
271}
272
273impl Default for GID {
274 fn default() -> Self {
275 GID::U64(u64::MAX)
276 }
277}
278
279impl Display for GID {
280 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
281 match self {
282 GID::U64(v) => write!(f, "{}", v),
283 GID::Str(v) => write!(f, "{}", v),
284 }
285 }
286}
287
288impl GID {
289 pub fn dtype(&self) -> GidType {
290 match self {
291 GID::U64(_) => GidType::U64,
292 GID::Str(_) => GidType::Str,
293 }
294 }
295 pub fn into_str(self) -> Option<String> {
296 match self {
297 GID::Str(v) => Some(v),
298 _ => None,
299 }
300 }
301
302 pub fn into_u64(self) -> Option<u64> {
303 match self {
304 GID::U64(v) => Some(v),
305 _ => None,
306 }
307 }
308
309 pub fn as_str(&self) -> Option<&str> {
310 match self {
311 GID::Str(v) => Some(v.as_str()),
312 _ => None,
313 }
314 }
315
316 pub fn as_u64(&self) -> Option<u64> {
317 match self {
318 GID::U64(v) => Some(*v),
319 _ => None,
320 }
321 }
322
323 pub fn to_str(&self) -> Cow<'_, str> {
324 match self {
325 GID::U64(v) => Cow::Owned(v.to_string()),
326 GID::Str(v) => Cow::Borrowed(v),
327 }
328 }
329
330 pub fn to_i64(&self) -> Option<i64> {
331 match self {
332 GID::U64(v) => v.to_i64(),
333 GID::Str(v) => parse_u64_strict(v)?.to_i64(),
334 }
335 }
336
337 pub fn to_u64(&self) -> Option<u64> {
338 match self {
339 GID::U64(v) => Some(*v),
340 GID::Str(v) => parse_u64_strict(v),
341 }
342 }
343
344 pub fn as_ref(&self) -> GidRef<'_> {
345 match self {
346 GID::U64(v) => GidRef::U64(*v),
347 GID::Str(v) => GidRef::Str(v),
348 }
349 }
350}
351
352impl From<u64> for GID {
353 fn from(id: u64) -> Self {
354 Self::U64(id)
355 }
356}
357
358impl From<&u64> for GID {
359 fn from(value: &u64) -> Self {
360 GID::U64(*value)
361 }
362}
363
364impl From<String> for GID {
365 fn from(id: String) -> Self {
366 Self::Str(id)
367 }
368}
369
370impl From<&str> for GID {
371 fn from(id: &str) -> Self {
372 Self::Str(id.to_string())
373 }
374}
375
376impl<'a> From<GidRef<'a>> for GID {
377 fn from(value: GidRef<'a>) -> Self {
378 match value {
379 GidRef::U64(v) => GID::U64(v),
380 GidRef::Str(v) => GID::Str(v.to_owned()),
381 }
382 }
383}
384
385#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
386pub enum GidRef<'a> {
387 U64(u64),
388 Str(&'a str),
389}
390
391#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
392pub enum GidCow<'a> {
393 U64(u64),
394 Str(Cow<'a, str>),
395}
396
397impl<'a> From<GidRef<'a>> for GidCow<'a> {
398 fn from(value: GidRef<'a>) -> Self {
399 match value {
400 GidRef::U64(v) => Self::U64(v),
401 GidRef::Str(v) => Self::Str(Cow::Borrowed(v)),
402 }
403 }
404}
405
406impl<'a> GidCow<'a> {
407 pub fn as_ref<'b>(&'b self) -> GidRef<'b>
408 where
409 'a: 'b,
410 {
411 match self {
412 GidCow::U64(v) => GidRef::U64(*v),
413 GidCow::Str(v) => GidRef::Str(v),
414 }
415 }
416
417 pub fn into_owned(self) -> GID {
418 match self {
419 GidCow::U64(v) => GID::U64(v),
420 GidCow::Str(v) => GID::Str(v.into_owned()),
421 }
422 }
423}
424
425#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
426pub enum GidType {
427 U64,
428 Str,
429}
430
431impl Display for GidType {
432 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
433 match self {
434 GidType::U64 => {
435 write!(f, "Numeric")
436 }
437 GidType::Str => {
438 write!(f, "String")
439 }
440 }
441 }
442}
443
444impl GidType {
445 pub fn from_prop_type(prop_type: &PropType) -> Option<Self> {
446 match prop_type {
447 PropType::Str => Some(GidType::Str),
448 PropType::U64 | PropType::U32 | PropType::I64 | PropType::I32 => Some(GidType::U64),
449 _ => None,
450 }
451 }
452}
453
454impl Display for GidRef<'_> {
455 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
456 match self {
457 GidRef::U64(v) => write!(f, "{v}"),
458 GidRef::Str(v) => write!(f, "{v}"),
459 }
460 }
461}
462
463impl<'a> From<&'a GID> for GidRef<'a> {
464 fn from(value: &'a GID) -> Self {
465 match value {
466 GID::U64(v) => GidRef::U64(*v),
467 GID::Str(v) => GidRef::Str(v),
468 }
469 }
470}
471
472impl<'a> From<&'a str> for GidRef<'a> {
473 fn from(value: &'a str) -> Self {
474 GidRef::Str(value)
475 }
476}
477
478impl From<u64> for GidRef<'_> {
479 fn from(value: u64) -> Self {
480 GidRef::U64(value)
481 }
482}
483
484impl<'a> GidRef<'a> {
485 pub fn dtype(self) -> GidType {
486 match self {
487 GidRef::U64(_) => GidType::U64,
488 GidRef::Str(_) => GidType::Str,
489 }
490 }
491 pub fn as_str(self) -> Option<&'a str> {
492 match self {
493 GidRef::Str(s) => Some(s),
494 _ => None,
495 }
496 }
497
498 pub fn as_u64(self) -> Option<u64> {
499 match self {
500 GidRef::U64(v) => Some(v),
501 _ => None,
502 }
503 }
504
505 pub fn to_owned(self) -> GID {
506 match self {
507 GidRef::U64(v) => GID::U64(v),
508 GidRef::Str(v) => GID::Str(v.to_owned()),
509 }
510 }
511
512 pub fn to_str(self) -> Cow<'a, str> {
513 match self {
514 GidRef::U64(v) => Cow::Owned(v.to_string()),
515 GidRef::Str(v) => Cow::Borrowed(v),
516 }
517 }
518
519 pub fn to_i64(self) -> Option<i64> {
520 match self {
521 GidRef::U64(v) => v.to_i64(),
522 GidRef::Str(v) => parse_u64_strict(v)?.to_i64(),
523 }
524 }
525
526 pub fn to_u64(self) -> Option<u64> {
527 match self {
528 GidRef::U64(v) => Some(v),
529 GidRef::Str(v) => parse_u64_strict(v),
530 }
531 }
532}
533
534#[cfg(test)]
535mod test {
536 use crate::core::entities::{LayerId, Multiple};
537
538 #[test]
539 fn empty_bit_multiple() {
540 let bm = super::Multiple::default();
541 let actual = bm.into_iter().collect::<Vec<_>>();
542 let expected: Vec<LayerId> = vec![];
543 assert_eq!(actual, expected);
544 }
545
546 #[test]
547 fn set_one() {
548 let bm: Multiple = [1].into_iter().collect();
549 let actual = bm.into_iter().collect::<Vec<_>>();
550 assert_eq!(actual, vec![1usize]);
551 }
552
553 #[test]
554 fn set_two() {
555 let bm: Multiple = [1, 67].into_iter().collect();
556
557 let actual = bm.into_iter().collect::<Vec<_>>();
558 assert_eq!(actual, vec![1usize, 67]);
559 }
560}
561
562impl LayerIds {
563 pub fn intersect(&self, other: &LayerIds) -> LayerIds {
564 match (self, other) {
565 (LayerIds::None, _) => LayerIds::None,
566 (_, LayerIds::None) => LayerIds::None,
567 (LayerIds::All, other) => other.clone(),
568 (this, LayerIds::All) => this.clone(),
569 (LayerIds::One(id), other) => {
570 if other.contains(id) {
571 LayerIds::One(*id)
572 } else {
573 LayerIds::None
574 }
575 }
576 (LayerIds::Multiple(ids), other) => {
577 let ids: Vec<_> = ids.iter().filter(|id| other.contains(id)).collect();
578 match ids.len() {
579 0 => LayerIds::None,
580 1 => LayerIds::One(ids[0]),
581 _ => LayerIds::Multiple(ids.into()),
582 }
583 }
584 }
585 }
586
587 pub fn union(&self, other: &LayerIds) -> LayerIds {
588 match (self, other) {
589 (LayerIds::All, _) | (_, LayerIds::All) => LayerIds::All,
590 (LayerIds::None, o) | (o, LayerIds::None) => o.clone(),
591 (LayerIds::One(id), LayerIds::One(other_id)) => {
592 if id == other_id {
593 LayerIds::One(*id)
594 } else {
595 LayerIds::Multiple([*id.min(other_id), *id.max(other_id)].into_iter().collect())
596 }
597 }
598 (LayerIds::Multiple(ids), LayerIds::Multiple(other_ids)) => {
599 LayerIds::Multiple(ids.iter().merge(other_ids.iter()).dedup().collect())
600 }
601 (LayerIds::One(id), LayerIds::Multiple(ids))
602 | (LayerIds::Multiple(ids), LayerIds::One(id)) => {
603 if ids.contains(*id) {
604 LayerIds::Multiple(ids.clone())
605 } else {
606 LayerIds::Multiple(ids.iter().merge(iter::once(*id)).collect())
607 }
608 }
609 }
610 }
611
612 pub fn contains(&self, layer_id: &LayerId) -> bool {
613 match self {
614 LayerIds::All => true,
615 LayerIds::One(id) => id == layer_id,
616 LayerIds::Multiple(ids) => ids.contains(*layer_id),
617 LayerIds::None => false,
618 }
619 }
620
621 pub fn is_none(&self) -> bool {
622 matches!(self, LayerIds::None)
623 }
624
625 pub fn is_single(&self) -> bool {
626 matches!(self, LayerIds::One(_))
627 }
628
629 pub fn is_all(&self) -> bool {
630 matches!(self, LayerIds::All)
631 }
632
633 pub fn iter(&self, num_layers: usize) -> impl Iterator<Item = LayerId> + use<'_> {
634 match self {
635 LayerIds::None => iter::empty().into_dyn_boxed(),
636 LayerIds::All => (0..num_layers).map(LayerId).into_dyn_boxed(),
637 LayerIds::One(id) => iter::once(*id).into_dyn_boxed(),
638 LayerIds::Multiple(ids) => ids.into_iter().into_dyn_boxed(),
639 }
640 }
641
642 pub fn into_iter(self, num_layers: usize) -> impl Iterator<Item = LayerId> {
643 match self {
644 LayerIds::None => iter::empty().into_dyn_boxed(),
645 LayerIds::All => (0..num_layers).map(LayerId).into_dyn_boxed(),
646 LayerIds::One(id) => iter::once(id).into_dyn_boxed(),
647 LayerIds::Multiple(ids) => ids.into_iter().into_dyn_boxed(),
648 }
649 }
650}
651
652impl From<Vec<usize>> for LayerIds {
653 fn from(v: Vec<usize>) -> Self {
654 match v.len() {
655 0 => LayerIds::All,
656 1 => LayerIds::One(LayerId(v[0])),
657 _ => LayerIds::Multiple(v.into()),
658 }
659 }
660}
661
662impl From<Vec<LayerId>> for LayerIds {
663 fn from(v: Vec<LayerId>) -> Self {
664 match v.len() {
665 0 => LayerIds::All,
666 1 => LayerIds::One(v[0]),
667 _ => LayerIds::Multiple(v.into()),
668 }
669 }
670}
671
672impl<const N: usize> From<[usize; N]> for LayerIds {
673 fn from(v: [usize; N]) -> Self {
674 match v.len() {
675 0 => LayerIds::All,
676 1 => LayerIds::One(LayerId(v[0])),
677 _ => LayerIds::Multiple(v.into_iter().collect()),
678 }
679 }
680}
681
682impl<const N: usize> From<[LayerId; N]> for LayerIds {
683 fn from(v: [LayerId; N]) -> Self {
684 match v.len() {
685 0 => LayerIds::All,
686 1 => LayerIds::One(v[0]),
687 _ => LayerIds::Multiple(v.into_iter().collect()),
688 }
689 }
690}
691
692impl From<usize> for LayerIds {
693 fn from(id: usize) -> Self {
694 LayerIds::One(LayerId(id))
695 }
696}
697
698impl From<LayerId> for LayerIds {
699 fn from(id: LayerId) -> Self {
700 LayerIds::One(id)
701 }
702}
703
704#[cfg(test)]
705mod tests {
706 use std::hash::{Hash, Hasher};
707
708 use super::*;
709 use crate::core::entities::{LayerId, EID, MAX_EID};
710 use proptest::{prelude::*, prop_assert, prop_assert_eq, prop_oneof, proptest};
711
712 #[test]
713 fn test_elid_layer_proptest() {
714 proptest!(|(eid in 0..=MAX_EID, layer in 0..=usize::MAX)| {
715 let elid = EID(eid).with_layer(LayerId(layer));
716 prop_assert_eq!(elid.layer(), LayerId(layer));
717 prop_assert!(!elid.is_deletion());
718
719 let elid_deleted = elid.into_deletion();
720 prop_assert_eq!(elid_deleted.layer(), LayerId(layer));
721 prop_assert_eq!(elid_deleted.eid(), EID(eid));
722 prop_assert!(elid_deleted.is_deletion())
723 })
724 }
725
726 #[test]
727 fn test_elid_deletion_proptest() {
728 proptest!(|(eid in 0..=MAX_EID, layer in 0..=usize::MAX)| {
729 let elid = EID(eid).with_layer_deletion(LayerId(layer));
730 prop_assert_eq!(elid.layer(), LayerId(layer));
731 prop_assert!(elid.is_deletion());
732 prop_assert_eq!(elid, elid.into_deletion());
733 prop_assert_eq!(elid.eid().0, eid);
734 })
735 }
736
737 #[test]
738 fn gid_and_gid_ref_hash_to_the_same_thing() {
739 proptest!(|(gid in prop_oneof![any::<u64>().prop_map(GID::U64), ".*".prop_map(GID::Str)])| {
740 let gid_ref: GidRef<'_> = (&gid).into();
741 let mut gid_hasher = std::collections::hash_map::DefaultHasher::new();
742 let mut gid_ref_hasher = std::collections::hash_map::DefaultHasher::new();
743 gid.hash(&mut gid_hasher);
744 gid_ref.hash(&mut gid_ref_hasher);
745 prop_assert_eq!(gid_hasher.finish(), gid_ref_hasher.finish());
746 })
747 }
748}