Skip to main content

datex_core/shared_values/
pointer_address.rs

1use crate::{
2    global::protocol_structures::instructions::{
3        RawInternalPointerAddress, RawPointerAddress,
4    },
5    prelude::*,
6};
7
8use crate::global::protocol_structures::instructions::{
9    RawLocalPointerAddress, RawRemotePointerAddress,
10};
11use core::{fmt::Display, result::Result};
12use serde::{Deserialize, Serialize};
13
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub struct OwnedPointerAddress {
16    pub(crate) address: [u8; 5],
17}
18
19#[derive(Debug, Clone, PartialEq, Eq, Hash)]
20pub enum ReferencedPointerAddress {
21    // pointer with a remote endpoint as origin, contains the full pointers address
22    Remote([u8; 26]),
23    // globally unique internal pointer, e.g. for #core, #std
24    Internal([u8; 3]), // TODO #312 shrink down to 2 bytes?
25}
26
27impl OwnedPointerAddress {
28    pub fn new(address: [u8; 5]) -> Self {
29        OwnedPointerAddress { address }
30    }
31
32    pub const NULL: OwnedPointerAddress =
33        OwnedPointerAddress { address: [0u8; 5] };
34}
35
36#[derive(Debug, Clone, PartialEq, Eq, Hash)]
37pub enum PointerAddress {
38    // pointer with the local endpoint as origin
39    // the full pointer id consists of the local endpoint id + this local id
40    Owned(OwnedPointerAddress),
41    // pointer with a remote endpoint as origin, contains the full pointers address
42    Referenced(ReferencedPointerAddress),
43}
44
45impl PointerAddress {
46    pub const NULL: PointerAddress =
47        PointerAddress::Owned(OwnedPointerAddress::NULL);
48
49    pub fn owned(address: [u8; 5]) -> Self {
50        PointerAddress::Owned(OwnedPointerAddress::new(address))
51    }
52
53    pub fn internal(address: [u8; 3]) -> Self {
54        PointerAddress::Referenced(ReferencedPointerAddress::Internal(address))
55    }
56
57    pub fn remote(address: [u8; 26]) -> Self {
58        PointerAddress::Referenced(ReferencedPointerAddress::Remote(address))
59    }
60}
61
62impl TryFrom<String> for PointerAddress {
63    type Error = &'static str;
64    fn try_from(s: String) -> Result<Self, Self::Error> {
65        PointerAddress::try_from(s.as_str())
66    }
67}
68impl TryFrom<&str> for PointerAddress {
69    type Error = &'static str;
70    fn try_from(s: &str) -> Result<Self, Self::Error> {
71        let hex_str = if let Some(stripped) = s.strip_prefix('$') {
72            stripped
73        } else {
74            s
75        };
76        let bytes = hex::decode(hex_str).map_err(|_| "Invalid hex string")?;
77        match bytes.len() {
78            5 => {
79                let mut arr = [0u8; 5];
80                arr.copy_from_slice(&bytes);
81                Ok(PointerAddress::Owned(OwnedPointerAddress::new(arr)))
82            }
83            26 => {
84                let mut arr = [0u8; 26];
85                arr.copy_from_slice(&bytes);
86                Ok(PointerAddress::Referenced(
87                    ReferencedPointerAddress::Remote(arr),
88                ))
89            }
90            3 => {
91                let mut arr = [0u8; 3];
92                arr.copy_from_slice(&bytes);
93                Ok(PointerAddress::Referenced(
94                    ReferencedPointerAddress::Internal(arr),
95                ))
96            }
97            _ => Err("PointerAddress must be 5, 26 or 3 bytes long"),
98        }
99    }
100}
101
102impl From<RawPointerAddress> for PointerAddress {
103    fn from(raw: RawPointerAddress) -> Self {
104        PointerAddress::from(&raw)
105    }
106}
107
108impl From<&RawLocalPointerAddress> for PointerAddress {
109    fn from(raw: &RawLocalPointerAddress) -> Self {
110        PointerAddress::Owned(OwnedPointerAddress::new(raw.id))
111    }
112}
113
114impl From<&RawInternalPointerAddress> for PointerAddress {
115    fn from(raw: &RawInternalPointerAddress) -> Self {
116        PointerAddress::Referenced(ReferencedPointerAddress::Internal(raw.id))
117    }
118}
119
120impl From<&RawRemotePointerAddress> for PointerAddress {
121    fn from(raw: &RawRemotePointerAddress) -> Self {
122        PointerAddress::Referenced(ReferencedPointerAddress::Remote(raw.id))
123    }
124}
125
126impl From<&RawPointerAddress> for PointerAddress {
127    fn from(raw: &RawPointerAddress) -> Self {
128        match raw {
129            RawPointerAddress::Local(bytes) => {
130                PointerAddress::Owned(OwnedPointerAddress::new(bytes.id))
131            }
132            RawPointerAddress::Internal(bytes) => PointerAddress::Referenced(
133                ReferencedPointerAddress::Internal(bytes.id),
134            ),
135            RawPointerAddress::Remote(bytes) => PointerAddress::Referenced(
136                ReferencedPointerAddress::Remote(bytes.id),
137            ),
138        }
139    }
140}
141
142impl PointerAddress {
143    pub fn to_address_string(&self) -> String {
144        match self {
145            PointerAddress::Owned(local_address) => {
146                hex::encode(local_address.address)
147            }
148            PointerAddress::Referenced(ReferencedPointerAddress::Remote(
149                bytes,
150            )) => hex::encode(bytes),
151            PointerAddress::Referenced(ReferencedPointerAddress::Internal(
152                bytes,
153            )) => hex::encode(bytes),
154        }
155    }
156}
157
158impl Display for PointerAddress {
159    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
160        core::write!(f, "$")?;
161        core::write!(f, "{}", self.to_address_string())
162    }
163}
164impl Serialize for PointerAddress {
165    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
166    where
167        S: serde::Serializer,
168    {
169        let addr_str = self.to_address_string();
170        serializer.serialize_str(&addr_str)
171    }
172}
173impl<'de> Deserialize<'de> for PointerAddress {
174    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
175    where
176        D: serde::Deserializer<'de>,
177    {
178        let s = String::deserialize(deserializer)?;
179        PointerAddress::try_from(s.as_str()).map_err(|e| {
180            serde::de::Error::custom(format!(
181                "Failed to parse PointerAddress: {}",
182                e
183            ))
184        })
185    }
186}
187
188impl PointerAddress {
189    pub fn bytes(&self) -> &[u8] {
190        match self {
191            PointerAddress::Owned(local_address) => &local_address.address,
192            PointerAddress::Referenced(ReferencedPointerAddress::Remote(
193                bytes,
194            )) => bytes,
195            PointerAddress::Referenced(ReferencedPointerAddress::Internal(
196                bytes,
197            )) => bytes,
198        }
199    }
200
201    pub fn internal_bytes(&self) -> Option<&[u8; 3]> {
202        if let PointerAddress::Referenced(ReferencedPointerAddress::Internal(
203            bytes,
204        )) = self
205        {
206            Some(bytes)
207        } else {
208            None
209        }
210    }
211}