use crate::{Fragment, RonlogReferences, Version};
use chrono::{DateTime, Local};
use std::str::FromStr;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct Section {
references: RonlogReferences,
version: Version,
released: DateTime<Local>,
introduction: Option<String>,
changes: Fragment,
}
impl Section {
crate::getters!(@fn @ref
references: RonlogReferences,
version: Version,
released: DateTime<Local>,
introduction: Option<String>,
changes: Fragment
);
pub fn add_changes(&mut self, changes: Fragment) {
self.changes.merge(changes);
for (link, target) in self.changes.move_references() {
self
.references
.entry(link)
.and_modify(|t| *t = target.clone())
.or_insert(target);
}
}
pub fn merge(&mut self, mut other: Self) {
if self.version == other.version {
self.add_changes(other.changes.clone());
match &self.introduction {
Some(introduction_1) => {
if let Some(introduction_2) = &other.introduction {
let mut introduction_1 = introduction_1.clone();
introduction_1.push('\n');
introduction_1.push_str(introduction_2.as_str());
self.introduction = Some(introduction_1);
}
}
None => self.introduction = other.introduction.clone(),
}
for (link, target) in other.move_references() {
self
.references
.entry(link)
.and_modify(|t| *t = target.clone())
.or_insert(target);
}
self.released = self.released.max(other.released);
}
}
#[must_use]
pub fn move_references(&mut self) -> RonlogReferences {
let result = self.references.clone();
self.references.clear();
result
}
pub fn new(
mut changes: Fragment,
version: &str,
introduction: Option<String>,
references: Option<RonlogReferences>,
) -> sysexits::Result<Self> {
let mut references = references.unwrap_or_default();
for (link, target) in changes.move_references() {
references
.entry(link)
.and_modify(|t| *t = target.clone())
.or_insert(target);
}
Ok(Self {
references,
version: Version::from_str(version)?,
released: Local::now(),
introduction,
changes,
})
}
}
impl Eq for Section {}
impl Ord for Section {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.version.cmp(&other.version)
}
}
impl PartialEq for Section {
fn eq(&self, other: &Self) -> bool {
self.version == other.version
}
}
impl PartialOrd for Section {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}