extern crate alloc;
use miden_field_repr::FromFeltRepr;
use miden_stdlib_sys::{Felt, Word, felt};
pub fn padded_word_from_felt(value: Felt) -> Word {
Word::new([value, felt!(0), felt!(0), felt!(0)])
}
pub fn felt_from_padded_word(value: Word) -> Result<Felt, &'static str> {
if value[1] != felt!(0) || value[2] != felt!(0) || value[3] != felt!(0) {
return Err("expected zero padding in the trailing three felts");
}
Ok(value[0])
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromFeltRepr)]
pub struct AccountId {
pub prefix: Felt,
pub suffix: Felt,
}
impl AccountId {
pub fn new(prefix: Felt, suffix: Felt) -> Self {
Self { prefix, suffix }
}
}
#[derive(Copy, Clone)]
#[repr(C)]
pub(crate) struct RawAccountId {
pub suffix: Felt,
pub prefix: Felt,
}
impl RawAccountId {
pub(crate) fn into_account_id(self) -> AccountId {
AccountId::new(self.prefix, self.suffix)
}
}
impl From<AccountId> for Word {
#[inline]
fn from(value: AccountId) -> Self {
Word::from([felt!(0), felt!(0), value.suffix, value.prefix])
}
}
impl TryFrom<Word> for AccountId {
type Error = &'static str;
#[inline]
fn try_from(value: Word) -> Result<Self, Self::Error> {
if value[0] != felt!(0) || value[1] != felt!(0) {
return Err("expected zero padding in the upper two felts");
}
Ok(Self {
prefix: value[3],
suffix: value[2],
})
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct Asset {
pub key: Word,
pub value: Word,
}
impl Asset {
pub fn new(key: impl Into<Word>, value: impl Into<Word>) -> Self {
Self {
key: key.into(),
value: value.into(),
}
}
}
impl From<Asset> for (Word, Word) {
fn from(val: Asset) -> Self {
(val.key, val.value)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct Recipient {
pub inner: Word,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct NoteMetadata {
pub attachment: Word,
pub header: Word,
}
impl NoteMetadata {
pub fn new(attachment: Word, header: Word) -> Self {
Self { attachment, header }
}
}
impl From<[Felt; 4]> for Recipient {
fn from(value: [Felt; 4]) -> Self {
Recipient {
inner: Word::from(value),
}
}
}
impl From<Word> for Recipient {
fn from(value: Word) -> Self {
Recipient { inner: value }
}
}
impl From<Recipient> for Word {
#[inline]
fn from(value: Recipient) -> Self {
value.inner
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct Tag {
pub inner: Felt,
}
impl From<Felt> for Tag {
fn from(value: Felt) -> Self {
Tag { inner: value }
}
}
impl From<Tag> for Word {
#[inline]
fn from(value: Tag) -> Self {
padded_word_from_felt(value.inner)
}
}
impl TryFrom<Word> for Tag {
type Error = &'static str;
#[inline]
fn try_from(value: Word) -> Result<Self, Self::Error> {
Ok(Tag {
inner: felt_from_padded_word(value)?,
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct NoteIdx {
pub inner: Felt,
}
impl From<NoteIdx> for Word {
#[inline]
fn from(value: NoteIdx) -> Self {
padded_word_from_felt(value.inner)
}
}
impl TryFrom<Word> for NoteIdx {
type Error = &'static str;
#[inline]
fn try_from(value: Word) -> Result<Self, Self::Error> {
Ok(NoteIdx {
inner: felt_from_padded_word(value)?,
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(transparent)]
pub struct NoteType {
pub inner: Felt,
}
impl From<Felt> for NoteType {
fn from(value: Felt) -> Self {
NoteType { inner: value }
}
}
impl From<NoteType> for Word {
#[inline]
fn from(value: NoteType) -> Self {
padded_word_from_felt(value.inner)
}
}
impl TryFrom<Word> for NoteType {
type Error = &'static str;
#[inline]
fn try_from(value: Word) -> Result<Self, Self::Error> {
Ok(NoteType {
inner: felt_from_padded_word(value)?,
})
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct StorageSlotId {
suffix: Felt,
prefix: Felt,
}
impl StorageSlotId {
pub fn new(suffix: Felt, prefix: Felt) -> Self {
Self { suffix, prefix }
}
pub fn from_prefix_suffix(prefix: Felt, suffix: Felt) -> Self {
Self { suffix, prefix }
}
pub fn to_prefix_suffix(&self) -> (Felt, Felt) {
(self.prefix, self.suffix)
}
pub fn to_suffix_prefix(&self) -> (Felt, Felt) {
(self.suffix, self.prefix)
}
pub fn suffix(&self) -> Felt {
self.suffix
}
pub fn prefix(&self) -> Felt {
self.prefix
}
}
#[cfg(test)]
mod tests {
use miden_stdlib_sys::{Word, felt};
use super::{felt_from_padded_word, padded_word_from_felt};
#[test]
fn padded_word_from_felt_zero_pads_trailing_limbs() {
assert_eq!(
padded_word_from_felt(felt!(7)),
Word::new([felt!(7), felt!(0), felt!(0), felt!(0)])
);
}
#[test]
fn felt_from_padded_word_rejects_non_zero_padding() {
let err =
felt_from_padded_word(Word::new([felt!(7), felt!(1), felt!(0), felt!(0)])).unwrap_err();
assert_eq!(err, "expected zero padding in the trailing three felts");
}
#[test]
fn felt_padding_helpers_roundtrip() {
let value = felt!(42);
assert_eq!(felt_from_padded_word(padded_word_from_felt(value)), Ok(value));
}
}