Skip to main content

miden_project/
linkage.rs

1use alloc::string::{String, ToString};
2use core::{fmt, str::FromStr};
3
4#[cfg(all(feature = "arbitrary", feature = "serde", test))]
5use miden_core::serde::{Deserializable, Serializable};
6
7/// This represents the way in which a dependent will link against a dependency during assembly.
8#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
9#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
10#[cfg_attr(
11    all(feature = "arbitrary", feature = "serde", test),
12    miden_test_serde_macros::serde_test(binary_serde(true))
13)]
14#[repr(u8)]
15pub enum Linkage {
16    /// Link against the target package dynamically, i.e. it is expected that the package will be
17    /// provided to the VM at runtime so that it is available for the dependent.
18    #[default]
19    Dynamic = 0,
20    /// Link the contents of the target package into the dependent package, as if they were defined
21    /// as part of the dependent.
22    ///
23    /// This linkage mode ensures that the dependency does not have to be provided to the VM
24    /// separately in order to execute code from the dependent.
25    Static,
26}
27
28impl Linkage {
29    /// Get the string representation of this linkage
30    pub const fn as_str(&self) -> &'static str {
31        match self {
32            Self::Dynamic => "dynamic",
33            Self::Static => "static",
34        }
35    }
36}
37
38impl fmt::Display for Linkage {
39    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40        f.write_str(self.as_str())
41    }
42}
43
44/// The error produced when parsing [Linkage] from a string value
45#[derive(Debug, thiserror::Error)]
46#[error("unknown linkage '{0}': expected either 'dynamic' or 'static'")]
47pub struct UnknownLinkageError(String);
48
49impl FromStr for Linkage {
50    type Err = UnknownLinkageError;
51
52    fn from_str(s: &str) -> Result<Self, Self::Err> {
53        match s {
54            "default" | "dynamic" => Ok(Self::Dynamic),
55            "static" => Ok(Self::Static),
56            other => Err(UnknownLinkageError(other.to_string())),
57        }
58    }
59}
60
61#[cfg(feature = "serde")]
62mod serialization {
63    use alloc::format;
64
65    use miden_core::serde::{
66        ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
67    };
68
69    use super::Linkage;
70
71    impl serde::Serialize for Linkage {
72        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
73        where
74            S: serde::Serializer,
75        {
76            if serializer.is_human_readable() {
77                self.as_str().serialize(serializer)
78            } else {
79                (*self as u8).serialize(serializer)
80            }
81        }
82    }
83
84    impl<'de> serde::Deserialize<'de> for Linkage {
85        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
86        where
87            D: serde::Deserializer<'de>,
88        {
89            if deserializer.is_human_readable() {
90                <&'de str>::deserialize(deserializer)?
91                    .parse::<Linkage>()
92                    .map_err(serde::de::Error::custom)
93            } else {
94                match u8::deserialize(deserializer)? {
95                    0 => Ok(Self::Dynamic),
96                    1 => Ok(Self::Static),
97                    other => {
98                        Err(serde::de::Error::custom(format!("invalid Linkage tag '{other}'")))
99                    },
100                }
101            }
102        }
103    }
104
105    impl Serializable for Linkage {
106        fn write_into<W: ByteWriter>(&self, target: &mut W) {
107            target.write_u8(*self as u8);
108        }
109    }
110
111    impl Deserializable for Linkage {
112        fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
113            match source.read_u8()? {
114                0 => Ok(Self::Dynamic),
115                1 => Ok(Self::Static),
116                other => Err(DeserializationError::InvalidValue(format!(
117                    "unknown Linkage tag '{other}'"
118                ))),
119            }
120        }
121    }
122}