use crate::{BytesRef, DecodeValue, EncodeValue, Error, Header, Length, Reader, Result, Writer};
use core::str;
#[derive(Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct StringRef(str);
impl StringRef {
pub const fn new(s: &str) -> Result<&Self> {
match Length::new_usize(s.len()) {
Ok(_) => Ok(Self::new_unchecked(s)),
Err(err) => Err(err),
}
}
pub(crate) const fn new_unchecked(s: &str) -> &Self {
#[allow(unsafe_code)]
unsafe {
&*(core::ptr::from_ref::<str>(s) as *const Self)
}
}
pub fn from_bytes(bytes: &[u8]) -> Result<&Self> {
Self::new(str::from_utf8(bytes)?)
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn len(&self) -> Length {
debug_assert!(u32::try_from(self.0.len()).is_ok());
#[allow(clippy::cast_possible_truncation)] Length::new(self.0.len() as u32)
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl AsRef<str> for StringRef {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl AsRef<[u8]> for StringRef {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl AsRef<BytesRef> for StringRef {
fn as_ref(&self) -> &BytesRef {
BytesRef::new_unchecked(self.as_bytes())
}
}
impl<'a> DecodeValue<'a> for &'a StringRef {
type Error = Error;
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
StringRef::from_bytes(<&'a BytesRef>::decode_value(reader, header)?.as_slice())
}
}
impl EncodeValue for StringRef {
fn value_len(&self) -> Result<Length> {
Ok(self.len())
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.as_ref())
}
}
#[cfg(feature = "alloc")]
pub(crate) mod allocating {
use super::StringRef;
use crate::{
BytesRef, DecodeValue, EncodeValue, Error, Header, Length, Reader, Result, Writer,
};
use alloc::{borrow::ToOwned, string::String};
use core::{borrow::Borrow, ops::Deref, str};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct StringOwned {
pub(crate) inner: String,
pub(crate) length: Length,
}
impl StringOwned {
pub fn new(s: String) -> Result<Self> {
let length = Length::try_from(s.len())?;
Ok(Self { inner: s, length })
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
Ok(Self {
inner: String::from_utf8(bytes.to_vec())?,
length: Length::try_from(bytes.len())?,
})
}
pub fn as_str(&self) -> &str {
&self.inner
}
pub fn as_bytes(&self) -> &[u8] {
self.inner.as_bytes()
}
pub fn len(&self) -> Length {
self.length
}
pub fn is_empty(&self) -> bool {
self.len() == Length::ZERO
}
}
impl AsRef<str> for StringOwned {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl AsRef<[u8]> for StringOwned {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl AsRef<BytesRef> for StringOwned {
fn as_ref(&self) -> &BytesRef {
BytesRef::new_unchecked(self.as_bytes())
}
}
impl AsRef<StringRef> for StringOwned {
fn as_ref(&self) -> &StringRef {
StringRef::new_unchecked(&self.inner)
}
}
impl Borrow<StringRef> for StringOwned {
fn borrow(&self) -> &StringRef {
StringRef::new_unchecked(&self.inner)
}
}
impl Deref for StringOwned {
type Target = StringRef;
fn deref(&self) -> &StringRef {
self.borrow()
}
}
impl<'a> DecodeValue<'a> for StringOwned {
type Error = Error;
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
Self::from_bytes(<&'a BytesRef>::decode_value(reader, header)?.as_slice())
}
}
impl EncodeValue for StringOwned {
fn value_len(&self) -> Result<Length> {
Ok(self.length)
}
fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
writer.write(self.as_ref())
}
}
impl ToOwned for StringRef {
type Owned = StringOwned;
fn to_owned(&self) -> StringOwned {
StringOwned {
inner: self.as_str().into(),
length: self.len(),
}
}
}
}