diff options
Diffstat (limited to 'vendor/gix-object/src/object')
-rw-r--r-- | vendor/gix-object/src/object/convert.rs | 228 | ||||
-rw-r--r-- | vendor/gix-object/src/object/mod.rs | 296 |
2 files changed, 524 insertions, 0 deletions
diff --git a/vendor/gix-object/src/object/convert.rs b/vendor/gix-object/src/object/convert.rs new file mode 100644 index 000000000..5e6e63486 --- /dev/null +++ b/vendor/gix-object/src/object/convert.rs @@ -0,0 +1,228 @@ +use std::convert::TryFrom; + +use crate::{tree, Blob, BlobRef, Commit, CommitRef, Object, ObjectRef, Tag, TagRef, Tree, TreeRef}; + +impl From<TagRef<'_>> for Tag { + fn from(other: TagRef<'_>) -> Tag { + let TagRef { + target, + name, + target_kind, + message, + tagger: signature, + pgp_signature, + } = other; + Tag { + target: gix_hash::ObjectId::from_hex(target).expect("prior parser validation"), + name: name.to_owned(), + target_kind, + message: message.to_owned(), + tagger: signature.map(Into::into), + pgp_signature: pgp_signature.map(ToOwned::to_owned), + } + } +} + +impl From<CommitRef<'_>> for Commit { + fn from(other: CommitRef<'_>) -> Commit { + let CommitRef { + tree, + parents, + author, + committer, + encoding, + message, + extra_headers, + } = other; + Commit { + tree: gix_hash::ObjectId::from_hex(tree).expect("prior parser validation"), + parents: parents + .iter() + .map(|parent| gix_hash::ObjectId::from_hex(parent).expect("prior parser validation")) + .collect(), + author: author.into(), + committer: committer.into(), + encoding: encoding.map(ToOwned::to_owned), + message: message.to_owned(), + extra_headers: extra_headers + .into_iter() + .map(|(k, v)| (k.into(), v.into_owned())) + .collect(), + } + } +} + +impl<'a> From<BlobRef<'a>> for Blob { + fn from(v: BlobRef<'a>) -> Self { + Blob { + data: v.data.to_owned(), + } + } +} + +impl From<TreeRef<'_>> for Tree { + fn from(other: TreeRef<'_>) -> Tree { + let TreeRef { entries } = other; + Tree { + entries: entries.into_iter().map(Into::into).collect(), + } + } +} + +impl From<tree::EntryRef<'_>> for tree::Entry { + fn from(other: tree::EntryRef<'_>) -> tree::Entry { + let tree::EntryRef { mode, filename, oid } = other; + tree::Entry { + mode, + filename: filename.to_owned(), + oid: oid.into(), + } + } +} + +impl<'a> From<ObjectRef<'a>> for Object { + fn from(v: ObjectRef<'_>) -> Self { + match v { + ObjectRef::Tree(v) => Object::Tree(v.into()), + ObjectRef::Blob(v) => Object::Blob(v.into()), + ObjectRef::Commit(v) => Object::Commit(v.into()), + ObjectRef::Tag(v) => Object::Tag(v.into()), + } + } +} + +impl From<Tag> for Object { + fn from(v: Tag) -> Self { + Object::Tag(v) + } +} + +impl From<Commit> for Object { + fn from(v: Commit) -> Self { + Object::Commit(v) + } +} + +impl From<Tree> for Object { + fn from(v: Tree) -> Self { + Object::Tree(v) + } +} + +impl From<Blob> for Object { + fn from(v: Blob) -> Self { + Object::Blob(v) + } +} + +impl TryFrom<Object> for Tag { + type Error = Object; + + fn try_from(value: Object) -> Result<Self, Self::Error> { + Ok(match value { + Object::Tag(v) => v, + _ => return Err(value), + }) + } +} + +impl TryFrom<Object> for Commit { + type Error = Object; + + fn try_from(value: Object) -> Result<Self, Self::Error> { + Ok(match value { + Object::Commit(v) => v, + _ => return Err(value), + }) + } +} + +impl TryFrom<Object> for Tree { + type Error = Object; + + fn try_from(value: Object) -> Result<Self, Self::Error> { + Ok(match value { + Object::Tree(v) => v, + _ => return Err(value), + }) + } +} + +impl TryFrom<Object> for Blob { + type Error = Object; + + fn try_from(value: Object) -> Result<Self, Self::Error> { + Ok(match value { + Object::Blob(v) => v, + _ => return Err(value), + }) + } +} + +impl<'a> From<TagRef<'a>> for ObjectRef<'a> { + fn from(v: TagRef<'a>) -> Self { + ObjectRef::Tag(v) + } +} + +impl<'a> From<CommitRef<'a>> for ObjectRef<'a> { + fn from(v: CommitRef<'a>) -> Self { + ObjectRef::Commit(v) + } +} + +impl<'a> From<TreeRef<'a>> for ObjectRef<'a> { + fn from(v: TreeRef<'a>) -> Self { + ObjectRef::Tree(v) + } +} + +impl<'a> From<BlobRef<'a>> for ObjectRef<'a> { + fn from(v: BlobRef<'a>) -> Self { + ObjectRef::Blob(v) + } +} + +impl<'a> TryFrom<ObjectRef<'a>> for TagRef<'a> { + type Error = ObjectRef<'a>; + + fn try_from(value: ObjectRef<'a>) -> Result<Self, Self::Error> { + Ok(match value { + ObjectRef::Tag(v) => v, + _ => return Err(value), + }) + } +} + +impl<'a> TryFrom<ObjectRef<'a>> for CommitRef<'a> { + type Error = ObjectRef<'a>; + + fn try_from(value: ObjectRef<'a>) -> Result<Self, Self::Error> { + Ok(match value { + ObjectRef::Commit(v) => v, + _ => return Err(value), + }) + } +} + +impl<'a> TryFrom<ObjectRef<'a>> for TreeRef<'a> { + type Error = ObjectRef<'a>; + + fn try_from(value: ObjectRef<'a>) -> Result<Self, Self::Error> { + Ok(match value { + ObjectRef::Tree(v) => v, + _ => return Err(value), + }) + } +} + +impl<'a> TryFrom<ObjectRef<'a>> for BlobRef<'a> { + type Error = ObjectRef<'a>; + + fn try_from(value: ObjectRef<'a>) -> Result<Self, Self::Error> { + Ok(match value { + ObjectRef::Blob(v) => v, + _ => return Err(value), + }) + } +} diff --git a/vendor/gix-object/src/object/mod.rs b/vendor/gix-object/src/object/mod.rs new file mode 100644 index 000000000..c0f9dcd52 --- /dev/null +++ b/vendor/gix-object/src/object/mod.rs @@ -0,0 +1,296 @@ +use crate::{Blob, Commit, Object, Tag, Tree}; + +mod convert; + +mod write { + use std::io; + + use crate::{Kind, Object, ObjectRef, WriteTo}; + + /// Serialization + impl<'a> WriteTo for ObjectRef<'a> { + /// Write the contained object to `out` in the git serialization format. + fn write_to(&self, out: impl io::Write) -> io::Result<()> { + use crate::ObjectRef::*; + match self { + Tree(v) => v.write_to(out), + Blob(v) => v.write_to(out), + Commit(v) => v.write_to(out), + Tag(v) => v.write_to(out), + } + } + + fn size(&self) -> usize { + use crate::ObjectRef::*; + match self { + Tree(v) => v.size(), + Blob(v) => v.size(), + Commit(v) => v.size(), + Tag(v) => v.size(), + } + } + + fn kind(&self) -> Kind { + self.kind() + } + } + + /// Serialization + impl WriteTo for Object { + /// Write the contained object to `out` in the git serialization format. + fn write_to(&self, out: impl io::Write) -> io::Result<()> { + use crate::Object::*; + match self { + Tree(v) => v.write_to(out), + Blob(v) => v.write_to(out), + Commit(v) => v.write_to(out), + Tag(v) => v.write_to(out), + } + } + + fn size(&self) -> usize { + use crate::Object::*; + match self { + Tree(v) => v.size(), + Blob(v) => v.size(), + Commit(v) => v.size(), + Tag(v) => v.size(), + } + } + + fn kind(&self) -> Kind { + self.kind() + } + } +} + +/// Convenient extraction of typed object. +impl Object { + /// Turns this instance into a [`Blob`][Blob], panic otherwise. + pub fn into_blob(self) -> Blob { + match self { + Object::Blob(v) => v, + _ => panic!("BUG: not a blob"), + } + } + /// Turns this instance into a [`Commit`][Commit] panic otherwise. + pub fn into_commit(self) -> Commit { + match self { + Object::Commit(v) => v, + _ => panic!("BUG: not a commit"), + } + } + /// Turns this instance into a [`Tree`][Tree] panic otherwise. + pub fn into_tree(self) -> Tree { + match self { + Object::Tree(v) => v, + _ => panic!("BUG: not a tree"), + } + } + /// Turns this instance into a [`Tag`][Tag] panic otherwise. + pub fn into_tag(self) -> Tag { + match self { + Object::Tag(v) => v, + _ => panic!("BUG: not a tag"), + } + } + /// Turns this instance into a [`Blob`][Blob] if it is one. + #[allow(clippy::result_large_err)] + pub fn try_into_blob(self) -> Result<Blob, Self> { + match self { + Object::Blob(v) => Ok(v), + _ => Err(self), + } + } + /// Turns this instance into a [`BlobRef`][BlobRef] if it is a blob. + pub fn try_into_blob_ref(&self) -> Option<BlobRef<'_>> { + match self { + Object::Blob(v) => Some(v.to_ref()), + _ => None, + } + } + /// Turns this instance into a [`Commit`][Commit] if it is one. + #[allow(clippy::result_large_err)] + pub fn try_into_commit(self) -> Result<Commit, Self> { + match self { + Object::Commit(v) => Ok(v), + _ => Err(self), + } + } + /// Turns this instance into a [`Tree`][Tree] if it is one. + #[allow(clippy::result_large_err)] + pub fn try_into_tree(self) -> Result<Tree, Self> { + match self { + Object::Tree(v) => Ok(v), + _ => Err(self), + } + } + /// Turns this instance into a [`Tag`][Tag] if it is one. + #[allow(clippy::result_large_err)] + pub fn try_into_tag(self) -> Result<Tag, Self> { + match self { + Object::Tag(v) => Ok(v), + _ => Err(self), + } + } + + /// Returns a [`Blob`][Blob] if it is one. + pub fn as_blob(&self) -> Option<&Blob> { + match self { + Object::Blob(v) => Some(v), + _ => None, + } + } + /// Returns a [`Commit`][Commit] if it is one. + pub fn as_commit(&self) -> Option<&Commit> { + match self { + Object::Commit(v) => Some(v), + _ => None, + } + } + /// Returns a [`Tree`][Tree] if it is one. + pub fn as_tree(&self) -> Option<&Tree> { + match self { + Object::Tree(v) => Some(v), + _ => None, + } + } + /// Returns a [`Tag`][Tag] if it is one. + pub fn as_tag(&self) -> Option<&Tag> { + match self { + Object::Tag(v) => Some(v), + _ => None, + } + } + /// Returns the kind of object stored in this instance. + pub fn kind(&self) -> crate::Kind { + match self { + Object::Tree(_) => crate::Kind::Tree, + Object::Blob(_) => crate::Kind::Blob, + Object::Commit(_) => crate::Kind::Commit, + Object::Tag(_) => crate::Kind::Tag, + } + } +} + +use crate::{ + decode::{loose_header, Error as DecodeError, LooseHeaderDecodeError}, + BlobRef, CommitRef, Kind, ObjectRef, TagRef, TreeRef, +}; + +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] +pub enum LooseDecodeError { + #[error(transparent)] + InvalidHeader(#[from] LooseHeaderDecodeError), + #[error(transparent)] + InvalidContent(#[from] DecodeError), +} + +impl<'a> ObjectRef<'a> { + /// Deserialize an object from a loose serialisation + pub fn from_loose(data: &'a [u8]) -> Result<ObjectRef<'a>, LooseDecodeError> { + let (kind, size, offset) = loose_header(data)?; + + let body = &data[offset..] + .get(..size) + .ok_or(LooseHeaderDecodeError::InvalidHeader { + message: "object data was shorter than its size declared in the header", + })?; + + Ok(Self::from_bytes(kind, body)?) + } + + /// Deserialize an object of `kind` from the given `data`. + pub fn from_bytes(kind: Kind, data: &'a [u8]) -> Result<ObjectRef<'a>, crate::decode::Error> { + Ok(match kind { + Kind::Tree => ObjectRef::Tree(TreeRef::from_bytes(data)?), + Kind::Blob => ObjectRef::Blob(BlobRef { data }), + Kind::Commit => ObjectRef::Commit(CommitRef::from_bytes(data)?), + Kind::Tag => ObjectRef::Tag(TagRef::from_bytes(data)?), + }) + } + + /// Convert the immutable object into a mutable version, consuming the source in the process. + /// + /// Note that this is an expensive operation. + pub fn into_owned(self) -> Object { + self.into() + } + + /// Convert this immutable object into its mutable counterpart. + /// + /// Note that this is an expensive operation. + pub fn to_owned(&self) -> Object { + self.clone().into() + } +} + +/// Convenient access to contained objects. +impl<'a> ObjectRef<'a> { + /// Interpret this object as blob. + pub fn as_blob(&self) -> Option<&BlobRef<'a>> { + match self { + ObjectRef::Blob(v) => Some(v), + _ => None, + } + } + /// Interpret this object as blob, chainable. + pub fn into_blob(self) -> Option<BlobRef<'a>> { + match self { + ObjectRef::Blob(v) => Some(v), + _ => None, + } + } + /// Interpret this object as commit. + pub fn as_commit(&self) -> Option<&CommitRef<'a>> { + match self { + ObjectRef::Commit(v) => Some(v), + _ => None, + } + } + /// Interpret this object as commit, chainable. + pub fn into_commit(self) -> Option<CommitRef<'a>> { + match self { + ObjectRef::Commit(v) => Some(v), + _ => None, + } + } + /// Interpret this object as tree. + pub fn as_tree(&self) -> Option<&TreeRef<'a>> { + match self { + ObjectRef::Tree(v) => Some(v), + _ => None, + } + } + /// Interpret this object as tree, chainable + pub fn into_tree(self) -> Option<TreeRef<'a>> { + match self { + ObjectRef::Tree(v) => Some(v), + _ => None, + } + } + /// Interpret this object as tag. + pub fn as_tag(&self) -> Option<&TagRef<'a>> { + match self { + ObjectRef::Tag(v) => Some(v), + _ => None, + } + } + /// Interpret this object as tag, chainable. + pub fn into_tag(self) -> Option<TagRef<'a>> { + match self { + ObjectRef::Tag(v) => Some(v), + _ => None, + } + } + /// Return the kind of object. + pub fn kind(&self) -> Kind { + match self { + ObjectRef::Tree(_) => Kind::Tree, + ObjectRef::Blob(_) => Kind::Blob, + ObjectRef::Commit(_) => Kind::Commit, + ObjectRef::Tag(_) => Kind::Tag, + } + } +} |