1use std::env;
25use std::fmt::{self, Display, Formatter};
26use std::str::FromStr;
27
28use amplify::confinement::TinyVec;
29use strict_encoding::{Ident, STRICT_TYPES_LIB};
30
31use crate::typelib::TypeLibId;
32use crate::SemId;
33
34#[derive(Clone, Eq, PartialEq, Debug, Display, Error)]
35#[display("unknown name for the file format '{0}'")]
36pub struct UnknownFormat(String);
37
38#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
39pub enum StlFormat {
40 #[display("sty")]
41 Source,
42 #[display("stl")]
43 Binary,
44 #[cfg(feature = "armor")]
45 #[display("sta")]
46 Armored,
47}
48
49impl FromStr for StlFormat {
50 type Err = UnknownFormat;
51
52 fn from_str(s: &str) -> Result<Self, Self::Err> {
53 match s {
54 "stl" => Ok(StlFormat::Binary),
55 #[cfg(feature = "armor")]
56 "sta" => Ok(StlFormat::Armored),
57 "sty" => Ok(StlFormat::Source),
58 invalid => Err(UnknownFormat(invalid.to_owned())),
59 }
60 }
61}
62
63pub fn parse_args() -> (StlFormat, Option<String>) {
64 let args: Vec<String> = env::args().collect();
65 let ext = args.get(1).map(String::as_str).map(|s| s.trim_start_matches("--")).unwrap_or("sty");
66 let format = StlFormat::from_str(ext).expect("unrecognized file format argument");
67 let dir = match args.len() {
68 1 => None,
69 2 | 3 => Some(args.get(2).cloned().unwrap_or_else(|| s!("stl"))),
70 _ => panic!("invalid argument count"),
71 };
72 (format, dir)
73}
74
75#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, From)]
130#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)]
131#[strict_type(lib = STRICT_TYPES_LIB, tags = order, dumb = { PreFragment::Digits(1) })]
132#[display(inner)]
133pub enum PreFragment {
134 #[from]
135 Ident(Ident),
136 #[from]
137 Digits(u128),
138}
139
140#[derive(Clone, Eq, PartialEq, Hash, Debug, Display)]
141#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)]
142#[strict_type(lib = STRICT_TYPES_LIB, tags = order, dumb = { BuildFragment::Ident(Ident::from("alpha")) })]
143#[display(inner)]
144pub enum BuildFragment {
145 Ident(Ident),
146 Digits(Ident),
147}
148
149#[derive(Clone, Eq, PartialEq, Hash, Debug)]
151#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)]
152#[strict_type(lib = STRICT_TYPES_LIB)]
153pub struct SemVer {
154 pub major: u16,
155 pub minor: u16,
156 pub patch: u16,
157 pub pre: TinyVec<PreFragment>,
158 pub build: TinyVec<BuildFragment>,
159}
160
161impl SemVer {
162 pub fn new(major: u16, minor: u16, patch: u16) -> Self {
163 SemVer {
164 major,
165 minor,
166 patch,
167 pre: none!(),
168 build: none!(),
169 }
170 }
171}
172
173impl Display for SemVer {
174 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
175 write!(f, "{}.{}.{}", self.major, self.minor, self.patch)?;
176
177 if !self.build.is_empty() {
178 f.write_str("-")?;
179 }
180 let mut len = self.build.len();
181 for item in &self.build {
182 Display::fmt(item, f)?;
183 len -= 1;
184 if len > 0 {
185 f.write_str(".")?;
186 }
187 }
188
189 if !self.pre.is_empty() {
190 f.write_str("+")?;
191 }
192 let mut len = self.pre.len();
193 for item in &self.pre {
194 Display::fmt(item, f)?;
195 len -= 1;
196 if len > 0 {
197 f.write_str(".")?;
198 }
199 }
200 Ok(())
201 }
202}
203
204#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)]
205pub enum Urn {
206 #[from]
207 #[display("urn:sten:lib:{0}", alt = "urn:sten:lib:{0:#}")]
208 Lib(TypeLibId),
209
210 #[from]
211 #[display("urn:sten:id:{0}", alt = "urn:sten:id:{0:#}")]
212 Type(SemId),
213}