Skip to main content

distrib_ruby/
gemspec.rs

1// This is free and unencumbered software released into the public domain.
2
3use alloc::{collections::BTreeMap, string::String, vec::Vec};
4
5pub type Gemspec = Specification;
6
7/// The package information for a gem, typically defined in a `.gemspec` file.
8///
9/// This is the tag `!ruby/object:Gem::Specification` in YAML.
10///
11/// Note that we (pedantically) distinguish between `Option<Vec<T>` and
12/// `Vec<T>` so as to indicate whether the property was unset or set to empty
13/// the input specification file.
14///
15/// See: <https://guides.rubygems.org/specification-reference/>
16#[cfg_attr(feature = "serde", serde_with::serde_as)]
17#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
18#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
19#[cfg_attr(feature = "serde", serde(default, tag = "@type"))]
20pub struct Specification<T = Metadata> {
21    /// See: <https://guides.rubygems.org/specification-reference/#authors=>
22    #[cfg_attr(feature = "serde", serde(alias = "author"))]
23    #[cfg_attr(feature = "serde", serde_as(as = "OneOrMany<_, PreferMany>"))]
24    pub authors: Vec<String>,
25
26    /// See: <https://guides.rubygems.org/specification-reference/#bindir>
27    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
28    pub bindir: Option<String>,
29
30    /// See: <https://guides.rubygems.org/specification-reference/#cert_chain>
31    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
32    pub cert_chain: Option<Vec<String>>,
33
34    /// See: <https://guides.rubygems.org/specification-reference/#add_dependency>
35    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
36    pub dependencies: Option<Vec<Dependency>>,
37
38    /// See: <https://guides.rubygems.org/specification-reference/#description>
39    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
40    pub description: Option<String>,
41
42    /// See: <https://guides.rubygems.org/specification-reference/#email>
43    #[cfg_attr(
44        feature = "serde",
45        serde(alias = "emails", skip_serializing_if = "Vec::is_empty")
46    )]
47    #[cfg_attr(feature = "serde", serde_as(as = "OneOrMany<_, PreferOne>"))]
48    pub email: Vec<String>, // TODO: Option<Vec<String>>
49
50    /// See: <https://guides.rubygems.org/specification-reference/#executables>
51    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
52    pub executables: Option<Vec<String>>,
53
54    /// See: <https://guides.rubygems.org/specification-reference/#extensions>
55    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
56    pub extensions: Option<Vec<String>>,
57
58    /// See: <https://guides.rubygems.org/specification-reference/#extensions_dir>
59    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
60    pub extensions_dir: Option<String>,
61
62    /// See: <https://guides.rubygems.org/specification-reference/#extra_rdoc_files>
63    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
64    pub extra_rdoc_files: Option<Vec<String>>,
65
66    /// See: <https://guides.rubygems.org/specification-reference/#files>
67    pub files: Vec<String>,
68
69    /// See: <https://guides.rubygems.org/specification-reference/#homepage>
70    pub homepage: Option<String>,
71
72    /// See: <https://guides.rubygems.org/specification-reference/#licenses=>
73    #[cfg_attr(
74        feature = "serde",
75        serde(alias = "license", skip_serializing_if = "Vec::is_empty")
76    )]
77    #[cfg_attr(feature = "serde", serde_as(as = "OneOrMany<_, PreferMany>"))]
78    pub licenses: Vec<String>, // TODO: Option<Vec<String>>
79
80    /// See: <https://guides.rubygems.org/specification-reference/#metadata>
81    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
82    pub metadata: Option<T>,
83
84    /// See: <https://guides.rubygems.org/specification-reference/#name>
85    pub name: String,
86
87    /// See: <https://guides.rubygems.org/specification-reference/#platform=>
88    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
89    pub platform: Option<Platform>,
90
91    /// See: <https://guides.rubygems.org/specification-reference/#post_install_message>
92    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
93    pub post_install_message: Option<String>,
94
95    /// See: <https://guides.rubygems.org/specification-reference/#rdoc_options>
96    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
97    pub rdoc_options: Option<Vec<String>>,
98
99    /// See: <https://guides.rubygems.org/specification-reference/#require_paths=>
100    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
101    pub require_paths: Option<Vec<String>>,
102
103    /// See: <https://guides.rubygems.org/specification-reference/#required_ruby_version>
104    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
105    pub required_ruby_version: Option<Requirement>,
106
107    /// See: <https://guides.rubygems.org/specification-reference/#required_rubygems_version>
108    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
109    pub required_rubygems_version: Option<Requirement>,
110
111    /// See: <https://guides.rubygems.org/specification-reference/#requirements>
112    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
113    pub requirements: Option<Vec<String>>,
114
115    /// See: <https://guides.rubygems.org/specification-reference/#rubygems_version>
116    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
117    pub rubygems_version: Option<String>,
118
119    /// See: <https://guides.rubygems.org/specification-reference/#signing_key>
120    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
121    pub signing_key: Option<String>,
122
123    /// See: <https://guides.rubygems.org/specification-reference/#summary>
124    pub summary: String,
125
126    /// See: <https://guides.rubygems.org/specification-reference/#version>
127    pub version: Version,
128}
129
130/// !ruby/object:Gem::Dependency
131#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
132#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
133#[cfg_attr(feature = "serde", serde(default))]
134pub struct Dependency {
135    pub name: String,
136    pub requirement: Requirement,
137    pub r#type: String,
138    pub prerelease: bool,
139    pub version_requirements: Requirement,
140}
141
142/// `!ruby/object:Gem::Requirement`
143#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
144#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
145#[cfg_attr(feature = "serde", serde(default))]
146pub struct Requirement {
147    pub requirements: Vec<(String, Version)>,
148}
149
150/// `!ruby/object:Gem::Version`
151#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
152#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
153#[cfg_attr(feature = "serde", serde(default))]
154pub struct Version {
155    pub version: String,
156}
157
158#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
159#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
160#[cfg_attr(
161    feature = "serde",
162    serde(rename_all(serialize = "lowercase", deserialize = "lowercase"))
163)]
164pub enum Platform {
165    #[default]
166    Ruby,
167    Current,
168    #[cfg_attr(feature = "serde", serde(untagged))]
169    Other(String),
170}
171
172/// See: <https://guides.rubygems.org/specification-reference/#metadata>
173#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
174#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
175#[cfg_attr(feature = "serde", serde(default))]
176pub struct Metadata {
177    /// See: <https://guides.rubygems.org/specification-reference/#metadata>
178    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
179    pub bug_tracker_uri: Option<String>,
180
181    /// See: <https://guides.rubygems.org/specification-reference/#metadata>
182    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
183    pub changelog_uri: Option<String>,
184
185    /// See: <https://guides.rubygems.org/specification-reference/#metadata>
186    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
187    pub documentation_uri: Option<String>,
188
189    /// See: <https://guides.rubygems.org/specification-reference/#metadata>
190    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
191    pub funding_uri: Option<String>,
192
193    /// See: <https://guides.rubygems.org/specification-reference/#metadata>
194    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
195    pub homepage_uri: Option<String>,
196
197    /// See: <https://guides.rubygems.org/specification-reference/#metadata>
198    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
199    pub mailing_list_uri: Option<String>,
200
201    /// See: <https://guides.rubygems.org/specification-reference/#metadata>
202    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
203    pub source_code_uri: Option<String>,
204
205    /// See: <https://guides.rubygems.org/specification-reference/#metadata>
206    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
207    pub wiki_uri: Option<String>,
208
209    #[cfg_attr(
210        feature = "serde",
211        serde(flatten, skip_serializing_if = "serde_json::Map::is_empty")
212    )]
213    pub other: serde_json::Map<String, serde_json::Value>,
214}