use std::cmp::Ordering;
use std::fmt::{Debug, Display, Formatter};
use serde::{Deserialize, Serialize};
use crate::{FMRI, version::segments::Segments};
pub mod segment;
pub mod segments;
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
pub struct Version {
component_version: Segments,
build_version: Segments,
branch_version: Segments,
timestamp: Segments,
}
impl Version {
pub fn new(mut version: String) -> Result<Self, String> {
if !version.starts_with('@') {
version.insert(0, '@')
}
Ok(Self {
component_version: Segments::get_segment_from_string(version.clone(), '@')?,
build_version: Segments::get_segment_from_string(version.clone(), ',')?,
branch_version: Segments::get_segment_from_string(version.clone(), '-')?,
timestamp: Segments::get_segment_from_string(version.clone(), ':')?,
})
}
pub fn parse_version_from_raw_fmri(raw_fmri: String) -> Result<Option<Self>, String> {
let mut raw_fmri = raw_fmri.trim_start_matches("fmri=").to_owned();
match raw_fmri.find('@') {
None => Ok(None),
Some(position) => {
let version = raw_fmri.split_off(position);
Ok(Some(Self::new(version.to_owned())?))
}
}
}
}
impl PartialOrd<Self> for Version {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Version {
fn cmp(&self, other: &Self) -> Ordering {
if let (
Segments::ComponentVersion(self_segment),
Segments::ComponentVersion(other_segment),
) = (&self.component_version, &other.component_version)
{
if self_segment != other_segment {
return self_segment.cmp(other_segment);
}
}
if let (Segments::BuildVersion(self_segment), Segments::BuildVersion(other_segment)) =
(&self.build_version, &other.build_version)
{
if self_segment != other_segment {
return self_segment.cmp(other_segment);
}
}
if let (Segments::BranchVersion(self_segment), Segments::BranchVersion(other_segment)) =
(&self.branch_version, &other.branch_version)
{
if self_segment != other_segment {
return self_segment.cmp(other_segment);
}
}
Ordering::Equal
}
}
impl Display for Version {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let string: &mut String = &mut "".to_string();
if let Segments::ComponentVersion(segment) = &self.component_version {
string.push('@');
string.push_str(&segment.as_string());
}
if let Segments::BuildVersion(segment) = &self.build_version {
string.push(',');
string.push_str(&segment.as_string());
}
if let Segments::BranchVersion(segment) = &self.branch_version {
string.push('-');
string.push_str(&segment.as_string());
}
if let Segments::Timestamp(segment) = &self.timestamp {
string.push(':');
string.push_str(segment);
}
write!(f, "{}", string)
}
}
impl Debug for Version {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self)
}
}