bee_block/payload/milestone/option/receipt/
tail_transaction_hash.rs1use alloc::string::String;
5use core::fmt;
6
7use bee_ternary::{T5B1Buf, TritBuf, Trits, T5B1};
8use bytemuck::cast_slice;
9use packable::{
10 error::{UnpackError, UnpackErrorExt},
11 packer::Packer,
12 unpacker::Unpacker,
13 Packable,
14};
15
16use crate::Error;
17
18#[derive(Clone, Eq, PartialEq)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub struct TailTransactionHash(TritBuf<T5B1Buf>);
22
23impl TailTransactionHash {
24 pub const LENGTH: usize = 49;
26
27 pub fn new(bytes: [u8; TailTransactionHash::LENGTH]) -> Result<Self, Error> {
29 bytes.try_into()
30 }
31}
32
33impl TryFrom<[u8; TailTransactionHash::LENGTH]> for TailTransactionHash {
34 type Error = Error;
35
36 fn try_from(bytes: [u8; TailTransactionHash::LENGTH]) -> Result<Self, Error> {
37 Ok(TailTransactionHash(
38 Trits::<T5B1>::try_from_raw(cast_slice(&bytes), 243)
39 .map_err(|_| Error::InvalidTailTransactionHash)?
40 .to_buf(),
41 ))
42 }
43}
44
45impl AsRef<[u8]> for TailTransactionHash {
46 fn as_ref(&self) -> &[u8] {
47 cast_slice(self.0.as_slice().as_i8_slice())
48 }
49}
50
51impl fmt::Display for TailTransactionHash {
52 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53 write!(f, "{}", self.0.iter_trytes().map(char::from).collect::<String>())
54 }
55}
56
57impl fmt::Debug for TailTransactionHash {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59 write!(f, "TailTransactionHash({})", self)
60 }
61}
62
63impl Packable for TailTransactionHash {
64 type UnpackError = Error;
65 type UnpackVisitor = ();
66
67 fn pack<P: Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
68 packer.pack_bytes(self.as_ref())
69 }
70
71 fn unpack<U: Unpacker, const VERIFY: bool>(
72 unpacker: &mut U,
73 visitor: &Self::UnpackVisitor,
74 ) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
75 Self::new(<[u8; TailTransactionHash::LENGTH]>::unpack::<_, VERIFY>(unpacker, visitor).coerce()?)
76 .map_err(UnpackError::Packable)
77 }
78}