platform_data/
constants.rs1use 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(
33 target_part: T,
34 internal: RangeInclusive<T>,
35 external: Option<RangeInclusive<T>>,
36 ) -> Self {
37 if let Some(external) = external.as_ref() {
38 assert!(
39 external.is_empty()
40 || external.end() < internal.start()
41 || external.start() > internal.end(),
42 "external range must not overlap the internal range or reserved service values"
43 );
44 }
45
46 Self {
47 index_part: T::from_byte(0),
48 source_part: T::from_byte(1),
49 target_part,
50 null: T::from_byte(0),
51 r#continue: *internal.end(),
52 r#break: *internal.end() - T::from_byte(1),
53 skip: *internal.end() - T::from_byte(2),
54 any: *internal.end() - T::from_byte(3),
55 itself: *internal.end() - T::from_byte(4),
56 error: *internal.end() - T::from_byte(5),
57 internal_range: *internal.start()..=*internal.end() - T::from_byte(6),
58 external_range: external,
59 }
60 }
61
62 pub fn via_external(target_part: T, external: bool) -> Self {
64 Self::full_new(
65 target_part,
66 Self::default_internal(external),
67 Self::default_external(external),
68 )
69 }
70
71 pub fn via_ranges(internal: RangeInclusive<T>, external: Option<RangeInclusive<T>>) -> Self {
77 Self::full_new(Self::default_target_part(), internal, external)
78 }
79
80 #[must_use]
81 pub fn via_only_external(external: bool) -> Self {
82 Self::via_external(Self::default_target_part(), external)
83 }
84
85 #[must_use]
87 pub fn external() -> Self {
88 Self::via_only_external(true)
89 }
90
91 #[must_use]
92 pub fn internal() -> Self {
93 Self::via_only_external(false)
94 }
95
96 #[must_use]
97 pub fn new() -> Self {
98 Self::internal()
99 }
100
101 fn default_internal(external: bool) -> RangeInclusive<T> {
102 if external {
103 T::from_byte(1)..=Hybrid::half()
104 } else {
105 T::from_byte(1)..=T::MAX
106 }
107 }
108
109 fn default_external(external: bool) -> Option<RangeInclusive<T>> {
110 if external {
111 Some(Hybrid::<T>::half() + T::from_byte(1)..=T::MAX)
112 } else {
113 None
114 }
115 }
116
117 pub fn is_internal(&self, address: T) -> bool {
118 self.internal_range.contains(&address)
119 }
120
121 pub fn is_external(&self, address: T) -> bool {
122 self.external_range
123 .clone()
124 .is_some_and(|range| range.contains(&address))
125 }
126
127 pub fn is_reference(&self, address: T) -> bool {
128 self.is_internal(address) || self.is_external(address)
129 }
130}
131
132impl<T: LinkReference> Default for LinksConstants<T> {
133 fn default() -> Self {
134 Self::new()
135 }
136}