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