use std::{borrow::Cow, fmt, fmt::Write, str::FromStr};
use git2::{MessageTrailersStrs, MessageTrailersStrsIterator};
use metadata::commit::trailers::Separator;
pub struct Trailers {
inner: MessageTrailersStrs,
}
impl Trailers {
pub fn parse(message: &str) -> Result<Self, git2::Error> {
Ok(Self {
inner: git2::message_trailers_strs(message)?,
})
}
pub fn iter(&self) -> Iter<'_> {
Iter {
inner: self.inner.iter(),
}
}
pub fn to_string<'a, S>(&self, sep: S) -> String
where
S: Separator<'a>,
{
let mut buf = String::new();
for (i, trailer) in self.iter().enumerate() {
if i > 0 {
writeln!(buf).ok();
}
write!(buf, "{}", trailer.display(sep.sep_for(&trailer.token))).ok();
}
writeln!(buf).ok();
buf
}
}
impl fmt::Display for Trailers {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.to_string(": "))
}
}
impl FromStr for Trailers {
type Err = git2::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::parse(s)
}
}
pub struct Iter<'a> {
inner: MessageTrailersStrsIterator<'a>,
}
impl<'a> Iterator for Iter<'a> {
type Item = metadata::commit::trailers::Trailer<'a>;
fn next(&mut self) -> Option<Self::Item> {
let (token, value) = self.inner.next()?;
Some(metadata::commit::trailers::Trailer {
token: {
metadata::commit::trailers::Token::try_from(token)
.expect("token from `git2` must be valid")
},
value: Cow::Borrowed(value),
})
}
}