extern crate alloc;
use alloc::vec::Vec;
use core::{
fmt,
ops::{Deref, DerefMut},
str::FromStr,
};
use crate::{Btrit, Error, Trits, T3B1};
#[derive(Copy, Clone, Eq, Hash, PartialEq)]
#[repr(i8)]
#[allow(missing_docs)]
pub enum Tryte {
N = -13,
O = -12,
P = -11,
Q = -10,
R = -9,
S = -8,
T = -7,
U = -6,
V = -5,
W = -4,
X = -3,
Y = -2,
Z = -1,
Nine = 0,
A = 1,
B = 2,
C = 3,
D = 4,
E = 5,
F = 6,
G = 7,
H = 8,
I = 9,
J = 10,
K = 11,
L = 12,
M = 13,
}
impl Tryte {
pub const MIN_VALUE: Self = Tryte::N;
pub const MAX_VALUE: Self = Tryte::M;
pub fn from_trits(trits: [Btrit; 3]) -> Self {
let x = i8::from(trits[0]) + i8::from(trits[1]) * 3 + i8::from(trits[2]) * 9;
Tryte::try_from(x).unwrap()
}
pub fn as_trits(&self) -> &Trits<T3B1> {
unsafe { &*(T3B1::make(self as *const _ as *const _, 0, 3) as *const _) }
}
pub fn as_trits_mut(&mut self) -> &mut Trits<T3B1> {
unsafe { &mut *(T3B1::make(self as *const _ as *const _, 0, 3) as *mut _) }
}
}
impl From<Tryte> for char {
fn from(tryte: Tryte) -> char {
match tryte as i8 {
0 => '9',
-13..=-1 => (((tryte as i8 + 13) as u8) + b'N') as char,
1..=13 => (((tryte as i8 - 1) as u8) + b'A') as char,
x => unreachable!("Tried to decode Tryte with variant {}", x),
}
}
}
impl From<[Btrit; 3]> for Tryte {
fn from(trits: [Btrit; 3]) -> Self {
Self::from_trits(trits)
}
}
impl fmt::Debug for Tryte {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", char::from(*self))
}
}
impl fmt::Display for Tryte {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", char::from(*self))
}
}
impl TryFrom<char> for Tryte {
type Error = Error;
fn try_from(c: char) -> Result<Self, Self::Error> {
match c {
'9' => Ok(Tryte::Nine),
'N'..='Z' => Ok(unsafe { core::mem::transmute((c as u8 - b'N') as i8 - 13) }),
'A'..='M' => Ok(unsafe { core::mem::transmute((c as u8 - b'A') as i8 + 1) }),
_ => Err(Error::InvalidRepr),
}
}
}
impl TryFrom<i8> for Tryte {
type Error = Error;
fn try_from(x: i8) -> Result<Self, Self::Error> {
match x {
-13..=13 => Ok(unsafe { core::mem::transmute(x) }),
_ => Err(Error::InvalidRepr),
}
}
}
#[derive(Default)]
pub struct TryteBuf {
inner: Vec<Tryte>,
}
impl TryteBuf {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(cap: usize) -> Self {
Self {
inner: Vec::with_capacity(cap),
}
}
pub fn try_from_str(s: &str) -> Result<Self, Error> {
s.chars().map(Tryte::try_from).collect()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn push(&mut self, tryte: Tryte) {
self.inner.push(tryte);
}
pub fn pop(&mut self) -> Option<Tryte> {
self.inner.pop()
}
pub fn as_trits(&self) -> &Trits<T3B1> {
unsafe { &*(T3B1::make(self.as_ptr() as *const _, 0, self.len() * 3) as *const _) }
}
pub fn as_trits_mut(&mut self) -> &mut Trits<T3B1> {
unsafe { &mut *(T3B1::make(self.as_ptr() as *const _, 0, self.len() * 3) as *mut _) }
}
}
impl Deref for TryteBuf {
type Target = [Tryte];
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for TryteBuf {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl FromIterator<Tryte> for TryteBuf {
fn from_iter<I: IntoIterator<Item = Tryte>>(iter: I) -> Self {
let iter = iter.into_iter();
let mut this = Self::with_capacity(iter.size_hint().0);
for tryte in iter {
this.push(tryte);
}
this
}
}
impl<'a> From<&'a [Tryte]> for TryteBuf {
fn from(trytes: &'a [Tryte]) -> Self {
Self { inner: trytes.to_vec() }
}
}
impl FromStr for TryteBuf {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from_str(s)
}
}
impl fmt::Debug for TryteBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.inner)
}
}
impl fmt::Display for TryteBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for tryte in self.iter() {
write!(f, "{}", tryte)?;
}
Ok(())
}
}