diff --git a/radicle-cob/src/trailers.rs b/radicle-cob/src/trailers.rs index 320a92a7..aa47ca2c 100644 --- a/radicle-cob/src/trailers.rs +++ b/radicle-cob/src/trailers.rs @@ -3,108 +3,79 @@ // This file is part of radicle-link, distributed under the GPLv3 with Radicle // Linking Exception. For full terms see the included LICENSE file. -mod resource_identity { - super::oid_trailer! {ResourceCommitTrailer, "Rad-Resource"} -} +use git_trailers::{OwnedTrailer, Token, Trailer}; +use radicle_git_ext as ext; pub mod error { - pub use super::resource_identity::Error as InvalidResourceTrailer; + use thiserror::Error; + + #[derive(Debug, Error)] + pub enum InvalidResourceTrailer { + #[error("found wrong token for Rad-Resource tailer")] + WrongToken, + #[error("no Rad-Resource")] + NoTrailer, + #[error("no value for Rad-Resource")] + NoValue, + #[error("invalid git OID")] + InvalidOid, + } } -pub use resource_identity::ResourceCommitTrailer; +pub struct ResourceCommitTrailer(git2::Oid); -/// A macro for generating boilerplate From and TryFrom impls for trailers which -/// have git object IDs as their values -#[macro_export] -macro_rules! oid_trailer { - ($typename:ident, $trailer:literal) => { - use git_trailers::{OwnedTrailer, Token, Trailer}; - use radicle_git_ext as ext; - - use std::convert::{TryFrom, TryInto}; - - #[derive(Debug)] - pub enum Error { - WrongToken, - NoTrailer, - NoValue, - InvalidOid, - } - - // We can't use `derive(thiserror::Error)` as we need to concat strings with - // $trailer and macros are not allowed in non-key-value attributes - impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::WrongToken => { - write!(f, concat!("found wrong token for ", $trailer, " trailer")) - } - Self::NoTrailer => write!(f, concat!("no ", $trailer)), - Self::NoValue => write!(f, concat!("no value for ", $trailer, " trailer")), - Self::InvalidOid => write!(f, "invalid git OID"), - } - } - } - - impl std::error::Error for Error {} - - pub struct $typename(git2::Oid); - - impl $typename { - pub fn oid(&self) -> git2::Oid { - self.0 - } - } - - impl From for $typename { - fn from(oid: git2::Oid) -> Self { - $typename(oid) - } - } - - impl From<$typename> for Trailer<'_> { - fn from(containing: $typename) -> Self { - Trailer { - token: Token::try_from($trailer).unwrap(), - values: vec![containing.0.to_string().into()], - } - } - } - - impl From<$typename> for OwnedTrailer { - fn from(containing: $typename) -> Self { - Trailer::from(containing).to_owned() - } - } - - impl TryFrom<&Trailer<'_>> for $typename { - type Error = Error; - - fn try_from(Trailer { values, token }: &Trailer<'_>) -> Result { - let val = values.first().ok_or(Error::NoValue)?; - let ext_oid = - radicle_git_ext::Oid::try_from(val.as_ref()).map_err(|_| Error::InvalidOid)?; - if Some(token) == Token::try_from($trailer).ok().as_ref() { - Ok($typename(ext_oid.into())) - } else { - Err(Error::WrongToken) - } - } - } - - impl TryFrom<&OwnedTrailer> for $typename { - type Error = Error; - - fn try_from(trailer: &OwnedTrailer) -> Result { - (&Trailer::from(trailer)).try_into() - } - } - - impl From for $typename { - fn from(oid: ext::Oid) -> Self { - $typename(oid.into()) - } - } - }; +impl ResourceCommitTrailer { + pub fn oid(&self) -> git2::Oid { + self.0 + } +} + +impl TryFrom<&Trailer<'_>> for ResourceCommitTrailer { + type Error = error::InvalidResourceTrailer; + + fn try_from(Trailer { values, token }: &Trailer<'_>) -> Result { + let val = values.first().ok_or(Self::Error::NoValue)?; + let ext_oid = + radicle_git_ext::Oid::try_from(val.as_ref()).map_err(|_| Self::Error::InvalidOid)?; + if Some(token) == Token::try_from("Rad-Resource").ok().as_ref() { + Ok(ResourceCommitTrailer(ext_oid.into())) + } else { + Err(Self::Error::WrongToken) + } + } +} + +impl TryFrom<&OwnedTrailer> for ResourceCommitTrailer { + type Error = error::InvalidResourceTrailer; + + fn try_from(trailer: &OwnedTrailer) -> Result { + Self::try_from(&Trailer::from(trailer)) + } +} + +impl From for ResourceCommitTrailer { + fn from(oid: git2::Oid) -> Self { + Self(oid) + } +} + +impl From for Trailer<'_> { + fn from(containing: ResourceCommitTrailer) -> Self { + Trailer { + token: Token::try_from("Rad-Resource").unwrap(), + values: vec![containing.0.to_string().into()], + } + } +} + +impl From for OwnedTrailer { + fn from(containing: ResourceCommitTrailer) -> Self { + Trailer::from(containing).to_owned() + } +} + +impl From for ResourceCommitTrailer { + fn from(oid: ext::Oid) -> Self { + Self(oid.into()) + } } -pub(crate) use oid_trailer;