git_internal/internal/object/
types.rs1use std::fmt::Display;
2
3use serde::{Deserialize, Serialize};
4
5use crate::errors::GitError;
6
7#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, Serialize, Deserialize)]
26pub enum ObjectType {
27 Commit = 1,
28 Tree,
29 Blob,
30 Tag,
31 OffsetZstdelta, OffsetDelta,
33 HashDelta,
34}
35
36const COMMIT_OBJECT_TYPE: &[u8] = b"commit";
37const TREE_OBJECT_TYPE: &[u8] = b"tree";
38const BLOB_OBJECT_TYPE: &[u8] = b"blob";
39const TAG_OBJECT_TYPE: &[u8] = b"tag";
40
41impl Display for ObjectType {
43 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
44 match self {
45 ObjectType::Blob => write!(f, "blob"),
46 ObjectType::Tree => write!(f, "tree"),
47 ObjectType::Commit => write!(f, "commit"),
48 ObjectType::Tag => write!(f, "tag"),
49 ObjectType::OffsetZstdelta => write!(f, "OffsetZstdelta"),
50 ObjectType::OffsetDelta => write!(f, "OffsetDelta"),
51 ObjectType::HashDelta => write!(f, "HashDelta"),
52 }
53 }
54}
55
56impl ObjectType {
58 pub fn to_bytes(&self) -> &[u8] {
59 match self {
60 ObjectType::Commit => COMMIT_OBJECT_TYPE,
61 ObjectType::Tree => TREE_OBJECT_TYPE,
62 ObjectType::Blob => BLOB_OBJECT_TYPE,
63 ObjectType::Tag => TAG_OBJECT_TYPE,
64 _ => panic!("can put compute the delta hash value"),
65 }
66 }
67
68 pub fn from_string(s: &str) -> Result<ObjectType, GitError> {
70 match s {
71 "blob" => Ok(ObjectType::Blob),
72 "tree" => Ok(ObjectType::Tree),
73 "commit" => Ok(ObjectType::Commit),
74 "tag" => Ok(ObjectType::Tag),
75 _ => Err(GitError::InvalidObjectType(s.to_string())),
76 }
77 }
78
79 pub fn to_data(self) -> Result<Vec<u8>, GitError> {
81 match self {
82 ObjectType::Blob => Ok(vec![0x62, 0x6c, 0x6f, 0x62]),
83 ObjectType::Tree => Ok(vec![0x74, 0x72, 0x65, 0x65]),
84 ObjectType::Commit => Ok(vec![0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74]),
85 ObjectType::Tag => Ok(vec![0x74, 0x61, 0x67]),
86 _ => Err(GitError::InvalidObjectType(self.to_string())),
87 }
88 }
89
90 pub fn to_u8(&self) -> u8 {
92 match self {
93 ObjectType::Commit => 1,
94 ObjectType::Tree => 2,
95 ObjectType::Blob => 3,
96 ObjectType::Tag => 4,
97 ObjectType::OffsetZstdelta => 5, ObjectType::OffsetDelta => 6,
99 ObjectType::HashDelta => 7,
100 }
101 }
102
103 pub fn from_u8(number: u8) -> Result<ObjectType, GitError> {
105 match number {
106 1 => Ok(ObjectType::Commit),
107 2 => Ok(ObjectType::Tree),
108 3 => Ok(ObjectType::Blob),
109 4 => Ok(ObjectType::Tag),
110 5 => Ok(ObjectType::OffsetZstdelta),
111 6 => Ok(ObjectType::OffsetDelta),
112 7 => Ok(ObjectType::HashDelta),
113 _ => Err(GitError::InvalidObjectType(format!(
114 "Invalid object type number: {number}"
115 ))),
116 }
117 }
118
119 pub fn is_base(&self) -> bool {
120 match self {
121 ObjectType::Commit => true,
122 ObjectType::Tree => true,
123 ObjectType::Blob => true,
124 ObjectType::Tag => true,
125 ObjectType::HashDelta => false,
126 ObjectType::OffsetZstdelta => false,
127 ObjectType::OffsetDelta => false,
128 }
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use crate::internal::object::types::ObjectType;
135
136 #[test]
137 fn test_object_type_to_data() {
138 let blob = ObjectType::Blob;
139 let blob_bytes = blob.to_data().unwrap();
140 assert_eq!(blob_bytes, vec![0x62, 0x6c, 0x6f, 0x62]);
141 }
142
143 #[test]
144 fn test_object_type_from_string() {
145 let tree = ObjectType::from_string("tree").unwrap();
146 assert_eq!(tree, ObjectType::Tree);
147 }
148
149 #[test]
150 fn test_object_type_to_u8() {
151 let commit = ObjectType::Commit;
152 let commit_number = commit.to_u8();
153 assert_eq!(commit_number, 1);
154 }
155
156 #[test]
157 fn test_object_type_from_u8() {
158 let tag_number = 4;
159 let tag = ObjectType::from_u8(tag_number).unwrap();
160 assert_eq!(tag, ObjectType::Tag);
161 }
162}