1use std::hash::Hash;
2use std::marker::PhantomData;
3use std::str::FromStr;
4
5use crate::changelog::AsChangelogFmt;
6use crate::error::VersionBumpError;
7
8pub trait VersionEditor:
9 AsChangelogFmt + Versioned + Clone + Default + Hash + FromStr + Ord
10{
11 fn options() -> Vec<Self>;
12
13 fn mask<'a>(mask: &str, version: &'a str) -> &'a str;
14
15 fn r#match(mask: &str, version: &str) -> bool;
16}
17
18pub trait Versioned: ToString {
19 fn apply(&self, current: &str) -> Result<String, VersionBumpError>;
20}
21
22#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd)]
23pub struct VersionMod<T> {
24 pub(crate) version: T,
25}
26
27impl<T> VersionMod<T> {
28 pub fn new(version: T) -> Self {
29 VersionMod { version }
30 }
31}
32
33impl<T> Versioned for VersionMod<T>
34where
35 T: Versioned,
36{
37 fn apply(&self, current: &str) -> Result<String, VersionBumpError> {
38 self.version.apply(current)
39 }
40}
41
42impl<T> VersionEditor for VersionMod<T>
43where
44 T: VersionEditor,
45{
46 fn mask<'a>(mask: &str, version: &'a str) -> &'a str {
47 T::mask(mask, version)
48 }
49 fn r#match(mask: &str, version: &str) -> bool {
50 T::r#match(mask, version)
51 }
52 fn options() -> Vec<Self> {
53 T::options()
54 .into_iter()
55 .map(|version| Self { version })
56 .collect()
57 }
58}
59
60impl<T> FromStr for VersionMod<T>
61where
62 T: FromStr,
63{
64 type Err = T::Err;
65 fn from_str(value: &str) -> Result<Self, Self::Err> {
66 Ok(VersionMod {
67 version: T::from_str(value)?,
68 })
69 }
70}
71
72impl<T> ToString for VersionMod<T>
73where
74 T: ToString,
75{
76 fn to_string(&self) -> String {
77 self.version.to_string()
78 }
79}
80
81#[derive(Clone, Debug, PartialEq, Eq)]
82pub struct Version<T: ?Sized> {
83 pub value: String,
84 r#type: PhantomData<T>,
85}
86
87impl<T, U> From<U> for Version<T>
88where
89 U: ToString,
90{
91 fn from(value: U) -> Self {
92 Version {
93 value: value.to_string(),
94 r#type: PhantomData::<T>,
95 }
96 }
97}