crypto/encoding/ternary/
tryte.rs1extern crate alloc;
5
6use alloc::vec::Vec;
7use core::{
8 convert::TryFrom,
9 fmt,
10 iter::FromIterator,
11 ops::{Deref, DerefMut},
12 str::FromStr,
13};
14
15use crate::encoding::ternary::{Btrit, Error, Trits, T3B1};
16
17#[derive(Copy, Clone, Eq, Hash, PartialEq)]
19#[repr(i8)]
20#[allow(missing_docs)]
21pub enum Tryte {
22 N = -13,
23 O = -12,
24 P = -11,
25 Q = -10,
26 R = -9,
27 S = -8,
28 T = -7,
29 U = -6,
30 V = -5,
31 W = -4,
32 X = -3,
33 Y = -2,
34 Z = -1,
35 Nine = 0,
36 A = 1,
37 B = 2,
38 C = 3,
39 D = 4,
40 E = 5,
41 F = 6,
42 G = 7,
43 H = 8,
44 I = 9,
45 J = 10,
46 K = 11,
47 L = 12,
48 M = 13,
49}
50
51impl Tryte {
52 pub const MIN_VALUE: Self = Tryte::N;
54
55 pub const MAX_VALUE: Self = Tryte::M;
57
58 pub fn from_trits(trits: [Btrit; 3]) -> Self {
60 let x = i8::from(trits[0]) + i8::from(trits[1]) * 3 + i8::from(trits[2]) * 9;
61 Tryte::try_from(x).unwrap()
62 }
63
64 pub fn as_trits(&self) -> &Trits<T3B1> {
66 unsafe { &*(T3B1::make(self as *const _ as *const _, 0, 3) as *const _) }
67 }
68
69 pub fn as_trits_mut(&mut self) -> &mut Trits<T3B1> {
71 unsafe { &mut *(T3B1::make(self as *const _ as *const _, 0, 3) as *mut _) }
72 }
73}
74
75impl From<Tryte> for char {
76 fn from(tryte: Tryte) -> char {
77 match tryte as i8 {
78 0 => '9',
79 -13..=-1 => (((tryte as i8 + 13) as u8) + b'N') as char,
80 1..=13 => (((tryte as i8 - 1) as u8) + b'A') as char,
81 x => unreachable!("Tried to decode Tryte with variant {}", x),
82 }
83 }
84}
85
86impl From<[Btrit; 3]> for Tryte {
87 fn from(trits: [Btrit; 3]) -> Self {
88 Self::from_trits(trits)
89 }
90}
91
92impl fmt::Debug for Tryte {
93 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94 write!(f, "{:?}", char::from(*self))
95 }
96}
97
98impl fmt::Display for Tryte {
99 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100 write!(f, "{}", char::from(*self))
101 }
102}
103
104impl TryFrom<char> for Tryte {
105 type Error = Error;
106
107 fn try_from(c: char) -> Result<Self, Self::Error> {
108 match c {
109 '9' => Ok(Tryte::Nine),
110 'N'..='Z' => Ok(unsafe { core::mem::transmute::<i8, Self>((c as u8 - b'N') as i8 - 13) }),
111 'A'..='M' => Ok(unsafe { core::mem::transmute::<i8, Self>((c as u8 - b'A') as i8 + 1) }),
112 _ => Err(Error::InvalidRepr),
113 }
114 }
115}
116
117impl TryFrom<i8> for Tryte {
118 type Error = Error;
119
120 fn try_from(x: i8) -> Result<Self, Self::Error> {
121 match x {
122 -13..=13 => Ok(unsafe { core::mem::transmute::<i8, Self>(x) }),
123 _ => Err(Error::InvalidRepr),
124 }
125 }
126}
127
128#[derive(Default)]
131pub struct TryteBuf {
132 inner: Vec<Tryte>,
133}
134
135impl TryteBuf {
136 pub fn new() -> Self {
138 Self::default()
139 }
140
141 pub fn with_capacity(cap: usize) -> Self {
143 Self {
144 inner: Vec::with_capacity(cap),
145 }
146 }
147
148 pub fn try_from_str(s: &str) -> Result<Self, Error> {
150 s.chars().map(Tryte::try_from).collect()
151 }
152
153 pub fn is_empty(&self) -> bool {
155 self.len() == 0
156 }
157
158 pub fn len(&self) -> usize {
160 self.inner.len()
161 }
162
163 pub fn push(&mut self, tryte: Tryte) {
165 self.inner.push(tryte);
166 }
167
168 pub fn pop(&mut self) -> Option<Tryte> {
170 self.inner.pop()
171 }
172
173 pub fn as_trits(&self) -> &Trits<T3B1> {
175 unsafe { &*(T3B1::make(self.as_ptr() as *const _, 0, self.len() * 3) as *const _) }
176 }
177
178 pub fn as_trits_mut(&mut self) -> &mut Trits<T3B1> {
180 unsafe { &mut *(T3B1::make(self.as_ptr() as *const _, 0, self.len() * 3) as *mut _) }
181 }
182}
183
184impl Deref for TryteBuf {
185 type Target = [Tryte];
186 fn deref(&self) -> &Self::Target {
187 &self.inner
188 }
189}
190
191impl DerefMut for TryteBuf {
192 fn deref_mut(&mut self) -> &mut Self::Target {
193 &mut self.inner
194 }
195}
196
197impl FromIterator<Tryte> for TryteBuf {
198 fn from_iter<I: IntoIterator<Item = Tryte>>(iter: I) -> Self {
199 let iter = iter.into_iter();
200 let mut this = Self::with_capacity(iter.size_hint().0);
201 for tryte in iter {
202 this.push(tryte);
203 }
204 this
205 }
206}
207
208impl<'a> From<&'a [Tryte]> for TryteBuf {
209 fn from(trytes: &'a [Tryte]) -> Self {
210 Self { inner: trytes.to_vec() }
211 }
212}
213
214impl FromStr for TryteBuf {
215 type Err = Error;
216
217 fn from_str(s: &str) -> Result<Self, Self::Err> {
218 Self::try_from_str(s)
219 }
220}
221
222impl fmt::Debug for TryteBuf {
223 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224 write!(f, "{:?}", self.inner)
225 }
226}
227
228impl fmt::Display for TryteBuf {
229 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
230 for tryte in self.iter() {
231 write!(f, "{}", tryte)?;
232 }
233 Ok(())
234 }
235}