diff --git a/src/lib.rs b/src/lib.rs index 89977ef..18c70af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,7 @@ use subtle::{Choice, ConstantTimeEq}; #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] pub mod batch; +pub mod note_bytes; /// The size of the memo. pub const MEMO_SIZE: usize = 512; diff --git a/src/note_bytes.rs b/src/note_bytes.rs new file mode 100644 index 0000000..38d1153 --- /dev/null +++ b/src/note_bytes.rs @@ -0,0 +1,66 @@ +/// Represents a fixed-size array of bytes for note components. +#[derive(Clone, Copy, Debug)] +pub struct NoteBytesData(pub [u8; N]); + +impl AsRef<[u8]> for NoteBytesData { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl AsMut<[u8]> for NoteBytesData { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0 + } +} + +impl From<&[u8]> for NoteBytesData { + fn from(s: &[u8]) -> Self { + Self(s.try_into().unwrap()) + } +} + +impl From<(&[u8], &[u8])> for NoteBytesData { + fn from(s: (&[u8], &[u8])) -> Self { + let mut result: [u8; N] = [0; N]; + result[..s.0.len()].copy_from_slice(s.0); + result[s.0.len()..].copy_from_slice(s.1); + NoteBytesData::from(result.as_ref()) + } +} + +/// Defines the ability to concatenate two byte slices. +pub trait NoteByteConcat: for<'a> From<(&'a [u8], &'a [u8])> {} + +impl NoteByteConcat for NoteBytesData {} + +/// Defines the behavior for types that can provide read-only access to their internal byte array. +pub trait NoteByteReader: AsRef<[u8]> + for<'a> From<&'a [u8]> + Clone + Copy {} + +impl NoteByteReader for NoteBytesData {} + +/// Defines the behavior for types that support both read and write access to their internal byte array. +pub trait NoteByteWriter: NoteByteReader + AsMut<[u8]> {} + +impl NoteByteWriter for NoteBytesData {} + +/// Provides a unified interface for handling fixed-size byte arrays used in Orchard note encryption. +pub trait NoteBytes: + AsRef<[u8]> + + AsMut<[u8]> + + for<'a> From<&'a [u8]> + + for<'a> From<(&'a [u8], &'a [u8])> + + Clone + + Copy + + Send +{ + /// Constructs a new NoteBytesData from an empty slice of bytes. + fn new() -> Self; +} + +impl NoteBytes for NoteBytesData { + /// Constructs a new NoteBytesData from an empty slice of bytes. + fn new() -> Self { + Self([0u8; N]) + } +}