diff options
Diffstat (limited to 'vendor/gix-attributes/src/state.rs')
-rw-r--r-- | vendor/gix-attributes/src/state.rs | 84 |
1 files changed, 81 insertions, 3 deletions
diff --git a/vendor/gix-attributes/src/state.rs b/vendor/gix-attributes/src/state.rs index 02dc8ee0d..27ce2a247 100644 --- a/vendor/gix-attributes/src/state.rs +++ b/vendor/gix-attributes/src/state.rs @@ -1,7 +1,85 @@ -use bstr::ByteSlice; +use bstr::{BStr, ByteSlice}; +use kstring::{KString, KStringRef}; use crate::{State, StateRef}; +/// A container to encapsulate a tightly packed and typically unallocated byte value that isn't necessarily UTF8 encoded. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Value(KString); + +/// A reference container to encapsulate a tightly packed and typically unallocated byte value that isn't necessarily UTF8 encoded. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ValueRef<'a>(#[cfg_attr(feature = "serde", serde(borrow))] KStringRef<'a>); + +/// Conversions +impl<'a> ValueRef<'a> { + /// Keep `input` as our value. + pub fn from_bytes(input: &'a [u8]) -> Self { + Self(KStringRef::from_ref( + // SAFETY: our API makes accessing that value as `str` impossible, so illformed UTF8 is never exposed as such. + #[allow(unsafe_code)] + unsafe { + std::str::from_utf8_unchecked(input) + }, + )) + } + + /// Access this value as byte string. + pub fn as_bstr(&self) -> &BStr { + self.0.as_bytes().as_bstr() + } + + /// Convert this instance into its owned form. + pub fn to_owned(self) -> Value { + self.into() + } +} + +impl<'a> From<&'a str> for ValueRef<'a> { + fn from(v: &'a str) -> Self { + ValueRef(v.into()) + } +} + +impl<'a> From<ValueRef<'a>> for Value { + fn from(v: ValueRef<'a>) -> Self { + Value(v.0.into()) + } +} + +impl From<&str> for Value { + fn from(v: &str) -> Self { + Value(KString::from_ref(v)) + } +} + +/// Access +impl Value { + /// Return ourselves as reference. + pub fn as_ref(&self) -> ValueRef<'_> { + ValueRef(self.0.as_ref()) + } +} + +/// Access +impl StateRef<'_> { + /// Return `true` if the associated attribute was set to be unspecified using the `!attr` prefix or it wasn't mentioned. + pub fn is_unspecified(&self) -> bool { + matches!(self, StateRef::Unspecified) + } +} + +/// Initialization +impl<'a> StateRef<'a> { + /// Keep `input` in one of our enums. + pub fn from_bytes(input: &'a [u8]) -> Self { + Self::Value(ValueRef::from_bytes(input)) + } +} + +/// Access impl<'a> StateRef<'a> { /// Turn ourselves into our owned counterpart. pub fn to_owned(self) -> State { @@ -13,7 +91,7 @@ impl<'a> State { /// Turn ourselves into our ref-type. pub fn as_ref(&'a self) -> StateRef<'a> { match self { - State::Value(v) => StateRef::Value(v.as_bytes().as_bstr()), + State::Value(v) => StateRef::Value(v.as_ref()), State::Set => StateRef::Set, State::Unset => StateRef::Unset, State::Unspecified => StateRef::Unspecified, @@ -24,7 +102,7 @@ impl<'a> State { impl<'a> From<StateRef<'a>> for State { fn from(s: StateRef<'a>) -> Self { match s { - StateRef::Value(v) => State::Value(v.to_str().expect("no illformed unicode").into()), + StateRef::Value(v) => State::Value(v.into()), StateRef::Set => State::Set, StateRef::Unset => State::Unset, StateRef::Unspecified => State::Unspecified, |