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}
151impl PartialEq<str> for GID {
152 fn eq(&self, other: &str) -> bool {
153 match self {
154 GID::U64(_) => false,
155 GID::Str(id) => id == other,
156 }
157 }
158}
159
160impl PartialEq<String> for GID {
161 fn eq(&self, other: &String) -> bool {
162 match self {
163 GID::U64(_) => false,
164 GID::Str(id) => id == other,
165 }
166 }
167}
168
169impl PartialEq<u64> for GID {
170 fn eq(&self, other: &u64) -> bool {
171 match self {
172 GID::Str(_) => false,
173 GID::U64(id) => id == other,
174 }
175 }
176}
177
178impl Default for GID {
179 fn default() -> Self {
180 GID::U64(u64::MAX)
181 }
182}
183
184impl Display for GID {
185 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
186 match self {
187 GID::U64(v) => write!(f, "{}", v),
188 GID::Str(v) => write!(f, "{}", v),
189 }
190 }
191}
192
193impl GID {
194 pub fn dtype(&self) -> GidType {
195 match self {
196 GID::U64(_) => GidType::U64,
197 GID::Str(_) => GidType::Str,
198 }
199 }
200 pub fn into_str(self) -> Option<String> {
201 match self {
202 GID::Str(v) => Some(v),
203 _ => None,
204 }
205 }
206
207 pub fn into_u64(self) -> Option<u64> {
208 match self {
209 GID::U64(v) => Some(v),
210 _ => None,
211 }
212 }
213
214 pub fn as_str(&self) -> Option<&str> {
215 match self {
216 GID::Str(v) => Some(v.as_str()),
217 _ => None,
218 }
219 }
220
221 pub fn as_u64(&self) -> Option<u64> {
222 match self {
223 GID::U64(v) => Some(*v),
224 _ => None,
225 }
226 }
227
228 pub fn to_str(&'_ self) -> Cow<'_, str> {
229 match self {
230 GID::U64(v) => Cow::Owned(v.to_string()),
231 GID::Str(v) => Cow::Borrowed(v),
232 }
233 }
234
235 pub fn to_i64(&self) -> Option<i64> {
236 match self {
237 GID::U64(v) => v.to_i64(),
238 GID::Str(v) => parse_u64_strict(v)?.to_i64(),
239 }
240 }
241
242 pub fn to_u64(&self) -> Option<u64> {
243 match self {
244 GID::U64(v) => Some(*v),
245 GID::Str(v) => parse_u64_strict(v),
246 }
247 }
248
249 pub fn as_ref(&self) -> GidRef<'_> {
250 match self {
251 GID::U64(v) => GidRef::U64(*v),
252 GID::Str(v) => GidRef::Str(v),
253 }
254 }
255}
256
257impl From<u64> for GID {
258 fn from(id: u64) -> Self {
259 Self::U64(id)
260 }
261}
262
263impl From<&u64> for GID {
264 fn from(value: &u64) -> Self {
265 GID::U64(*value)
266 }
267}
268
269impl From<String> for GID {
270 fn from(id: String) -> Self {
271 Self::Str(id)
272 }
273}
274
275impl From<&str> for GID {
276 fn from(id: &str) -> Self {
277 Self::Str(id.to_string())
278 }
279}
280
281impl<'a> From<GidRef<'a>> for GID {
282 fn from(value: GidRef<'a>) -> Self {
283 match value {
284 GidRef::U64(v) => GID::U64(v),
285 GidRef::Str(v) => GID::Str(v.to_owned()),
286 }
287 }
288}
289
290#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
291pub enum GidRef<'a> {
292 U64(u64),
293 Str(&'a str),
294}
295
296#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
297pub enum GidType {
298 U64,
299 Str,
300}
301
302impl Display for GidType {
303 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
304 match self {
305 GidType::U64 => {
306 write!(f, "Numeric")
307 }
308 GidType::Str => {
309 write!(f, "String")
310 }
311 }
312 }
313}
314
315impl Display for GidRef<'_> {
316 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
317 match self {
318 GidRef::U64(v) => write!(f, "{}", v),
319 GidRef::Str(v) => write!(f, "{}", v),
320 }
321 }
322}
323
324impl<'a> From<&'a GID> for GidRef<'a> {
325 fn from(value: &'a GID) -> Self {
326 match value {
327 GID::U64(v) => GidRef::U64(*v),
328 GID::Str(v) => GidRef::Str(v),
329 }
330 }
331}
332
333impl<'a> From<&'a str> for GidRef<'a> {
334 fn from(value: &'a str) -> Self {
335 GidRef::Str(value)
336 }
337}
338
339impl<'a> GidRef<'a> {
340 pub fn dtype(self) -> GidType {
341 match self {
342 GidRef::U64(_) => GidType::U64,
343 GidRef::Str(_) => GidType::Str,
344 }
345 }
346 pub fn as_str(self) -> Option<&'a str> {
347 match self {
348 GidRef::Str(s) => Some(s),
349 _ => None,
350 }
351 }
352
353 pub fn as_u64(self) -> Option<u64> {
354 match self {
355 GidRef::U64(v) => Some(v),
356 _ => None,
357 }
358 }
359
360 pub fn to_owned(self) -> GID {
361 match self {
362 GidRef::U64(v) => GID::U64(v),
363 GidRef::Str(v) => GID::Str(v.to_owned()),
364 }
365 }
366
367 pub fn to_str(self) -> Cow<'a, str> {
368 match self {
369 GidRef::U64(v) => Cow::Owned(v.to_string()),
370 GidRef::Str(v) => Cow::Borrowed(v),
371 }
372 }
373
374 pub fn to_i64(self) -> Option<i64> {
375 match self {
376 GidRef::U64(v) => v.to_i64(),
377 GidRef::Str(v) => parse_u64_strict(v)?.to_i64(),
378 }
379 }
380
381 pub fn to_u64(self) -> Option<u64> {
382 match self {
383 GidRef::U64(v) => Some(v),
384 GidRef::Str(v) => parse_u64_strict(v),
385 }
386 }
387}
388
389#[cfg(test)]
390mod test {
391 use crate::core::entities::Multiple;
392
393 #[test]
394 fn empty_bit_multiple() {
395 let bm = super::Multiple::default();
396 let actual = bm.into_iter().collect::<Vec<_>>();
397 let expected: Vec<usize> = vec![];
398 assert_eq!(actual, expected);
399 }
400
401 #[test]
402 fn set_one() {
403 let bm: Multiple = [1].into_iter().collect();
404 let actual = bm.into_iter().collect::<Vec<_>>();
405 assert_eq!(actual, vec![1usize]);
406 }
407
408 #[test]
409 fn set_two() {
410 let bm: Multiple = [1, 67].into_iter().collect();
411
412 let actual = bm.into_iter().collect::<Vec<_>>();
413 assert_eq!(actual, vec![1usize, 67]);
414 }
415}
416
417impl LayerIds {
418 pub fn find(&self, layer_id: usize) -> Option<usize> {
419 match self {
420 LayerIds::All => Some(layer_id),
421 LayerIds::One(id) => {
422 if *id == layer_id {
423 Some(layer_id)
424 } else {
425 None
426 }
427 }
428 LayerIds::Multiple(ids) => ids.contains(layer_id).then_some(layer_id),
429 LayerIds::None => None,
430 }
431 }
432
433 pub fn intersect(&self, other: &LayerIds) -> LayerIds {
434 match (self, other) {
435 (LayerIds::None, _) => LayerIds::None,
436 (_, LayerIds::None) => LayerIds::None,
437 (LayerIds::All, other) => other.clone(),
438 (this, LayerIds::All) => this.clone(),
439 (LayerIds::One(id), other) => {
440 if other.contains(id) {
441 LayerIds::One(*id)
442 } else {
443 LayerIds::None
444 }
445 }
446 (LayerIds::Multiple(ids), other) => {
447 let ids: Vec<usize> = ids.iter().filter(|id| other.contains(id)).collect();
448 match ids.len() {
449 0 => LayerIds::None,
450 1 => LayerIds::One(ids[0]),
451 _ => LayerIds::Multiple(ids.into()),
452 }
453 }
454 }
455 }
456
457 pub fn constrain_from_edge(&self, e: EdgeRef) -> Cow<'_, LayerIds> {
458 match e.layer() {
459 None => Cow::Borrowed(self),
460 Some(l) => self
461 .find(l)
462 .map(|id| Cow::Owned(LayerIds::One(id)))
463 .unwrap_or(Cow::Owned(LayerIds::None)),
464 }
465 }
466
467 pub fn contains(&self, layer_id: &usize) -> bool {
468 self.find(*layer_id).is_some()
469 }
470
471 pub fn is_none(&self) -> bool {
472 matches!(self, LayerIds::None)
473 }
474
475 pub fn is_single(&self) -> bool {
476 matches!(self, LayerIds::One(_))
477 }
478
479 pub fn iter(&self, num_layers: usize) -> impl Iterator<Item = usize> {
480 match self {
481 LayerIds::None => iter::empty().into_dyn_boxed(),
482 LayerIds::All => (0..num_layers).into_dyn_boxed(),
483 LayerIds::One(id) => iter::once(*id).into_dyn_boxed(),
484 LayerIds::Multiple(ids) => ids.into_iter().into_dyn_boxed(),
485 }
486 }
487}
488
489impl From<Vec<usize>> for LayerIds {
490 fn from(v: Vec<usize>) -> Self {
491 match v.len() {
492 0 => LayerIds::All,
493 1 => LayerIds::One(v[0]),
494 _ => LayerIds::Multiple(v.into()),
495 }
496 }
497}
498
499impl<const N: usize> From<[usize; N]> for LayerIds {
500 fn from(v: [usize; N]) -> Self {
501 match v.len() {
502 0 => LayerIds::All,
503 1 => LayerIds::One(v[0]),
504 _ => LayerIds::Multiple(v.into_iter().collect()),
505 }
506 }
507}
508
509impl From<usize> for LayerIds {
510 fn from(id: usize) -> Self {
511 LayerIds::One(id)
512 }
513}
514
515#[cfg(test)]
516mod tests {
517 use crate::core::entities::{EID, MAX_LAYER};
518 use proptest::{prop_assert, prop_assert_eq, proptest};
519
520 #[test]
521 fn test_elid_layer() {
522 proptest!(|(eid in 0..=usize::MAX, layer in 0..=MAX_LAYER)| {
523 let elid = EID(eid).with_layer(layer);
524 prop_assert_eq!(elid.layer(), layer);
525 prop_assert!(!elid.is_deletion());
526
527 let elid_deleted = elid.into_deletion();
528 prop_assert_eq!(elid_deleted.layer(), layer);
529 prop_assert_eq!(elid_deleted.edge, EID(eid));
530 prop_assert!(elid_deleted.is_deletion())
531 })
532 }
533
534 #[test]
535 fn test_elid_deletion() {
536 proptest!(|(eid in 0..=usize::MAX, layer in 0..=MAX_LAYER)| {
537 let elid = EID(eid).with_layer_deletion(layer);
538 prop_assert_eq!(elid.layer(), layer);
539 prop_assert!(elid.is_deletion());
540 prop_assert_eq!(elid, elid.into_deletion());
541 prop_assert_eq!(elid.edge.0, eid);
542 })
543 }
544}