crypto/encoding/ternary/
raw.rs

1// Copyright 2020-2021 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use core::ops::Range;
5
6use crate::encoding::ternary::{Trit, TritBuf};
7
8/// A trait to be implemented by alternative trit encoding scheme slices.
9#[allow(clippy::len_without_is_empty)]
10#[allow(clippy::missing_safety_doc)]
11pub trait RawEncoding {
12    /// The type of trit associated with this trit encoding.
13    type Trit: Trit;
14
15    /// The trit buffer encoding associated with this trit slice encoding.
16    type Buf: RawEncodingBuf<Slice = Self>;
17
18    /// The number of trits that fit into this trit slice encoding.
19    const TRITS_PER_BYTE: usize;
20
21    /// Get an empty slice of this encoding
22    fn empty() -> &'static Self;
23
24    /// Get the number of trits in this buffer
25    fn len(&self) -> usize;
26
27    /// Interpret the raw data of this encoding as a slice of [`i8`].
28    fn as_i8_slice(&self) -> &[i8];
29
30    /// Interpret the raw data of this encoding as a mutable slice of [`i8`].
31    unsafe fn as_i8_slice_mut(&mut self) -> &mut [i8];
32
33    /// Get the trit at the given index
34    unsafe fn get_unchecked(&self, index: usize) -> Self::Trit;
35
36    /// Set the trit at the given index
37    unsafe fn set_unchecked(&mut self, index: usize, trit: Self::Trit);
38
39    /// Get a slice of this slice
40    unsafe fn slice_unchecked(&self, range: Range<usize>) -> &Self;
41
42    /// Get a mutable slice of this slice
43    unsafe fn slice_unchecked_mut(&mut self, range: Range<usize>) -> &mut Self;
44
45    /// Decide whether a byte is a valid series of trits in this encoding
46    fn is_valid(repr: i8) -> bool;
47
48    /// Unsafely reinterpret a slice of bytes as trit slice
49    unsafe fn from_raw_unchecked(b: &[i8], num_trits: usize) -> &Self;
50
51    /// Unsafely reinterpret a slice of bytes as trit slice
52    unsafe fn from_raw_unchecked_mut(b: &mut [i8], num_trits: usize) -> &mut Self;
53}
54
55/// A trait to be implemented by alternative trit encoding scheme buffers.
56pub trait RawEncodingBuf {
57    /// The trit slice encoding associated with this trit buffer encoding.
58    type Slice: RawEncoding + ?Sized;
59
60    /// Create a new empty buffer.
61    fn new() -> Self
62    where
63        Self: Sized;
64
65    /// Create a new empty buffer with a given capacity.
66    fn with_capacity(cap: usize) -> Self
67    where
68        Self: Sized;
69
70    /// Create a new buffer containing the given trits.
71    fn from_trits(trits: &[<Self::Slice as RawEncoding>::Trit]) -> Self
72    where
73        Self: Sized,
74    {
75        let mut this = Self::new();
76        for trit in trits {
77            this.push(*trit);
78        }
79        this
80    }
81
82    /// Clears the buffer, removing all values.
83    /// Note that this method has no effect on the allocated capacity of the buffer.
84    fn clear(&mut self);
85
86    /// Push a trit to the back of this buffer.
87    fn push(&mut self, trit: <Self::Slice as RawEncoding>::Trit);
88
89    /// Pop a trit from the back of this buffer.
90    fn pop(&mut self) -> Option<<Self::Slice as RawEncoding>::Trit>;
91
92    /// View the trits in this buffer as a slice.
93    fn as_slice(&self) -> &Self::Slice;
94
95    /// View the trits in this buffer as a mutable slice.
96    fn as_slice_mut(&mut self) -> &mut Self::Slice;
97
98    /// Returns the number of trits the buffer can hold.
99    fn capacity(&self) -> usize;
100
101    /// Convert this encoding into another encoding.
102    /// TODO: Rename this `reencode`
103    #[allow(clippy::wrong_self_convention)]
104    fn into_encoding<T>(this: TritBuf<Self>) -> TritBuf<T>
105    where
106        Self: Sized,
107        T: RawEncodingBuf,
108        T::Slice: RawEncoding<Trit = <Self::Slice as RawEncoding>::Trit>,
109    {
110        this.iter().collect()
111    }
112}