1use crate::{BlobRef, CommitRef, CommitRefIter, Data, Kind, ObjectRef, TagRef, TagRefIter, TreeRef, TreeRefIter};
4
5impl<'a> Data<'a> {
6 pub fn new(kind: Kind, data: &'a [u8]) -> Data<'a> {
8 Data { kind, data }
9 }
10 pub fn decode(&self) -> Result<ObjectRef<'a>, crate::decode::Error> {
16 Ok(match self.kind {
17 Kind::Tree => ObjectRef::Tree(TreeRef::from_bytes(self.data)?),
18 Kind::Blob => ObjectRef::Blob(BlobRef { data: self.data }),
19 Kind::Commit => ObjectRef::Commit(CommitRef::from_bytes(self.data)?),
20 Kind::Tag => ObjectRef::Tag(TagRef::from_bytes(self.data)?),
21 })
22 }
23
24 pub fn try_into_tree_iter(self) -> Option<TreeRefIter<'a>> {
27 match self.kind {
28 Kind::Tree => Some(TreeRefIter::from_bytes(self.data)),
29 _ => None,
30 }
31 }
32
33 pub fn try_into_commit_iter(self) -> Option<CommitRefIter<'a>> {
36 match self.kind {
37 Kind::Commit => Some(CommitRefIter::from_bytes(self.data)),
38 _ => None,
39 }
40 }
41
42 pub fn try_into_tag_iter(self) -> Option<TagRefIter<'a>> {
45 match self.kind {
46 Kind::Tag => Some(TagRefIter::from_bytes(self.data)),
47 _ => None,
48 }
49 }
50}
51
52pub mod verify {
54
55 #[derive(Debug, thiserror::Error)]
57 #[allow(missing_docs)]
58 pub enum Error {
59 #[error("Object expected to have id {desired}, but actual id was {actual}")]
60 ChecksumMismatch {
61 desired: git_hash::ObjectId,
62 actual: git_hash::ObjectId,
63 },
64 }
65
66 impl crate::Data<'_> {
67 pub fn verify_checksum(&self, desired: impl AsRef<git_hash::oid>) -> Result<(), Error> {
71 let desired = desired.as_ref();
72 let mut hasher = git_features::hash::hasher(desired.kind());
73 hasher.update(&crate::encode::loose_header(self.kind, self.data.len()));
74 hasher.update(self.data);
75
76 let actual_id = git_hash::ObjectId::from(hasher.digest());
77 if desired != actual_id {
78 return Err(Error::ChecksumMismatch {
79 desired: desired.into(),
80 actual: actual_id,
81 });
82 }
83 Ok(())
84 }
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn size_of_object() {
94 assert_eq!(std::mem::size_of::<Data<'_>>(), 24, "this shouldn't change unnoticed");
95 }
96}