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}