Skip to main content

morphir_core/ir/classic/
package.rs

1use super::module::{ModuleEntry, ModuleSpecification};
2use super::naming::Path;
3use serde::de::{self, IgnoredAny, MapAccess, SeqAccess, Visitor};
4use serde::ser::{SerializeTuple, Serializer};
5use serde::{Deserialize, Deserializer, Serialize};
6use std::fmt;
7
8/// Package specification - contains a list of module specifications
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct PackageSpecification<A> {
11    pub modules: Vec<ModuleSpecEntry<A>>,
12}
13
14/// Module specification entry - [modulePath, ModuleSpecification]
15#[derive(Debug, Clone, PartialEq)]
16pub struct ModuleSpecEntry<A> {
17    pub path: Path,
18    pub specification: ModuleSpecification<A>,
19}
20
21impl<A: Serialize> Serialize for ModuleSpecEntry<A> {
22    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23    where
24        S: Serializer,
25    {
26        let mut tuple = serializer.serialize_tuple(2)?;
27        tuple.serialize_element(&self.path)?;
28        tuple.serialize_element(&self.specification)?;
29        tuple.end()
30    }
31}
32
33impl<'de, A: Deserialize<'de>> Deserialize<'de> for ModuleSpecEntry<A> {
34    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
35    where
36        D: Deserializer<'de>,
37    {
38        struct ModuleSpecEntryVisitor<A>(std::marker::PhantomData<A>);
39
40        impl<'de, A: Deserialize<'de>> Visitor<'de> for ModuleSpecEntryVisitor<A> {
41            type Value = ModuleSpecEntry<A>;
42
43            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
44                formatter.write_str("a ModuleSpecEntry array [path, specification]")
45            }
46
47            fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
48            where
49                V: SeqAccess<'de>,
50            {
51                let path = seq
52                    .next_element()?
53                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
54                let specification = seq
55                    .next_element()?
56                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
57
58                if let Some(IgnoredAny) = seq.next_element()? {
59                    return Err(de::Error::custom("Expected end of ModuleSpecEntry array"));
60                }
61
62                Ok(ModuleSpecEntry {
63                    path,
64                    specification,
65                })
66            }
67        }
68
69        deserializer.deserialize_seq(ModuleSpecEntryVisitor(std::marker::PhantomData))
70    }
71}
72
73/// The message a Specs distribution gives for a module member a specification does not hold.
74const SPECS_HOLD_SPECIFICATIONS: &str =
75    "a v3 Specs distribution holds module specifications, not definitions";
76
77/// One of a v3 `Specs` distribution's own modules, read strictly.
78///
79/// [`ModuleSpecEntry`] reads a specification leniently: `types` and `values` default to empty
80/// and unknown members are ignored, so a module definition (`{"access": …, "value": …}`) would
81/// read as an empty specification and lose its content. A `Specs` distribution's own modules are
82/// read through this type instead, which accepts only `types`, `values` and `doc`.
83/// Dependencies keep the lenient reading.
84#[derive(Debug, Clone, PartialEq)]
85pub struct SpecsModuleEntry<A>(pub ModuleSpecEntry<A>);
86
87impl<A> From<SpecsModuleEntry<A>> for ModuleSpecEntry<A> {
88    fn from(entry: SpecsModuleEntry<A>) -> Self {
89        entry.0
90    }
91}
92
93impl<'de, A: Deserialize<'de>> Deserialize<'de> for SpecsModuleEntry<A> {
94    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
95    where
96        D: Deserializer<'de>,
97    {
98        struct EntryVisitor<A>(std::marker::PhantomData<A>);
99
100        impl<'de, A: Deserialize<'de>> Visitor<'de> for EntryVisitor<A> {
101            type Value = SpecsModuleEntry<A>;
102
103            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
104                formatter.write_str("a Specs module array [path, specification]")
105            }
106
107            fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
108            where
109                V: SeqAccess<'de>,
110            {
111                let path = seq
112                    .next_element()?
113                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
114                let StrictModuleSpecification(specification) = seq
115                    .next_element()?
116                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
117                if let Some(IgnoredAny) = seq.next_element()? {
118                    return Err(de::Error::custom("Expected end of ModuleSpecEntry array"));
119                }
120                Ok(SpecsModuleEntry(ModuleSpecEntry {
121                    path,
122                    specification,
123                }))
124            }
125        }
126
127        deserializer.deserialize_seq(EntryVisitor(std::marker::PhantomData))
128    }
129}
130
131/// A [`ModuleSpecification`] that refuses every member but `types`, `values` and `doc`.
132struct StrictModuleSpecification<A>(ModuleSpecification<A>);
133
134impl<'de, A: Deserialize<'de>> Deserialize<'de> for StrictModuleSpecification<A> {
135    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
136    where
137        D: Deserializer<'de>,
138    {
139        struct SpecificationVisitor<A>(std::marker::PhantomData<A>);
140
141        impl<'de, A: Deserialize<'de>> Visitor<'de> for SpecificationVisitor<A> {
142            type Value = StrictModuleSpecification<A>;
143
144            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
145                formatter.write_str("a module specification object {types, values, doc}")
146            }
147
148            fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
149            where
150                M: MapAccess<'de>,
151            {
152                let mut types = None;
153                let mut values = None;
154                let mut doc = None;
155                while let Some(key) = map.next_key::<String>()? {
156                    match key.as_str() {
157                        "types" if types.is_none() => types = Some(map.next_value()?),
158                        "values" if values.is_none() => values = Some(map.next_value()?),
159                        "doc" if doc.is_none() => doc = Some(map.next_value()?),
160                        "types" | "values" | "doc" => {
161                            return Err(de::Error::custom(format!("duplicate field `{key}`")));
162                        }
163                        _ => {
164                            return Err(de::Error::custom(format!(
165                                "{SPECS_HOLD_SPECIFICATIONS}: unexpected member `{key}`"
166                            )));
167                        }
168                    }
169                }
170                Ok(StrictModuleSpecification(ModuleSpecification {
171                    types: types.unwrap_or_default(),
172                    values: values.unwrap_or_default(),
173                    doc: doc.flatten(),
174                }))
175            }
176        }
177
178        deserializer.deserialize_map(SpecificationVisitor(std::marker::PhantomData))
179    }
180}
181
182/// Package definition - contains a list of module entries (full implementation)
183#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
184pub struct PackageDefinition<TA, VA> {
185    pub modules: Vec<ModuleEntry<TA, VA>>,
186}