gix_actor/signature/
mod.rs

1mod _ref {
2    use bstr::ByteSlice;
3    use winnow::{error::StrContext, prelude::*};
4
5    use crate::{signature::decode, IdentityRef, Signature, SignatureRef};
6
7    impl<'a> SignatureRef<'a> {
8        /// Deserialize a signature from the given `data`.
9        pub fn from_bytes<E>(mut data: &'a [u8]) -> Result<SignatureRef<'a>, winnow::error::ErrMode<E>>
10        where
11            E: winnow::error::ParserError<&'a [u8]> + winnow::error::AddContext<&'a [u8], StrContext>,
12        {
13            decode.parse_next(&mut data)
14        }
15
16        /// Create an owned instance from this shared one.
17        pub fn to_owned(&self) -> Signature {
18            Signature {
19                name: self.name.to_owned(),
20                email: self.email.to_owned(),
21                time: self.time,
22            }
23        }
24
25        /// Trim whitespace surrounding the name and email and return a new signature.
26        pub fn trim(&self) -> SignatureRef<'a> {
27            SignatureRef {
28                name: self.name.trim().as_bstr(),
29                email: self.email.trim().as_bstr(),
30                time: self.time,
31            }
32        }
33
34        /// Return the actor's name and email, effectively excluding the time stamp of this signature.
35        pub fn actor(&self) -> IdentityRef<'a> {
36            IdentityRef {
37                name: self.name,
38                email: self.email,
39            }
40        }
41    }
42}
43
44mod convert {
45    use crate::{Signature, SignatureRef};
46
47    impl Signature {
48        /// Borrow this instance as immutable
49        pub fn to_ref(&self) -> SignatureRef<'_> {
50            SignatureRef {
51                name: self.name.as_ref(),
52                email: self.email.as_ref(),
53                time: self.time,
54            }
55        }
56    }
57
58    impl From<SignatureRef<'_>> for Signature {
59        fn from(other: SignatureRef<'_>) -> Signature {
60            let SignatureRef { name, email, time } = other;
61            Signature {
62                name: name.to_owned(),
63                email: email.to_owned(),
64                time,
65            }
66        }
67    }
68
69    impl<'a> From<&'a Signature> for SignatureRef<'a> {
70        fn from(other: &'a Signature) -> SignatureRef<'a> {
71            other.to_ref()
72        }
73    }
74}
75
76pub(crate) mod write {
77    use bstr::{BStr, ByteSlice};
78
79    use crate::{Signature, SignatureRef};
80
81    /// The Error produced by [`Signature::write_to()`].
82    #[derive(Debug, thiserror::Error)]
83    #[allow(missing_docs)]
84    pub(crate) enum Error {
85        #[error("Signature name or email must not contain '<', '>' or \\n")]
86        IllegalCharacter,
87    }
88
89    impl From<Error> for std::io::Error {
90        fn from(err: Error) -> Self {
91            std::io::Error::new(std::io::ErrorKind::Other, err)
92        }
93    }
94
95    /// Output
96    impl Signature {
97        /// Serialize this instance to `out` in the git serialization format for actors.
98        pub fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> {
99            self.to_ref().write_to(out)
100        }
101        /// Computes the number of bytes necessary to serialize this signature
102        pub fn size(&self) -> usize {
103            self.to_ref().size()
104        }
105    }
106
107    impl SignatureRef<'_> {
108        /// Serialize this instance to `out` in the git serialization format for actors.
109        pub fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> {
110            out.write_all(validated_token(self.name)?)?;
111            out.write_all(b" ")?;
112            out.write_all(b"<")?;
113            out.write_all(validated_token(self.email)?)?;
114            out.write_all(b"> ")?;
115            self.time.write_to(out)
116        }
117        /// Computes the number of bytes necessary to serialize this signature
118        pub fn size(&self) -> usize {
119            self.name.len() + 2 /* space <*/ + self.email.len() +  2 /* > space */ + self.time.size()
120        }
121    }
122
123    pub(crate) fn validated_token(name: &BStr) -> Result<&BStr, Error> {
124        if name.find_byteset(b"<>\n").is_some() {
125            return Err(Error::IllegalCharacter);
126        }
127        Ok(name)
128    }
129}
130
131///
132pub mod decode;
133pub use decode::function::decode;