link_cli/link.rs
1//! Link - A doublet (source, target) pair with an index
2//!
3//! This module provides the core link data structure that represents
4//! a link in the doublet storage.
5//!
6//! The structure is generic over the link *address* type ([`GenericLink`])
7//! so that the storage and transactions layers can be reused with any
8//! address width supported by `doublets` (`u32`, `u64`, `usize`, ...).
9//! [`Link`] is the `u32` specialisation used by the `clink` CLI itself.
10
11use doublets::data::LinkReference;
12
13/// A doublet `(source, target)` pair together with its own address.
14///
15/// Generic over the address type `T` so external consumers can use the
16/// same storage/transaction stack with `usize`-addressed doublets stores.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
18pub struct GenericLink<T> {
19 pub index: T,
20 pub source: T,
21 pub target: T,
22}
23
24impl<T> GenericLink<T> {
25 /// Creates a new link with the given index, source, and target
26 pub const fn new(index: T, source: T, target: T) -> Self {
27 Self {
28 index,
29 source,
30 target,
31 }
32 }
33}
34
35impl<T: LinkReference> GenericLink<T> {
36 /// The null link (all addresses zero).
37 pub fn null() -> Self {
38 let zero = T::from_byte(0);
39 Self::new(zero, zero, zero)
40 }
41
42 /// Returns true if this link is null (all zeros)
43 pub fn is_null(&self) -> bool {
44 let zero = T::from_byte(0);
45 self.index == zero && self.source == zero && self.target == zero
46 }
47
48 /// Returns true if this is a full point (self-referential link)
49 pub fn is_full_point(&self) -> bool {
50 self.index == self.source && self.source == self.target
51 }
52
53 /// Returns true if this link references itself from at least one side.
54 pub fn is_partial_point(&self) -> bool {
55 self.index == self.source || self.index == self.target
56 }
57
58 /// Formats the link for display
59 pub fn format(&self) -> String {
60 format!("({} {} {})", self.index, self.source, self.target)
61 }
62}
63
64/// The `u32`-addressed link used by the `clink` CLI and its decorators.
65pub type Link = GenericLink<u32>;
66
67/// Link type from the upstream `doublets` crate used as the Rust basis.
68pub type DoubletsLink = doublets::Link<u32>;
69
70impl<T: LinkReference> From<doublets::Link<T>> for GenericLink<T> {
71 fn from(link: doublets::Link<T>) -> Self {
72 Self::new(link.index, link.source, link.target)
73 }
74}
75
76impl<T: LinkReference> From<GenericLink<T>> for doublets::Link<T> {
77 fn from(link: GenericLink<T>) -> Self {
78 Self::new(link.index, link.source, link.target)
79 }
80}