1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use crate::ByteSlice;
use nom::{lib::std::fmt::Formatter, lib::std::ops::Deref};
use quick_error::quick_error;
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub enum Sign {
Plus,
Minus,
}
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct Time {
pub time: u32,
pub offset: i32,
pub sign: Sign,
}
pub const SHA1_SIZE: usize = 20;
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct Id(pub [u8; SHA1_SIZE]);
impl Id {
pub fn encode_to_40_bytes_slice(&self, out: &mut [u8]) -> Result<(), hex::FromHexError> {
hex::encode_to_slice(self.0, out)
}
pub fn from_20_bytes(b: &[u8]) -> Id {
let mut id = [0; SHA1_SIZE];
id.copy_from_slice(b);
Id(id)
}
pub fn from_hex(buf: &[u8]) -> Result<Id, hex::FromHexError> {
use hex::FromHex;
Ok(Id(<[u8; 20]>::from_hex(buf)?))
}
pub fn null() -> Id {
Id([0u8; 20])
}
pub fn as_slice(&self) -> &[u8] {
self.0.as_ref()
}
}
impl Deref for Id {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0[..]
}
}
impl std::fmt::Display for Id {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut buf = [0u8; 40];
self.encode_to_40_bytes_slice(&mut buf).unwrap();
write!(f, "{}", &buf.as_bstr())
}
}
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub enum Kind {
Tree,
Blob,
Commit,
Tag,
}
quick_error! {
#[derive(Debug)]
pub enum Error {
InvalidObjectKind(kind: crate::BString) {
display("Unknown object kind: {:?}", std::str::from_utf8(&kind))
}
}
}
impl Kind {
pub fn from_bytes(s: &[u8]) -> Result<Kind, Error> {
Ok(match s {
b"tree" => Kind::Tree,
b"blob" => Kind::Blob,
b"commit" => Kind::Commit,
b"tag" => Kind::Tag,
_ => return Err(Error::InvalidObjectKind(s.into())),
})
}
pub fn to_bytes(&self) -> &[u8] {
match self {
Kind::Tree => b"tree",
Kind::Commit => b"commit",
Kind::Blob => b"blob",
Kind::Tag => b"tag",
}
}
}
impl std::fmt::Display for Kind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(std::str::from_utf8(self.to_bytes()).expect("valid utf8 in kind name"))
}
}