use std::env;
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use amplify::confinement::TinyVec;
use strict_encoding::{Ident, STRICT_TYPES_LIB};
use crate::typelib::TypeLibId;
use crate::SemId;
#[derive(Clone, Eq, PartialEq, Debug, Display, Error)]
#[display("unknown name for the file format '{0}'")]
pub struct UnknownFormat(String);
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
pub enum StlFormat {
#[display("sty")]
Source,
#[display("stl")]
Binary,
#[cfg(feature = "armor")]
#[display("sta")]
Armored,
}
impl FromStr for StlFormat {
type Err = UnknownFormat;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"stl" => Ok(StlFormat::Binary),
#[cfg(feature = "armor")]
"sta" => Ok(StlFormat::Armored),
"sty" => Ok(StlFormat::Source),
invalid => Err(UnknownFormat(invalid.to_owned())),
}
}
}
pub fn parse_args() -> (StlFormat, Option<String>) {
let args: Vec<String> = env::args().collect();
let ext = args.get(1).map(String::as_str).map(|s| s.trim_start_matches("--")).unwrap_or("sty");
let format = StlFormat::from_str(ext).expect("unrecognized file format argument");
let dir = match args.len() {
1 => None,
2 | 3 => Some(args.get(2).cloned().unwrap_or_else(|| s!("stl"))),
_ => panic!("invalid argument count"),
};
(format, dir)
}
#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, From)]
#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = STRICT_TYPES_LIB, tags = order, dumb = { PreFragment::Digits(1) })]
#[display(inner)]
pub enum PreFragment {
#[from]
Ident(Ident),
#[from]
Digits(u128),
}
#[derive(Clone, Eq, PartialEq, Hash, Debug, Display)]
#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = STRICT_TYPES_LIB, tags = order, dumb = { BuildFragment::Ident(Ident::from("alpha")) })]
#[display(inner)]
pub enum BuildFragment {
Ident(Ident),
Digits(Ident),
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
#[derive(StrictDumb, StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = STRICT_TYPES_LIB)]
pub struct SemVer {
pub major: u16,
pub minor: u16,
pub patch: u16,
pub pre: TinyVec<PreFragment>,
pub build: TinyVec<BuildFragment>,
}
impl SemVer {
pub fn new(major: u16, minor: u16, patch: u16) -> Self {
SemVer {
major,
minor,
patch,
pre: none!(),
build: none!(),
}
}
}
impl Display for SemVer {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}.{}.{}", self.major, self.minor, self.patch)?;
if !self.build.is_empty() {
f.write_str("-")?;
}
let mut len = self.build.len();
for item in &self.build {
Display::fmt(item, f)?;
len -= 1;
if len > 0 {
f.write_str(".")?;
}
}
if !self.pre.is_empty() {
f.write_str("+")?;
}
let mut len = self.pre.len();
for item in &self.pre {
Display::fmt(item, f)?;
len -= 1;
if len > 0 {
f.write_str(".")?;
}
}
Ok(())
}
}
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)]
pub enum Urn {
#[from]
#[display("urn:sten:lib:{0}", alt = "urn:sten:lib:{0:#}")]
Lib(TypeLibId),
#[from]
#[display("urn:sten:id:{0}", alt = "urn:sten:id:{0:#}")]
Type(SemId),
}