vildrose_core/word/
conversion.rs1use super::{Tribble, Tryte, Word27, Word54, WordError};
2use crate::trit::Trit;
3
4impl Tribble {
5 pub const MIN_INT: i8 = -(3_i8.pow(3) - 1) / 2;
7
8 pub const MAX_INT: i8 = (3_i8.pow(3) - 1) / 2;
10
11 #[must_use]
13 pub fn to_int(self) -> i8 {
14 let mut value = 0_i8;
15 let mut place = 1_i8;
16
17 for trit in self.0 {
18 value += trit.value() * place;
19 place *= 3;
20 }
21
22 value
23 }
24
25 pub fn from_int(mut value: i8) -> Result<Self, WordError> {
32 if !(Self::MIN_INT..=Self::MAX_INT).contains(&value) {
33 return Err(WordError::OutOfRange);
34 }
35
36 let mut trits = [Trit::Z; Self::TRIT_COUNT];
37
38 for trit in &mut trits {
39 let remainder = value.rem_euclid(3);
40
41 *trit = match remainder {
42 0 => Trit::Z,
43 1 => Trit::P,
44 2 => {
45 value += 1;
46 Trit::N
47 }
48 _ => unreachable!("remainder modulo three is always 0, 1, or 2"),
49 };
50
51 value = value.div_euclid(3);
52 }
53
54 Ok(Self(trits))
55 }
56}
57
58impl From<Tribble> for i8 {
59 fn from(word: Tribble) -> Self {
60 word.to_int()
61 }
62}
63
64impl TryFrom<i8> for Tribble {
65 type Error = WordError;
66
67 fn try_from(value: i8) -> Result<Self, Self::Error> {
68 Self::from_int(value)
69 }
70}
71
72impl Tryte {
73 pub const MIN_INT: i16 = -(3_i16.pow(9) - 1) / 2;
75
76 pub const MAX_INT: i16 = (3_i16.pow(9) - 1) / 2;
78
79 #[must_use]
81 pub fn to_int(self) -> i16 {
82 let mut value = 0_i16;
83 let mut place = 1_i16;
84
85 for trit in self.0 {
86 value += i16::from(trit.value()) * place;
87 place *= 3;
88 }
89
90 value
91 }
92
93 pub fn from_int(mut value: i16) -> Result<Self, WordError> {
100 if !(Self::MIN_INT..=Self::MAX_INT).contains(&value) {
101 return Err(WordError::OutOfRange);
102 }
103
104 let mut trits = [Trit::Z; Self::TRIT_COUNT];
105
106 for trit in &mut trits {
107 let remainder = value.rem_euclid(3);
108
109 *trit = match remainder {
110 0 => Trit::Z,
111 1 => Trit::P,
112 2 => {
113 value += 1;
114 Trit::N
115 }
116 _ => unreachable!("remainder modulo three is always 0, 1, or 2"),
117 };
118
119 value = value.div_euclid(3);
120 }
121
122 Ok(Self(trits))
123 }
124}
125
126impl From<Tryte> for i16 {
127 fn from(word: Tryte) -> Self {
128 word.to_int()
129 }
130}
131
132impl TryFrom<i16> for Tryte {
133 type Error = WordError;
134
135 fn try_from(value: i16) -> Result<Self, Self::Error> {
136 Self::from_int(value)
137 }
138}
139
140impl Word27 {
141 pub const MIN_INT: i64 = -(3_i64.pow(27) - 1) / 2;
143
144 pub const MAX_INT: i64 = (3_i64.pow(27) - 1) / 2;
146
147 #[must_use]
149 pub fn to_int(self) -> i64 {
150 let mut value = 0_i64;
151 let mut place = 1_i64;
152
153 for trit in self.0 {
154 value += i64::from(trit.value()) * place;
155 place *= 3;
156 }
157
158 value
159 }
160
161 pub fn from_int(mut value: i64) -> Result<Self, WordError> {
168 if !(Self::MIN_INT..=Self::MAX_INT).contains(&value) {
169 return Err(WordError::OutOfRange);
170 }
171
172 let mut trits = [Trit::Z; Self::TRIT_COUNT];
173
174 for trit in &mut trits {
175 let remainder = value.rem_euclid(3);
176
177 *trit = match remainder {
178 0 => Trit::Z,
179 1 => Trit::P,
180 2 => {
181 value += 1;
182 Trit::N
183 }
184 _ => unreachable!("remainder modulo three is always 0, 1, or 2"),
185 };
186
187 value = value.div_euclid(3);
188 }
189
190 Ok(Self(trits))
191 }
192}
193
194impl From<Word27> for i64 {
195 fn from(word: Word27) -> Self {
196 word.to_int()
197 }
198}
199
200impl TryFrom<i64> for Word27 {
201 type Error = WordError;
202
203 fn try_from(value: i64) -> Result<Self, Self::Error> {
204 Self::from_int(value)
205 }
206}
207
208impl Word54 {
209 pub const MIN_INT: i128 = -(3_i128.pow(54) - 1) / 2;
211
212 pub const MAX_INT: i128 = (3_i128.pow(54) - 1) / 2;
214
215 #[must_use]
217 pub fn to_int(self) -> i128 {
218 let mut value = 0_i128;
219 let mut place = 1_i128;
220
221 for trit in self.0 {
222 value += i128::from(trit.value()) * place;
223 place *= 3;
224 }
225
226 value
227 }
228
229 pub fn from_int(mut value: i128) -> Result<Self, WordError> {
236 if !(Self::MIN_INT..=Self::MAX_INT).contains(&value) {
237 return Err(WordError::OutOfRange);
238 }
239
240 let mut trits = [Trit::Z; Self::TRIT_COUNT];
241
242 for trit in &mut trits {
243 let remainder = value.rem_euclid(3);
244
245 *trit = match remainder {
246 0 => Trit::Z,
247 1 => Trit::P,
248 2 => {
249 value += 1;
250 Trit::N
251 }
252 _ => unreachable!("remainder modulo three is always 0, 1, or 2"),
253 };
254
255 value = value.div_euclid(3);
256 }
257
258 Ok(Self(trits))
259 }
260}
261
262impl From<Word54> for i128 {
263 fn from(word: Word54) -> Self {
264 word.to_int()
265 }
266}
267
268impl TryFrom<i128> for Word54 {
269 type Error = WordError;
270
271 fn try_from(value: i128) -> Result<Self, Self::Error> {
272 Self::from_int(value)
273 }
274}