morphir_core/ir/v4/
distribution.rs1use indexmap::IndexMap;
7use serde::ser::{SerializeMap, Serializer};
8use serde::{Deserialize, Serialize};
9
10use super::package::{PackageDefinition, PackageSpecification};
11use crate::naming::PackageName;
12
13#[derive(Debug, Clone, PartialEq)]
20pub enum Distribution {
21 Library(LibraryContent),
22 Specs(SpecsContent),
23 Application(ApplicationContent),
24}
25
26impl Distribution {
27 pub fn package_name(&self) -> &PackageName {
29 match self {
30 Distribution::Library(content) => &content.package_name,
31 Distribution::Specs(content) => &content.package_name,
32 Distribution::Application(content) => &content.package_name,
33 }
34 }
35}
36
37impl Serialize for Distribution {
38 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
39 where
40 S: Serializer,
41 {
42 let mut map = serializer.serialize_map(Some(1))?;
43 match self {
44 Distribution::Library(content) => {
45 map.serialize_entry("Library", content)?;
46 }
47 Distribution::Specs(content) => {
48 map.serialize_entry("Specs", content)?;
49 }
50 Distribution::Application(content) => {
51 map.serialize_entry("Application", content)?;
52 }
53 }
54 map.end()
55 }
56}
57
58impl<'de> Deserialize<'de> for Distribution {
59 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60 where
61 D: serde::Deserializer<'de>,
62 {
63 super::serde_document::deserialize_standalone_with(
64 deserializer,
65 super::serde_document::decode_distribution,
66 )
67 }
68}
69
70#[derive(Debug, Clone, PartialEq, Serialize)]
72#[serde(rename_all = "camelCase")]
73pub struct LibraryContent {
74 pub package_name: PackageName,
75 pub dependencies: Dependencies,
76 pub def: PackageDefinition,
77}
78
79#[derive(Debug, Clone, PartialEq, Serialize)]
84#[serde(rename_all = "camelCase")]
85pub struct SpecsContent {
86 pub package_name: PackageName,
87 pub dependencies: Dependencies,
88 pub spec: PackageSpecification,
89}
90
91#[derive(Debug, Clone, PartialEq, Serialize)]
93#[serde(rename_all = "camelCase")]
94pub struct ApplicationContent {
95 pub package_name: PackageName,
96 pub dependencies: DefinitionDependencies,
97 pub def: PackageDefinition,
98 pub entry_points: EntryPoints,
99}
100
101pub type Dependencies = IndexMap<String, PackageSpecification>;
107
108pub type DefinitionDependencies = IndexMap<String, PackageDefinition>;
114
115pub type EntryPoints = IndexMap<String, EntryPoint>;
117
118#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
123#[serde(rename_all = "camelCase")]
124pub struct EntryPoint {
125 pub target: String,
127 pub kind: EntryPointKind,
128 #[serde(skip_serializing_if = "Option::is_none")]
129 pub doc: Option<String>,
130}
131
132#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
134#[serde(rename_all = "lowercase")]
135pub enum EntryPointKind {
136 Main,
137 Command,
138 Handler,
139 Job,
140 Policy,
141}
142
143impl EntryPointKind {
144 pub const ALL: &'static [EntryPointKind] = &[
146 EntryPointKind::Main,
147 EntryPointKind::Command,
148 EntryPointKind::Handler,
149 EntryPointKind::Job,
150 EntryPointKind::Policy,
151 ];
152
153 pub fn as_str(self) -> &'static str {
155 match self {
156 EntryPointKind::Main => "main",
157 EntryPointKind::Command => "command",
158 EntryPointKind::Handler => "handler",
159 EntryPointKind::Job => "job",
160 EntryPointKind::Policy => "policy",
161 }
162 }
163
164 pub fn parse(text: &str) -> Option<EntryPointKind> {
166 Self::ALL.iter().copied().find(|kind| kind.as_str() == text)
167 }
168}
169
170#[cfg(test)]
171mod tests {
172 use super::*;
173 use crate::naming::Path;
174
175 #[test]
176 fn test_distribution_library_serialization() {
177 let dist = Distribution::Library(LibraryContent {
178 package_name: PackageName::new(Path::new("my/pkg")),
179 dependencies: IndexMap::new(),
180 def: PackageDefinition {
181 modules: IndexMap::new(),
182 },
183 });
184 let json = serde_json::to_string(&dist).unwrap();
185 assert!(json.contains("\"Library\""));
186 assert!(json.contains("packageName"));
187 }
188}