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