1use std::{
2 convert::TryFrom,
3 slice,
4};
5
6pub mod bigint;
7pub mod num_conversions;
8pub mod raw;
9pub mod t1b1;
10pub mod t2b1;
11pub mod t3b1;
12pub mod t4b1;
13pub mod t5b1;
14pub mod trit;
15pub mod tryte;
16
17#[cfg(feature = "serde1")]
18mod serde;
19
20use crate::raw::{
21 RawEncoding,
22 RawEncodingBuf,
23};
24use std::{
25 any,
26 borrow::{
27 Borrow,
28 BorrowMut,
29 },
30 cmp::{
31 self,
32 Ordering,
33 },
34 fmt,
35 hash,
36 iter::FromIterator,
37 ops::{
38 Deref,
39 DerefMut,
40 Index,
41 IndexMut,
42 Range,
43 },
44 ptr,
45};
46
47pub use crate::{
49 t1b1::{
50 T1B1Buf,
51 T1B1,
52 },
53 t2b1::{
54 T2B1Buf,
55 T2B1,
56 },
57 t3b1::{
58 T3B1Buf,
59 T3B1,
60 },
61 t4b1::{
62 T4B1Buf,
63 T4B1,
64 },
65 t5b1::{
66 T5B1Buf,
67 T5B1,
68 },
69 trit::{
70 Btrit,
71 ShiftTernary,
72 Trit,
73 Utrit,
74 },
75 tryte::{
76 Tryte,
77 TryteBuf,
78 MAX_TRYTE_VALUE,
79 MIN_TRYTE_VALUE,
80 },
81};
82
83#[derive(Debug)]
84pub enum Error {
85 InvalidRepr,
86}
87
88#[derive(Hash)]
89#[repr(transparent)]
90pub struct Trits<T: RawEncoding + ?Sized = T1B1<Btrit>>(T);
91
92impl<T> Trits<T>
93where
94 T: RawEncoding + ?Sized,
95{
96 pub fn empty() -> &'static Self {
97 unsafe { &*(T::empty() as *const _ as *const Self) }
98 }
99
100 pub unsafe fn from_raw_unchecked(raw: &[i8], num_trits: usize) -> &Self {
101 debug_assert!(raw.iter().all(T::is_valid));
102 &*(T::from_raw_unchecked(raw, num_trits) as *const _ as *const _)
103 }
104
105 pub unsafe fn from_raw_unchecked_mut(raw: &mut [i8], num_trits: usize) -> &mut Self {
106 debug_assert!(raw.iter().all(T::is_valid));
107 &mut *(T::from_raw_unchecked(raw, num_trits) as *const _ as *mut _)
108 }
109
110 pub fn try_from_raw(raw: &[i8], num_trits: usize) -> Result<&Self, Error> {
111 if raw.iter().all(T::is_valid) {
112 Ok(unsafe { Self::from_raw_unchecked(raw, num_trits) })
113 } else {
114 Err(Error::InvalidRepr)
115 }
116 }
117
118 pub fn try_from_raw_mut(raw: &mut [i8], num_trits: usize) -> Result<&mut Self, Error> {
119 if raw.iter().all(T::is_valid) {
120 Ok(unsafe { Self::from_raw_unchecked_mut(raw, num_trits) })
121 } else {
122 Err(Error::InvalidRepr)
123 }
124 }
125
126 pub fn len(&self) -> usize {
127 self.0.len()
128 }
129
130 pub fn as_i8_slice(&self) -> &[i8] {
133 self.0.as_i8_slice()
134 }
135
136 pub unsafe fn as_i8_slice_mut(&mut self) -> &mut [i8] {
139 self.0.as_i8_slice_mut()
140 }
141
142 pub unsafe fn get_unchecked(&self, index: usize) -> T::Trit {
143 debug_assert!(index < self.len());
144 self.0.get_unchecked(index)
145 }
146
147 pub unsafe fn set_unchecked(&mut self, index: usize, trit: T::Trit) {
148 debug_assert!(index < self.len());
149 self.0.set_unchecked(index, trit);
150 }
151
152 pub fn get(&self, index: usize) -> Option<T::Trit> {
153 if index < self.0.len() {
154 unsafe { Some(self.get_unchecked(index)) }
155 } else {
156 None
157 }
158 }
159
160 pub fn set(&mut self, index: usize, trit: T::Trit) {
161 if index < self.0.len() {
162 unsafe { self.set_unchecked(index, trit) };
163 } else {
164 panic!(
165 "Attempt to set trit at index {}, but length of slice is {}",
166 index,
167 self.len()
168 );
169 }
170 }
171
172 pub fn trits(&self) -> impl DoubleEndedIterator<Item = T::Trit> + ExactSizeIterator<Item = T::Trit> + '_ {
173 (0..self.0.len()).map(move |idx| unsafe { self.0.get_unchecked(idx) })
174 }
175
176 pub fn slice(&self, range: Range<usize>) -> &Self {
177 assert!(range.end >= range.start && range.end <= self.len());
178 unsafe { &*(self.0.slice_unchecked(range) as *const _ as *const Self) }
179 }
180
181 pub fn slice_mut(&mut self, range: Range<usize>) -> &mut Self {
182 assert!(range.end >= range.start && range.end <= self.len());
183 unsafe { &mut *(self.0.slice_unchecked_mut(range) as *mut _ as *mut Self) }
184 }
185
186 pub fn copy_from<U: RawEncoding<Trit = T::Trit> + ?Sized>(&mut self, trits: &Trits<U>) {
187 assert!(self.len() == trits.len());
188 for (i, trit) in trits.trits().enumerate() {
189 unsafe {
190 self.set_unchecked(i, trit);
191 }
192 }
193 }
194
195 pub fn fill(&mut self, trit: T::Trit) {
196 for i in 0..self.len() {
197 self.set(i, trit);
198 }
199 }
200
201 pub fn to_buf<U>(&self) -> TritBuf<U>
202 where
203 U: RawEncodingBuf,
204 U::Slice: RawEncoding<Trit = T::Trit>,
205 {
206 self.trits().collect()
207 }
208
209 pub fn chunks(
210 &self,
211 chunk_len: usize,
212 ) -> impl DoubleEndedIterator<Item = &Self> + ExactSizeIterator<Item = &Self> + '_ {
213 assert!(chunk_len > 0);
214 (0..self.len())
215 .step_by(chunk_len)
216 .map(move |i| self.slice(i..(i + chunk_len).min(self.len())))
217 }
218
219 pub fn encode<U>(&self) -> TritBuf<U>
220 where
221 U: RawEncodingBuf,
222 U::Slice: RawEncoding<Trit = T::Trit>,
223 {
224 self.trits().collect()
225 }
226}
227
228impl<T: Trit> Trits<T1B1<T>> {
229 pub fn as_raw_slice(&self) -> &[T] {
230 self.0.as_raw_slice()
231 }
232
233 pub fn as_raw_slice_mut(&mut self) -> &mut [T] {
234 self.0.as_raw_slice_mut()
235 }
236
237 pub fn chunks_mut(&mut self, chunk_len: usize) -> impl Iterator<Item = &mut Self> + '_ {
240 assert!(chunk_len > 0);
241 (0..self.len()).step_by(chunk_len).scan(self, move |this, _| {
242 let idx = chunk_len.min(this.len());
243 let (a, b) = Trits::split_at_mut(this, idx);
244 *this = b;
245 Some(a)
246 })
247 }
248
249 pub fn copy_raw_bytes(&mut self, trits: &Trits<T1B1>, offset: usize, count: usize) {
250 assert!(self.len() >= offset + count);
251 unsafe {
252 ptr::copy(
253 trits.as_i8_slice().as_ptr(),
254 self.as_i8_slice_mut().as_mut_ptr().offset(offset as isize),
255 count,
256 );
257 }
258 }
259
260 fn split_at_mut<'a>(this: &mut &'a mut Self, idx: usize) -> (&'a mut Self, &'a mut Self) {
265 assert!(idx <= this.len());
266 (
267 unsafe { &mut *(this.0.slice_unchecked_mut(0..idx) as *mut _ as *mut Self) },
268 unsafe { &mut *(this.0.slice_unchecked_mut(idx..this.len()) as *mut _ as *mut Self) },
269 )
270 }
271
272 pub fn iter<'a>(&'a self) -> slice::Iter<'a, T> {
273 self.as_raw_slice().iter()
274 }
275
276 pub fn iter_mut<'a>(&'a mut self) -> slice::IterMut<'a, T> {
277 self.as_raw_slice_mut().iter_mut()
278 }
279}
280
281impl Trits<T3B1> {
282 pub fn as_trytes(&self) -> &[Tryte] {
285 assert!(self.len() % 3 == 0);
286 unsafe { &*(self.as_i8_slice() as *const _ as *const _) }
287 }
288
289 pub fn as_trytes_mut(&mut self) -> &mut [Tryte] {
292 assert!(self.len() % 3 == 0);
293 unsafe { &mut *(self.as_i8_slice_mut() as *mut _ as *mut _) }
294 }
295}
296
297impl<T, U> cmp::PartialEq<Trits<U>> for Trits<T>
298where
299 T: RawEncoding + ?Sized,
300 U: RawEncoding<Trit = T::Trit> + ?Sized,
301{
302 fn eq(&self, other: &Trits<U>) -> bool {
303 self.len() == other.len() && self.trits().zip(other.trits()).all(|(a, b)| a == b)
304 }
305}
306
307impl<T, U> cmp::PartialOrd<Trits<U>> for Trits<T>
308where
309 T: RawEncoding + ?Sized,
310 U: RawEncoding<Trit = T::Trit> + ?Sized,
311 T::Trit: cmp::PartialOrd,
312{
313 fn partial_cmp(&self, other: &Trits<U>) -> Option<Ordering> {
314 if self.len() != other.len() {
315 return None;
316 }
317
318 for (a, b) in self.trits().zip(other.trits()) {
319 match a.partial_cmp(&b) {
320 Some(Ordering::Equal) => continue,
321 other_order => return other_order,
322 }
323 }
324
325 Some(Ordering::Equal)
326 }
327}
328
329impl<'a, T: RawEncoding + ?Sized> fmt::Debug for &'a Trits<T> {
330 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
331 write!(f, "Trits<{}> [", any::type_name::<T>())?;
332 for (i, trit) in self.trits().enumerate() {
333 if i != 0 {
334 write!(f, ", ")?;
335 }
336 write!(f, "{:?}", trit)?;
337 }
338 write!(f, "]")
339 }
340}
341
342impl<T: RawEncoding + ?Sized> Index<Range<usize>> for Trits<T> {
343 type Output = Self;
344
345 fn index(&self, range: Range<usize>) -> &Self::Output {
346 self.slice(range)
347 }
348}
349
350impl<T: RawEncoding + ?Sized> IndexMut<Range<usize>> for Trits<T> {
351 fn index_mut(&mut self, range: Range<usize>) -> &mut Self::Output {
352 self.slice_mut(range)
353 }
354}
355
356impl<T: RawEncoding + ?Sized> ToOwned for Trits<T> {
357 type Owned = TritBuf<T::Buf>;
358
359 fn to_owned(&self) -> Self::Owned {
360 self.to_buf()
361 }
362}
363
364#[derive(Clone)]
365#[repr(transparent)]
366pub struct TritBuf<T: RawEncodingBuf = T1B1Buf<Btrit>>(T);
367
368impl<T: RawEncodingBuf> TritBuf<T> {
369 pub fn new() -> Self {
370 Self(T::new())
371 }
372
373 fn with_capacity(_cap: usize) -> Self {
375 Self::new()
377 }
378
379 pub fn filled(len: usize, trit: <T::Slice as RawEncoding>::Trit) -> Self {
380 let mut this = Self::with_capacity(len);
381 for _ in 0..len {
382 this.push(trit);
383 }
384 this
385 }
386
387 pub fn zeros(len: usize) -> Self {
388 Self::filled(len, <T::Slice as RawEncoding>::Trit::zero())
389 }
390
391 pub fn from_trits(trits: &[<T::Slice as RawEncoding>::Trit]) -> Self {
392 Self(T::from_trits(trits))
393 }
394
395 #[deprecated]
397 pub fn from_i8_unchecked(trits: &[i8]) -> Self {
398 trits
399 .iter()
400 .map(|t| <T::Slice as RawEncoding>::Trit::try_from(*t))
401 .collect::<Result<Self, _>>()
402 .unwrap_or_else(|_| panic!("Invalid i8 when converting to trit."))
403 }
404
405 pub fn push(&mut self, trit: <T::Slice as RawEncoding>::Trit) {
406 self.0.push(trit);
407 }
408
409 pub fn pop(&mut self) -> Option<<T::Slice as RawEncoding>::Trit> {
410 self.0.pop()
411 }
412
413 pub fn as_slice(&self) -> &Trits<T::Slice> {
414 unsafe { &*(self.0.as_slice() as *const T::Slice as *const Trits<T::Slice>) }
415 }
416
417 pub fn as_slice_mut(&mut self) -> &mut Trits<T::Slice> {
418 unsafe { &mut *(self.0.as_slice_mut() as *mut T::Slice as *mut Trits<T::Slice>) }
419 }
420}
421
422impl<T> TritBuf<T1B1Buf<T>>
423where
424 T: Trit,
425 T::Target: Trit,
426{
427 pub fn into_shifted(self) -> TritBuf<T1B1Buf<<T as ShiftTernary>::Target>> {
428 TritBuf(self.0.into_shifted())
429 }
430}
431
432impl<T: RawEncodingBuf, U: RawEncodingBuf> PartialEq<TritBuf<U>> for TritBuf<T>
433where
434 T::Slice: RawEncoding,
435 U::Slice: RawEncoding<Trit = <T::Slice as RawEncoding>::Trit>,
436{
437 fn eq(&self, other: &TritBuf<U>) -> bool {
438 self.as_slice() == other.as_slice()
439 }
440}
441
442impl<T: RawEncodingBuf> Deref for TritBuf<T> {
443 type Target = Trits<T::Slice>;
444
445 fn deref(&self) -> &Self::Target {
446 self.as_slice()
447 }
448}
449
450impl<T: RawEncodingBuf> DerefMut for TritBuf<T> {
451 fn deref_mut(&mut self) -> &mut Self::Target {
452 self.as_slice_mut()
453 }
454}
455
456impl<T: RawEncodingBuf> FromIterator<<T::Slice as RawEncoding>::Trit> for TritBuf<T> {
457 fn from_iter<I: IntoIterator<Item = <T::Slice as RawEncoding>::Trit>>(iter: I) -> Self {
458 let iter = iter.into_iter();
459 let mut this = Self::with_capacity(iter.size_hint().0);
460 for trit in iter {
461 this.push(trit);
462 }
463 this
464 }
465}
466
467impl<T> hash::Hash for TritBuf<T>
468where
469 T: RawEncodingBuf,
470 T::Slice: hash::Hash,
471{
472 fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
473 (**self).hash(hasher)
474 }
475}
476
477impl<T: RawEncodingBuf> Index<Range<usize>> for TritBuf<T> {
478 type Output = Trits<T::Slice>;
479
480 fn index(&self, range: Range<usize>) -> &Self::Output {
481 self.slice(range)
482 }
483}
484
485impl<T: RawEncodingBuf> IndexMut<Range<usize>> for TritBuf<T> {
486 fn index_mut(&mut self, range: Range<usize>) -> &mut Self::Output {
487 self.slice_mut(range)
488 }
489}
490
491impl<T: RawEncodingBuf> fmt::Debug for TritBuf<T> {
492 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
493 write!(f, "TritBuf<{}> [", any::type_name::<T>())?;
494 for (i, trit) in self.trits().enumerate() {
495 if i != 0 {
496 write!(f, ", ")?;
497 }
498 write!(f, "{:?}", trit)?;
499 }
500 write!(f, "]")
501 }
502}
503
504impl<T: RawEncodingBuf> Borrow<Trits<T::Slice>> for TritBuf<T> {
505 fn borrow(&self) -> &Trits<T::Slice> {
506 self.as_slice()
507 }
508}
509
510impl<T: RawEncodingBuf> BorrowMut<Trits<T::Slice>> for TritBuf<T> {
511 fn borrow_mut(&mut self) -> &mut Trits<T::Slice> {
512 self.as_slice_mut()
513 }
514}