1use std::cmp::Ordering;
6use std::fmt::{Debug, Display, Error, Formatter, Octal};
7use std::hash::{Hash, Hasher};
8
9#[cfg(test)]
10use test_strategy::Arbitrary;
11
12use super::onescomplement::error::ConversionFailed;
13use super::onescomplement::signed::{Signed5Bit, Signed6Bit, Signed18Bit};
14use super::onescomplement::unsigned::{Unsigned6Bit, Unsigned18Bit, Unsigned36Bit};
15use super::onescomplement::{Signum, WordCommon};
16
17pub trait IndexBy<T> {
49 fn index_by(&self, delta: T) -> Address;
50}
51
52#[cfg_attr(test, derive(Arbitrary))]
68#[derive(Clone, Copy)]
69pub struct Address(Unsigned18Bit);
70
71pub const PLACEHOLDER_MARK_BIT: Unsigned18Bit = Unsigned18Bit::MAX.and(1u32 << 17); impl Address {
79 pub const ZERO: Address = Address(Unsigned18Bit::ZERO);
80 pub const MAX: Address = Address(Unsigned18Bit::MAX);
81
82 #[must_use]
83 pub const fn new(a: Unsigned18Bit) -> Address {
84 Address(a)
85 }
86
87 #[must_use]
93 pub const fn and(&self, mask: u32) -> Address {
94 Address(self.0.and(mask)) }
96
97 #[must_use]
99 pub fn mark_bit(&self) -> Unsigned18Bit {
100 self.0 & PLACEHOLDER_MARK_BIT
101 }
102
103 #[must_use]
109 pub fn is_marked_placeholder(&self) -> bool {
110 self.0 & PLACEHOLDER_MARK_BIT != 0_u16
111 }
112
113 #[must_use]
120 pub fn split(&self) -> (Unsigned18Bit, bool) {
121 let without_mark: Unsigned18Bit = self.0 & !PLACEHOLDER_MARK_BIT;
122 (without_mark, self.is_marked_placeholder())
123 }
124
125 #[must_use]
130 pub fn join(addr: Unsigned18Bit, mark: bool) -> Address {
131 let markbit: Unsigned18Bit = if mark {
132 PLACEHOLDER_MARK_BIT
133 } else {
134 Unsigned18Bit::ZERO
135 };
136 let addr_without_mark: Unsigned18Bit = addr & !PLACEHOLDER_MARK_BIT;
137 Address::from(markbit | addr_without_mark)
138 }
139
140 #[must_use]
146 pub fn successor(&self) -> Address {
147 self.index_by(1_u8)
148 }
149}
150
151impl From<Unsigned18Bit> for Address {
152 fn from(a: Unsigned18Bit) -> Address {
153 Address(a)
154 }
155}
156
157impl From<Address> for Unsigned18Bit {
158 fn from(addr: Address) -> Self {
159 addr.0
160 }
161}
162
163impl From<&Address> for Unsigned18Bit {
164 fn from(addr: &Address) -> Self {
165 addr.0
166 }
167}
168
169impl From<&Address> for Unsigned36Bit {
170 fn from(addr: &Address) -> Self {
171 addr.0.into()
172 }
173}
174
175impl From<Address> for Unsigned36Bit {
176 fn from(addr: Address) -> Self {
177 Unsigned36Bit::from(u32::from(addr))
178 }
179}
180
181impl TryFrom<Unsigned36Bit> for Address {
182 type Error = ConversionFailed;
183 fn try_from(n: Unsigned36Bit) -> Result<Address, ConversionFailed> {
184 let a: Unsigned18Bit = Unsigned18Bit::try_from(n)?;
185 Ok(Address::from(a))
186 }
187}
188
189impl IndexBy<u8> for Address {
190 fn index_by(&self, index: u8) -> Address {
191 let offset: Unsigned18Bit = index.into();
192 let (address, mark) = self.split();
193 Address::join(address.wrapping_add(offset) & !PLACEHOLDER_MARK_BIT, mark)
194 }
195}
196
197fn unsigned_idx_impl(base: Address, delta: Unsigned18Bit) -> Result<Address, ConversionFailed> {
198 let (current, mark) = base.split();
199 let physical = current.wrapping_add(delta) & !PLACEHOLDER_MARK_BIT;
200 Ok(Address::join(physical, mark))
201}
202
203fn signed_idx_impl(base: Address, delta: Signed18Bit) -> Result<Address, ConversionFailed> {
204 let (current, mark) = base.split();
205 let abs_delta: Unsigned18Bit = Unsigned18Bit::try_from(i32::from(delta.abs()))?;
206 let physical = match delta.signum() {
207 Signum::Zero => current,
208 Signum::Positive => current.wrapping_add(abs_delta),
209 Signum::Negative => current.wrapping_sub(abs_delta),
210 } & !PLACEHOLDER_MARK_BIT;
211 Ok(Address::join(physical, mark))
212}
213
214impl IndexBy<Signed5Bit> for Address {
215 fn index_by(&self, delta: Signed5Bit) -> Address {
216 signed_idx_impl(*self, Signed18Bit::from(delta)).unwrap()
217 }
218}
219
220impl IndexBy<Signed6Bit> for Address {
221 fn index_by(&self, delta: Signed6Bit) -> Address {
222 signed_idx_impl(*self, Signed18Bit::from(delta)).unwrap()
223 }
224}
225
226impl IndexBy<Signed18Bit> for Address {
227 fn index_by(&self, delta: Signed18Bit) -> Address {
228 signed_idx_impl(*self, delta).unwrap()
229 }
230}
231
232impl IndexBy<Unsigned18Bit> for Address {
233 fn index_by(&self, delta: Unsigned18Bit) -> Address {
234 unsigned_idx_impl(*self, delta).unwrap()
235 }
236}
237
238#[test]
239fn index_by_5bit_quantity() {
240 let start: Address = Address::from(Unsigned18Bit::from(0o4000_u16));
241 let up: Signed5Bit = Signed5Bit::try_from(6_i8).unwrap();
242 assert_eq!(
243 start.index_by(up),
244 Address::from(Unsigned18Bit::from(0o4006_u16))
245 );
246
247 let down: Signed5Bit = Signed5Bit::try_from(-4_i8).unwrap();
248 assert_eq!(
249 start.index_by(down),
250 Address::from(Unsigned18Bit::from(0o3774_u16))
251 );
252}
253
254impl TryFrom<u32> for Address {
255 type Error = ConversionFailed;
256 fn try_from(n: u32) -> Result<Address, ConversionFailed> {
257 let value = Unsigned18Bit::try_from(n)?;
258 Ok(Address::from(value))
259 }
260}
261
262impl From<Address> for u32 {
263 fn from(a: Address) -> u32 {
264 u32::from(Unsigned18Bit::from(a))
265 }
266}
267
268impl From<&Address> for u32 {
269 fn from(a: &Address) -> u32 {
270 u32::from(Unsigned18Bit::from(*a))
271 }
272}
273
274impl Default for Address {
275 fn default() -> Address {
276 Address::from(Unsigned18Bit::from(0_u8))
277 }
278}
279
280impl Display for Address {
281 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
282 write!(f, "{:>08o}", self.0)
284 }
285}
286
287impl Octal for Address {
288 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
289 let val = self.0;
290 Octal::fmt(&val, f) }
292}
293
294impl Debug for Address {
295 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
296 write!(f, "{:>08o}", self.0)
298 }
299}
300
301impl Ord for Address {
302 fn cmp(&self, other: &Self) -> Ordering {
303 self.0.cmp(&other.0)
304 }
305}
306
307impl PartialOrd for Address {
308 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
309 Some(self.cmp(other))
310 }
311}
312
313impl PartialEq for Address {
314 fn eq(&self, other: &Self) -> bool {
315 self.0.eq(&other.0)
316 }
317}
318
319impl Hash for Address {
320 fn hash<H>(&self, h: &mut H)
321 where
322 H: Hasher,
323 {
324 self.0.hash(h);
325 }
326}
327
328impl PartialEq<u32> for Address {
329 fn eq(&self, other: &u32) -> bool {
330 let v: u32 = self.0.into();
331 v.eq(other)
332 }
333}
334impl Eq for Address {}
335
336pub type SequenceNumber = Unsigned6Bit;
337
338#[test]
339fn test_sequence_numnber() {
340 const ZERO: SequenceNumber = SequenceNumber::ZERO;
341 const ONE: SequenceNumber = SequenceNumber::ONE;
342
343 assert_eq!(SequenceNumber::try_from(2_u8).unwrap(), ONE << ONE);
346
347 assert!(ONE > ZERO);
351 assert!(ZERO < ONE);
352 assert_eq!(ONE, ONE);
353 assert_eq!(ZERO, ZERO);
354 assert!(ONE != ZERO);
355 assert!(ZERO != ONE);
356
357 }