Skip to main content

platform_data/
constants.rs

1use std::ops::RangeInclusive;
2
3use crate::Hybrid;
4use platform_num::LinkReference;
5
6#[derive(Clone, Eq, PartialEq, Debug)]
7pub struct LinksConstants<T: LinkReference> {
8    pub index_part: T,
9    pub source_part: T,
10    pub target_part: T,
11    pub null: T,
12    pub r#continue: T,
13    pub r#break: T,
14    pub skip: T,
15    pub any: T,
16    pub itself: T,
17    pub error: T,
18    pub internal_range: RangeInclusive<T>,
19    pub external_range: Option<RangeInclusive<T>>,
20}
21
22impl<T: LinkReference> LinksConstants<T> {
23    fn default_target_part() -> T {
24        T::from_byte(2)
25    }
26
27    pub fn full_new(
28        target_part: T,
29        internal: RangeInclusive<T>,
30        external: Option<RangeInclusive<T>>,
31    ) -> Self {
32        Self {
33            index_part: T::from_byte(0),
34            source_part: T::from_byte(1),
35            target_part,
36            null: T::from_byte(0),
37            r#continue: *internal.end(),
38            r#break: *internal.end() - T::from_byte(1),
39            skip: *internal.end() - T::from_byte(2),
40            any: *internal.end() - T::from_byte(3),
41            itself: *internal.end() - T::from_byte(4),
42            error: *internal.end() - T::from_byte(5),
43            internal_range: *internal.start()..=*internal.end() - T::from_byte(6),
44            external_range: external,
45        }
46    }
47
48    // TODO: enough for now
49    pub fn via_external(target_part: T, external: bool) -> Self {
50        Self::full_new(
51            target_part,
52            Self::default_internal(external),
53            Self::default_external(external),
54        )
55    }
56
57    pub fn via_ranges(internal: RangeInclusive<T>, external: Option<RangeInclusive<T>>) -> Self {
58        Self::full_new(Self::default_target_part(), internal, external)
59    }
60
61    #[must_use]
62    pub fn via_only_external(external: bool) -> Self {
63        Self::via_external(Self::default_target_part(), external)
64    }
65
66    #[must_use]
67    pub fn external() -> Self {
68        Self::via_only_external(true)
69    }
70
71    #[must_use]
72    pub fn internal() -> Self {
73        Self::via_only_external(false)
74    }
75
76    #[must_use]
77    pub fn new() -> Self {
78        Self::internal()
79    }
80
81    fn default_internal(external: bool) -> RangeInclusive<T> {
82        if external {
83            T::from_byte(1)..=Hybrid::half()
84        } else {
85            T::from_byte(1)..=T::MAX
86        }
87    }
88
89    fn default_external(external: bool) -> Option<RangeInclusive<T>> {
90        if external {
91            Some(Hybrid::half()..=T::MAX)
92        } else {
93            None
94        }
95    }
96
97    pub fn is_internal(&self, address: T) -> bool {
98        self.internal_range.contains(&address)
99    }
100
101    pub fn is_external(&self, address: T) -> bool {
102        self.external_range
103            .clone()
104            .is_some_and(|range| range.contains(&address))
105    }
106
107    pub fn is_reference(&self, address: T) -> bool {
108        self.is_internal(address) || self.is_external(address)
109    }
110}
111
112impl<T: LinkReference> Default for LinksConstants<T> {
113    fn default() -> Self {
114        Self::new()
115    }
116}