use alloc::string::ToString;
use super::{
AccountId, ByteReader, ByteWriter, Deserializable, DeserializationError, Felt, NoteError,
NoteTag, NoteType, Serializable, Word,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct NoteMetadata {
sender: AccountId,
note_type: NoteType,
tag: NoteTag,
aux: Felt,
}
impl NoteMetadata {
pub fn new(
sender: AccountId,
note_type: NoteType,
tag: NoteTag,
aux: Felt,
) -> Result<Self, NoteError> {
let tag = tag.validate(note_type)?;
Ok(Self { sender, note_type, tag, aux })
}
pub fn sender(&self) -> AccountId {
self.sender
}
pub fn note_type(&self) -> NoteType {
self.note_type
}
pub fn tag(&self) -> NoteTag {
self.tag
}
pub fn aux(&self) -> Felt {
self.aux
}
pub fn is_offchain(&self) -> bool {
self.note_type == NoteType::OffChain
}
}
impl From<NoteMetadata> for Word {
fn from(metadata: NoteMetadata) -> Self {
(&metadata).into()
}
}
impl From<&NoteMetadata> for Word {
fn from(metadata: &NoteMetadata) -> Self {
let mut elements = Word::default();
elements[0] = metadata.tag.inner().into();
elements[1] = metadata.sender.into();
elements[2] = metadata.note_type.into();
elements[3] = metadata.aux;
elements
}
}
impl TryFrom<Word> for NoteMetadata {
type Error = NoteError;
fn try_from(elements: Word) -> Result<Self, Self::Error> {
let sender = elements[1].try_into().map_err(NoteError::InvalidNoteSender)?;
let note_type = elements[2].try_into()?;
let tag: u64 = elements[0].into();
let tag: u32 =
tag.try_into().map_err(|_| NoteError::InconsistentNoteTag(note_type, tag))?;
Self::new(sender, note_type, tag.into(), elements[3])
}
}
impl Serializable for NoteMetadata {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
self.sender.write_into(target);
self.note_type.write_into(target);
self.tag.write_into(target);
self.aux.write_into(target);
}
}
impl Deserializable for NoteMetadata {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let sender = AccountId::read_from(source)?;
let note_type = NoteType::read_from(source)?;
let tag = NoteTag::read_from(source)?;
let aux = Felt::read_from(source)?;
Self::new(sender, note_type, tag, aux)
.map_err(|err| DeserializationError::InvalidValue(err.to_string()))
}
}