]>
Commit | Line | Data |
---|---|---|
0a29b90c | 1 | mod _ref { |
fe692bf9 | 2 | use bstr::ByteSlice; |
781aab86 | 3 | use winnow::{error::StrContext, prelude::*}; |
0a29b90c | 4 | |
fe692bf9 | 5 | use crate::{signature::decode, IdentityRef, Signature, SignatureRef}; |
0a29b90c FG |
6 | |
7 | impl<'a> SignatureRef<'a> { | |
8 | /// Deserialize a signature from the given `data`. | |
781aab86 | 9 | pub fn from_bytes<E>(mut data: &'a [u8]) -> Result<SignatureRef<'a>, winnow::error::ErrMode<E>> |
0a29b90c | 10 | where |
781aab86 | 11 | E: winnow::error::ParserError<&'a [u8]> + winnow::error::AddContext<&'a [u8], StrContext>, |
0a29b90c | 12 | { |
781aab86 | 13 | decode.parse_next(&mut data) |
0a29b90c FG |
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. | |
fe692bf9 FG |
35 | pub fn actor(&self) -> IdentityRef<'a> { |
36 | IdentityRef { | |
37 | name: self.name, | |
38 | email: self.email, | |
39 | } | |
0a29b90c FG |
40 | } |
41 | } | |
42 | } | |
43 | ||
44 | mod convert { | |
45 | use crate::{Signature, SignatureRef}; | |
46 | ||
47 | impl Signature { | |
0a29b90c FG |
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 | ||
fe692bf9 | 76 | pub(crate) mod write { |
0a29b90c FG |
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)] | |
fe692bf9 | 84 | pub(crate) enum Error { |
0a29b90c FG |
85 | #[error("Signature name or email must not contain '<', '>' or \\n")] |
86 | IllegalCharacter, | |
87 | } | |
88 | ||
fe692bf9 | 89 | impl From<Error> for std::io::Error { |
0a29b90c | 90 | fn from(err: Error) -> Self { |
fe692bf9 | 91 | std::io::Error::new(std::io::ErrorKind::Other, err) |
0a29b90c FG |
92 | } |
93 | } | |
94 | ||
95 | /// Output | |
96 | impl Signature { | |
97 | /// Serialize this instance to `out` in the git serialization format for actors. | |
781aab86 | 98 | pub fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> { |
0a29b90c FG |
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<'a> SignatureRef<'a> { | |
108 | /// Serialize this instance to `out` in the git serialization format for actors. | |
781aab86 | 109 | pub fn write_to(&self, out: &mut dyn std::io::Write) -> std::io::Result<()> { |
0a29b90c FG |
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 | ||
fe692bf9 | 123 | pub(crate) fn validated_token(name: &BStr) -> Result<&BStr, Error> { |
0a29b90c FG |
124 | if name.find_byteset(b"<>\n").is_some() { |
125 | return Err(Error::IllegalCharacter); | |
126 | } | |
127 | Ok(name) | |
128 | } | |
129 | } | |
130 | ||
131 | /// | |
fe692bf9 FG |
132 | pub mod decode; |
133 | pub use decode::function::decode; |