Skip to main content

miden_mast_package/package/
id.rs

1use alloc::{string::ToString, sync::Arc};
2use core::{borrow::Borrow, fmt, ops::Deref};
3
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7/// A type that represents the unique identifier for packages in a registry.
8///
9/// This is a simple newtype wrapper around an [`Arc<str>`] so that we can provide some ergonomic
10/// conveniences, and allow migration to some other type in the future with minimal downstream
11/// impact, if any.
12#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14#[cfg_attr(feature = "serde", serde(transparent))]
15#[repr(transparent)]
16pub struct PackageId(Arc<str>);
17
18impl PackageId {
19    #[inline(always)]
20    pub fn into_inner(self) -> Arc<str> {
21        self.0
22    }
23}
24
25impl PartialEq<str> for PackageId {
26    fn eq(&self, other: &str) -> bool {
27        self.0.as_ref() == other
28    }
29}
30
31impl Borrow<str> for PackageId {
32    fn borrow(&self) -> &str {
33        &self.0
34    }
35}
36
37impl Borrow<Arc<str>> for PackageId {
38    fn borrow(&self) -> &Arc<str> {
39        &self.0
40    }
41}
42
43impl fmt::Display for PackageId {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        fmt::Display::fmt(&self.0, f)
46    }
47}
48
49impl AsRef<str> for PackageId {
50    #[inline(always)]
51    fn as_ref(&self) -> &str {
52        self.0.as_ref()
53    }
54}
55
56impl AsRef<Arc<str>> for PackageId {
57    #[inline(always)]
58    fn as_ref(&self) -> &Arc<str> {
59        &self.0
60    }
61}
62
63impl Deref for PackageId {
64    type Target = str;
65
66    #[inline(always)]
67    fn deref(&self) -> &Self::Target {
68        self.0.as_ref()
69    }
70}
71
72impl From<Arc<str>> for PackageId {
73    fn from(value: Arc<str>) -> Self {
74        Self(value)
75    }
76}
77
78impl From<&str> for PackageId {
79    fn from(value: &str) -> Self {
80        Self(value.to_string().into_boxed_str().into())
81    }
82}
83
84impl From<alloc::string::String> for PackageId {
85    fn from(value: alloc::string::String) -> Self {
86        Self(value.into_boxed_str().into())
87    }
88}
89
90#[cfg(feature = "arbitrary")]
91impl proptest::arbitrary::Arbitrary for PackageId {
92    type Parameters = ();
93    type Strategy = proptest::prelude::BoxedStrategy<Self>;
94    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
95        use alloc::string::String;
96
97        use proptest::prelude::Strategy;
98
99        let chars = proptest::char::range('a', 'z');
100        proptest::collection::vec(chars, 4..32)
101            .prop_map(|chars| Self(String::from_iter(chars).into_boxed_str().into()))
102            .no_shrink()  // Pure random strings, no meaningful shrinking pattern
103            .boxed()
104    }
105}
106
107mod serialization {
108    use miden_core::serde::*;
109
110    use super::PackageId;
111
112    impl Serializable for PackageId {
113        fn write_into<W: ByteWriter>(&self, target: &mut W) {
114            // This is equivalent to String::write_into
115            target.write_usize(self.0.len());
116            target.write_bytes(self.0.as_bytes());
117        }
118    }
119
120    impl Deserializable for PackageId {
121        fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
122            alloc::string::String::read_from(source).map(Self::from)
123        }
124    }
125}