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