Skip to content

Commit b4392e8

Browse files
committed
refactor
1 parent 087857a commit b4392e8

File tree

5 files changed

+247
-253
lines changed

5 files changed

+247
-253
lines changed

git-object/src/owned/convert.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use crate::{borrowed, owned};
2+
3+
impl Into<owned::Signature> for borrowed::Signature<'_> {
4+
fn into(self) -> owned::Signature {
5+
let borrowed::Signature { name, email, time } = self;
6+
owned::Signature {
7+
name: name.to_owned(),
8+
email: email.to_owned(),
9+
time,
10+
}
11+
}
12+
}
13+
14+
impl Into<owned::Tag> for borrowed::Tag<'_> {
15+
fn into(self) -> owned::Tag {
16+
let borrowed::Tag {
17+
target,
18+
name,
19+
target_kind,
20+
message,
21+
signature,
22+
pgp_signature,
23+
} = self;
24+
owned::Tag {
25+
target: crate::Id::from_40_bytes_in_hex(&target).expect("40 bytes hex sha1"),
26+
name: name.to_owned(),
27+
target_kind,
28+
message: message.to_owned(),
29+
signature: signature.into(),
30+
pgp_signature: pgp_signature.map(ToOwned::to_owned),
31+
}
32+
}
33+
}

git-object/src/owned/mod.rs

Lines changed: 4 additions & 253 deletions
Original file line numberDiff line numberDiff line change
@@ -1,258 +1,9 @@
11
//! Owned objects for use with serialization.
22
3-
mod ser {
4-
use bstr::{BString, ByteSlice};
5-
use quick_error::quick_error;
6-
use std::io;
7-
8-
quick_error! {
9-
#[derive(Debug)]
10-
enum Error {
11-
NewlineInHeaderValue(value: BString) {
12-
display("Newlines are not allowed in header values: {:?}", value)
13-
}
14-
EmptyValue {
15-
display("Header values must not be empty")
16-
}
17-
}
18-
}
19-
20-
impl Into<io::Error> for Error {
21-
fn into(self) -> io::Error {
22-
io::Error::new(io::ErrorKind::Other, self)
23-
}
24-
}
25-
26-
const NL: &[u8; 1] = b"\n";
27-
const SPACE: &[u8; 1] = b" ";
28-
29-
pub fn trusted_header_field(name: &[u8], value: &[u8], mut out: impl io::Write) -> io::Result<()> {
30-
out.write_all(name)?;
31-
out.write_all(&SPACE[..])?;
32-
out.write_all(value)?;
33-
out.write_all(&NL[..])
34-
}
35-
pub fn header_field(name: &[u8], value: &[u8], out: impl io::Write) -> io::Result<()> {
36-
if value.is_empty() {
37-
return Err(Error::EmptyValue.into());
38-
}
39-
if value.find(NL).is_some() {
40-
return Err(Error::NewlineInHeaderValue(value.into()).into());
41-
}
42-
trusted_header_field(name, value, out)
43-
}
44-
}
45-
46-
mod object {
47-
use crate::Time;
48-
use bstr::BString;
49-
50-
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
51-
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
52-
pub struct Signature {
53-
pub name: BString,
54-
pub email: BString,
55-
pub time: Time,
56-
}
57-
}
58-
59-
mod tag {
60-
use crate::{owned, owned::ser, Id};
61-
use bstr::{BStr, BString};
62-
use quick_error::quick_error;
63-
use std::io;
64-
65-
quick_error! {
66-
#[derive(Debug)]
67-
pub enum Error {
68-
StartsWithDash {
69-
description("Tags must not start with a dash: '-'")
70-
}
71-
InvalidRefName(err: reference::Error) {
72-
display("The tag name was no valid reference name")
73-
from()
74-
cause(err)
75-
}
76-
}
77-
}
78-
79-
impl From<Error> for io::Error {
80-
fn from(err: Error) -> Self {
81-
io::Error::new(io::ErrorKind::Other, err)
82-
}
83-
}
84-
85-
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
86-
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
87-
pub struct Tag {
88-
// Target SHA1 in hex, always 40 lower case characters from 0-9 and a-f
89-
pub target: Id,
90-
// The name of the tag, e.g. "v1.0"
91-
pub name: BString,
92-
pub target_kind: crate::Kind,
93-
pub message: BString,
94-
pub signature: owned::object::Signature,
95-
pub pgp_signature: Option<BString>,
96-
}
97-
98-
impl Tag {
99-
pub fn to_write(&self, mut out: impl io::Write) -> io::Result<()> {
100-
let mut hex_buf: [u8; 40] = [0; 40];
101-
self.target
102-
.encode_to_40_bytes_slice(&mut hex_buf[..])
103-
.expect("20 to 40 bytes hex encoding to always work");
104-
105-
ser::trusted_header_field(b"object", &hex_buf, &mut out)?;
106-
ser::trusted_header_field(b"type", self.target_kind.to_bytes(), &mut out)?;
107-
ser::header_field(b"type", validated_name(self.name.as_ref())?, &mut out)?;
108-
unimplemented!("tag to_write")
109-
}
110-
}
111-
112-
pub mod reference {
113-
use bstr::BStr;
114-
115-
use quick_error::quick_error;
116-
117-
quick_error! {
118-
#[derive(Debug)]
119-
pub enum Error {
120-
StartsWithDot {
121-
description("A ref must not start with a '.'")
122-
}
123-
Empty {
124-
description("A ref must not be empty")
125-
}
126-
}
127-
}
128-
129-
pub fn validated_name(name: &BStr) -> Result<&BStr, Error> {
130-
if name.is_empty() {
131-
return Err(Error::Empty);
132-
}
133-
if name[0] == b'.' {
134-
return Err(Error::StartsWithDot);
135-
}
136-
Ok(name)
137-
}
138-
139-
#[cfg(test)]
140-
mod tests {
141-
mod validated_name {
142-
mod valid {
143-
use super::super::super::*;
144-
use bstr::ByteSlice;
145-
146-
macro_rules! mktest {
147-
($name:ident, $input:literal) => {
148-
#[test]
149-
fn $name() {
150-
assert!(validated_name($input.as_bstr()).is_ok())
151-
}
152-
};
153-
}
154-
155-
mktest!(dot_in_the_middle, b"token.other");
156-
mktest!(dot_at_the_end, b"hello.");
157-
}
158-
mod invalid {
159-
use super::super::super::*;
160-
use bstr::ByteSlice;
161-
162-
macro_rules! mktest {
163-
($name:ident, $input:literal, $expected:ident) => {
164-
#[test]
165-
fn $name() {
166-
match validated_name($input.as_bstr()) {
167-
Err(Error::$expected) => {}
168-
got => panic!("Wanted {}, got {:?}", stringify!($expected), got),
169-
}
170-
}
171-
};
172-
}
173-
174-
mktest!(starts_with_dot, b".with-dot", StartsWithDot);
175-
mktest!(empty, b"", Empty);
176-
}
177-
}
178-
}
179-
}
180-
181-
fn validated_name(name: &BStr) -> Result<&BStr, Error> {
182-
reference::validated_name(name)?;
183-
if name[0] == b'-' {
184-
return Err(Error::StartsWithDash);
185-
}
186-
Ok(name)
187-
}
188-
189-
#[cfg(test)]
190-
mod tests {
191-
mod validated_name {
192-
mod invalid {
193-
use super::super::super::*;
194-
use bstr::ByteSlice;
195-
196-
#[test]
197-
fn only_dash() {
198-
assert!(validated_name(b"-".as_bstr()).is_err())
199-
}
200-
#[test]
201-
fn leading_dash() {
202-
assert!(validated_name(b"-hello".as_bstr()).is_err())
203-
}
204-
}
205-
206-
mod valid {
207-
use super::super::super::*;
208-
use bstr::ByteSlice;
209-
210-
#[test]
211-
fn version() {
212-
for version in &["v1.0.0", "0.2.1", "0-alpha1"] {
213-
assert!(validated_name(version.as_bytes().as_bstr()).is_ok())
214-
}
215-
}
216-
}
217-
}
218-
}
219-
}
220-
221-
mod convert {
222-
use crate::{borrowed, owned};
223-
224-
impl Into<owned::Signature> for borrowed::Signature<'_> {
225-
fn into(self) -> owned::Signature {
226-
let borrowed::Signature { name, email, time } = self;
227-
owned::Signature {
228-
name: name.to_owned(),
229-
email: email.to_owned(),
230-
time,
231-
}
232-
}
233-
}
234-
235-
impl Into<owned::Tag> for borrowed::Tag<'_> {
236-
fn into(self) -> owned::Tag {
237-
let borrowed::Tag {
238-
target,
239-
name,
240-
target_kind,
241-
message,
242-
signature,
243-
pgp_signature,
244-
} = self;
245-
owned::Tag {
246-
target: crate::Id::from_40_bytes_in_hex(&target).expect("40 bytes hex sha1"),
247-
name: name.to_owned(),
248-
target_kind,
249-
message: message.to_owned(),
250-
signature: signature.into(),
251-
pgp_signature: pgp_signature.map(ToOwned::to_owned),
252-
}
253-
}
254-
}
255-
}
3+
mod convert;
4+
mod object;
5+
mod ser;
6+
mod tag;
2567

2578
pub use object::*;
2589
pub use tag::Tag;

git-object/src/owned/object.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use crate::Time;
2+
use bstr::BString;
3+
4+
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
5+
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
6+
pub struct Signature {
7+
pub name: BString,
8+
pub email: BString,
9+
pub time: Time,
10+
}

git-object/src/owned/ser.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use bstr::{BString, ByteSlice};
2+
use quick_error::quick_error;
3+
use std::io;
4+
5+
quick_error! {
6+
#[derive(Debug)]
7+
enum Error {
8+
NewlineInHeaderValue(value: BString) {
9+
display("Newlines are not allowed in header values: {:?}", value)
10+
}
11+
EmptyValue {
12+
display("Header values must not be empty")
13+
}
14+
}
15+
}
16+
17+
impl Into<io::Error> for Error {
18+
fn into(self) -> io::Error {
19+
io::Error::new(io::ErrorKind::Other, self)
20+
}
21+
}
22+
23+
const NL: &[u8; 1] = b"\n";
24+
const SPACE: &[u8; 1] = b" ";
25+
26+
pub fn trusted_header_field(name: &[u8], value: &[u8], mut out: impl io::Write) -> io::Result<()> {
27+
out.write_all(name)?;
28+
out.write_all(&SPACE[..])?;
29+
out.write_all(value)?;
30+
out.write_all(&NL[..])
31+
}
32+
33+
pub fn header_field(name: &[u8], value: &[u8], out: impl io::Write) -> io::Result<()> {
34+
if value.is_empty() {
35+
return Err(Error::EmptyValue.into());
36+
}
37+
if value.find(NL).is_some() {
38+
return Err(Error::NewlineInHeaderValue(value.into()).into());
39+
}
40+
trusted_header_field(name, value, out)
41+
}

0 commit comments

Comments
 (0)