1
0
mirror of https://github.com/fafhrd91/actix-net synced 2025-01-31 16:10:08 +01:00

465 lines
12 KiB
Rust
Raw Normal View History

2020-04-26 20:11:16 +01:00
//! A UTF-8 encoded read-only string using Bytes as storage.
#![no_std]
#![deny(rust_2018_idioms, nonstandard_style)]
2021-12-08 06:09:46 +00:00
#![warn(future_incompatible, missing_docs)]
extern crate alloc;
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};
2023-04-01 22:45:18 +01:00
use core::{borrow::Borrow, convert::TryFrom, fmt, hash, ops, str};
2019-12-07 09:59:39 +06:00
use bytes::Bytes;
/// An immutable UTF-8 encoded string with [`Bytes`] as a storage.
#[derive(Clone, Default, Eq, PartialOrd, Ord)]
2019-12-07 09:59:39 +06:00
pub struct ByteString(Bytes);
impl ByteString {
/// Creates a new empty `ByteString`.
pub const fn new() -> Self {
ByteString(Bytes::new())
2019-12-07 09:59:39 +06:00
}
/// Get a reference to the underlying `Bytes` object.
pub fn as_bytes(&self) -> &Bytes {
2019-12-07 09:59:39 +06:00
&self.0
}
/// Unwraps this `ByteString` into the underlying `Bytes` object.
pub fn into_bytes(self) -> Bytes {
2019-12-07 09:59:39 +06:00
self.0
}
/// Creates a new `ByteString` from a `&'static str`.
pub const fn from_static(src: &'static str) -> ByteString {
Self(Bytes::from_static(src.as_bytes()))
2019-12-07 09:59:39 +06:00
}
2019-12-07 10:48:22 +06:00
/// Creates a new `ByteString` from a Bytes.
///
/// # Safety
/// This function is unsafe because it does not check the bytes passed to it are valid UTF-8.
/// If this constraint is violated, it may cause memory unsafety issues with future users of
/// the `ByteString`, as we assume that `ByteString`s are valid UTF-8. However, the most likely
/// issue is that the data gets corrupted.
pub const unsafe fn from_bytes_unchecked(src: Bytes) -> ByteString {
2019-12-07 10:48:22 +06:00
Self(src)
}
2022-11-08 04:16:46 +08:00
2023-02-26 16:24:48 +00:00
/// Returns a new byte string that is equivalent to the given `subset`.
2022-11-08 04:16:46 +08:00
///
2022-11-07 20:21:57 +00:00
/// When processing a `ByteString` buffer with other tools, one often gets a `&str` which is in
2023-02-26 16:24:48 +00:00
/// fact a slice of the original `ByteString`; i.e., a subset of it. This function turns that
/// `&str` into another `ByteString`, as if one had sliced the `ByteString` with the offsets
/// that correspond to `subset`.
2022-11-07 20:21:57 +00:00
///
/// Corresponds to [`Bytes::slice_ref`].
2022-11-08 04:16:46 +08:00
///
/// This operation is `O(1)`.
///
2022-11-07 20:21:57 +00:00
/// # Panics
2023-02-26 16:24:48 +00:00
///
/// Panics if `subset` is not a sub-slice of this byte string.
///
/// Note that strings which are only subsets from an equality perspective do not uphold this
/// requirement; see examples.
2022-11-08 04:16:46 +08:00
///
2022-11-07 20:21:57 +00:00
/// # Examples
2023-02-26 16:24:48 +00:00
///
2022-11-08 04:16:46 +08:00
/// ```
2022-11-07 20:21:57 +00:00
/// # use bytestring::ByteString;
2022-11-08 04:16:46 +08:00
/// let string = ByteString::from_static(" foo ");
/// let subset = string.trim();
/// let substring = string.slice_ref(subset);
/// assert_eq!(substring, "foo");
/// ```
2023-02-26 16:24:48 +00:00
///
/// ```should_panic
/// # use bytestring::ByteString;
/// // panics because the given slice is not derived from the original byte string, despite
/// // being a logical subset of the string
/// ByteString::from_static("foo bar").slice_ref("foo");
/// ```
2022-11-08 04:16:46 +08:00
pub fn slice_ref(&self, subset: &str) -> Self {
Self(self.0.slice_ref(subset.as_bytes()))
}
2019-12-07 09:59:39 +06:00
}
impl PartialEq<str> for ByteString {
fn eq(&self, other: &str) -> bool {
&self[..] == other
}
}
impl<T: AsRef<str>> PartialEq<T> for ByteString {
fn eq(&self, other: &T) -> bool {
&self[..] == other.as_ref()
}
}
2023-02-26 16:24:48 +00:00
impl AsRef<ByteString> for ByteString {
fn as_ref(&self) -> &ByteString {
self
}
}
impl AsRef<[u8]> for ByteString {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
2020-01-14 15:06:02 -08:00
impl AsRef<str> for ByteString {
fn as_ref(&self) -> &str {
2022-07-23 01:51:12 +02:00
self
2020-01-14 15:06:02 -08:00
}
}
2019-12-07 09:59:39 +06:00
impl hash::Hash for ByteString {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
2019-12-07 11:51:47 +06:00
(**self).hash(state);
2019-12-07 09:59:39 +06:00
}
}
impl ops::Deref for ByteString {
type Target = str;
#[inline]
fn deref(&self) -> &str {
let bytes = self.0.as_ref();
2023-04-01 22:45:18 +01:00
// SAFETY: UTF-8 validity is guaranteed during construction.
unsafe { str::from_utf8_unchecked(bytes) }
2019-12-07 09:59:39 +06:00
}
}
2023-04-01 22:45:18 +01:00
impl Borrow<str> for ByteString {
2019-12-07 09:59:39 +06:00
fn borrow(&self) -> &str {
2022-07-23 01:51:12 +02:00
self
2019-12-07 09:59:39 +06:00
}
}
impl From<String> for ByteString {
#[inline]
2019-12-07 09:59:39 +06:00
fn from(value: String) -> Self {
Self(Bytes::from(value))
}
}
impl From<&str> for ByteString {
#[inline]
fn from(value: &str) -> Self {
2019-12-07 09:59:39 +06:00
Self(Bytes::copy_from_slice(value.as_ref()))
}
}
impl From<Box<str>> for ByteString {
#[inline]
fn from(value: Box<str>) -> Self {
Self(Bytes::from(value.into_boxed_bytes()))
}
}
impl From<ByteString> for String {
#[inline]
fn from(value: ByteString) -> Self {
value.to_string()
}
}
impl TryFrom<&[u8]> for ByteString {
2019-12-07 09:59:39 +06:00
type Error = str::Utf8Error;
#[inline]
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
2019-12-07 09:59:39 +06:00
let _ = str::from_utf8(value)?;
Ok(ByteString(Bytes::copy_from_slice(value)))
}
}
impl TryFrom<Vec<u8>> for ByteString {
type Error = str::Utf8Error;
#[inline]
2019-12-07 09:59:39 +06:00
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
let buf = String::from_utf8(value).map_err(|err| err.utf8_error())?;
Ok(ByteString(Bytes::from(buf)))
2019-12-07 09:59:39 +06:00
}
}
2019-12-07 10:22:08 +06:00
impl TryFrom<Bytes> for ByteString {
type Error = str::Utf8Error;
#[inline]
2019-12-07 10:22:08 +06:00
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
let _ = str::from_utf8(value.as_ref())?;
Ok(ByteString(value))
}
}
impl TryFrom<bytes::BytesMut> for ByteString {
type Error = str::Utf8Error;
#[inline]
2019-12-07 10:22:08 +06:00
fn try_from(value: bytes::BytesMut) -> Result<Self, Self::Error> {
let _ = str::from_utf8(&value)?;
2019-12-07 10:22:08 +06:00
Ok(ByteString(value.freeze()))
}
}
2019-12-07 09:59:39 +06:00
macro_rules! array_impls {
($($len:expr)+) => {
$(
impl TryFrom<[u8; $len]> for ByteString {
2019-12-07 09:59:39 +06:00
type Error = str::Utf8Error;
#[inline]
fn try_from(value: [u8; $len]) -> Result<Self, Self::Error> {
ByteString::try_from(&value[..])
}
}
impl TryFrom<&[u8; $len]> for ByteString {
type Error = str::Utf8Error;
#[inline]
fn try_from(value: &[u8; $len]) -> Result<Self, Self::Error> {
2019-12-07 09:59:39 +06:00
ByteString::try_from(&value[..])
}
}
)+
}
}
array_impls!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32);
2019-12-07 09:59:39 +06:00
impl fmt::Debug for ByteString {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2019-12-07 09:59:39 +06:00
(**self).fmt(fmt)
}
}
impl fmt::Display for ByteString {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2019-12-07 09:59:39 +06:00
(**self).fmt(fmt)
}
}
2020-03-30 11:54:40 +06:00
#[cfg(feature = "serde")]
mod serde {
use alloc::string::String;
2020-03-30 11:54:40 +06:00
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use super::ByteString;
impl Serialize for ByteString {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.as_ref())
}
}
impl<'de> Deserialize<'de> for ByteString {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
String::deserialize(deserializer).map(ByteString::from)
}
}
2021-11-25 03:29:30 +00:00
#[cfg(test)]
mod serde_impl_tests {
use serde::de::DeserializeOwned;
use static_assertions::assert_impl_all;
2022-04-10 02:48:53 +01:00
use super::*;
2021-11-25 03:29:30 +00:00
assert_impl_all!(ByteString: Serialize, DeserializeOwned);
}
2020-03-30 11:54:40 +06:00
}
2019-12-07 09:59:39 +06:00
#[cfg(test)]
mod test {
2023-04-01 22:45:18 +01:00
use alloc::{borrow::ToOwned, format, vec};
2023-02-26 16:24:48 +00:00
use core::{
hash::{Hash, Hasher},
panic::{RefUnwindSafe, UnwindSafe},
};
2021-01-03 04:42:08 +00:00
use ahash::AHasher;
2021-11-25 03:29:30 +00:00
use static_assertions::assert_impl_all;
2019-12-07 09:59:39 +06:00
use super::*;
2019-12-07 11:51:47 +06:00
2021-11-25 03:29:30 +00:00
assert_impl_all!(ByteString: Send, Sync, Unpin, Sized);
assert_impl_all!(ByteString: Clone, Default, Eq, PartialOrd, Ord);
assert_impl_all!(ByteString: fmt::Debug, fmt::Display);
2023-02-26 16:24:48 +00:00
assert_impl_all!(ByteString: UnwindSafe, RefUnwindSafe);
#[test]
2023-04-01 22:45:18 +01:00
fn eq() {
let s: ByteString = ByteString::from_static("test");
assert_eq!(s, "test");
assert_eq!(s, *"test");
assert_eq!(s, "test".to_owned());
}
#[test]
2023-04-01 22:45:18 +01:00
fn new() {
let _: ByteString = ByteString::new();
}
2019-12-07 11:51:47 +06:00
#[test]
2023-04-01 22:45:18 +01:00
fn as_bytes() {
let buf = ByteString::new();
assert!(buf.as_bytes().is_empty());
let buf = ByteString::from("hello");
assert_eq!(buf.as_bytes(), "hello");
}
#[test]
fn from_bytes_unchecked() {
let buf = unsafe { ByteString::from_bytes_unchecked(Bytes::new()) };
assert!(buf.is_empty());
let buf = unsafe { ByteString::from_bytes_unchecked(Bytes::from("hello")) };
assert_eq!(buf, "hello");
}
#[test]
fn as_ref() {
let buf = ByteString::new();
let _: &ByteString = buf.as_ref();
let _: &[u8] = buf.as_ref();
}
#[test]
fn borrow() {
let buf = ByteString::new();
let _: &str = buf.borrow();
}
#[test]
fn hash() {
2021-01-03 04:42:08 +00:00
let mut hasher1 = AHasher::default();
2019-12-07 11:51:47 +06:00
"str".hash(&mut hasher1);
2021-01-03 04:42:08 +00:00
let mut hasher2 = AHasher::default();
2019-12-07 11:51:47 +06:00
let s = ByteString::from_static("str");
s.hash(&mut hasher2);
assert_eq!(hasher1.finish(), hasher2.finish());
}
2019-12-07 09:59:39 +06:00
#[test]
2023-04-01 22:45:18 +01:00
fn from_string() {
let s: ByteString = "hello".to_owned().into();
2019-12-07 09:59:39 +06:00
assert_eq!(&s, "hello");
2020-01-14 15:06:02 -08:00
let t: &str = s.as_ref();
assert_eq!(t, "hello");
2019-12-07 09:59:39 +06:00
}
#[test]
2023-04-01 22:45:18 +01:00
fn from_str() {
2019-12-07 09:59:39 +06:00
let _: ByteString = "str".into();
2023-04-01 22:45:18 +01:00
let _: ByteString = "str".to_owned().into_boxed_str().into();
2019-12-07 09:59:39 +06:00
}
#[test]
2023-04-01 22:45:18 +01:00
fn to_string() {
let buf = ByteString::from("foo");
assert_eq!(String::from(buf), "foo");
}
#[test]
fn from_static_str() {
2020-01-28 20:27:33 +09:00
static _S: ByteString = ByteString::from_static("hello");
2019-12-07 09:59:39 +06:00
let _ = ByteString::from_static("str");
}
#[test]
2023-04-01 22:45:18 +01:00
fn try_from_slice() {
2019-12-07 09:59:39 +06:00
let _ = ByteString::try_from(b"nice bytes").unwrap();
}
2019-12-07 10:22:08 +06:00
#[test]
2023-04-01 22:45:18 +01:00
fn try_from_array() {
assert_eq!(
ByteString::try_from([b'h', b'i']).unwrap(),
ByteString::from_static("hi")
);
}
2019-12-07 10:22:08 +06:00
#[test]
2023-04-01 22:45:18 +01:00
fn try_from_vec() {
let _ = ByteString::try_from(vec![b'f', b'o', b'o']).unwrap();
ByteString::try_from(vec![0, 159, 146, 150]).unwrap_err();
}
#[test]
fn try_from_bytes() {
2019-12-07 10:22:08 +06:00
let _ = ByteString::try_from(Bytes::from_static(b"nice bytes")).unwrap();
}
#[test]
2023-04-01 22:45:18 +01:00
fn try_from_bytes_mut() {
2019-12-07 10:22:08 +06:00
let _ = ByteString::try_from(bytes::BytesMut::from(&b"nice bytes"[..])).unwrap();
}
2020-03-30 11:54:40 +06:00
2023-04-01 22:45:18 +01:00
#[test]
fn display() {
let buf = ByteString::from("bar");
assert_eq!(format!("{buf}"), "bar");
}
#[test]
fn debug() {
let buf = ByteString::from("baz");
assert_eq!(format!("{buf:?}"), r#""baz""#);
}
2020-03-30 11:54:40 +06:00
#[cfg(feature = "serde")]
#[test]
2023-04-01 22:45:18 +01:00
fn serialize() {
2020-03-30 11:54:40 +06:00
let s: ByteString = serde_json::from_str(r#""nice bytes""#).unwrap();
assert_eq!(s, "nice bytes");
}
#[cfg(feature = "serde")]
#[test]
2023-04-01 22:45:18 +01:00
fn deserialize() {
2020-03-30 11:54:40 +06:00
let s = serde_json::to_string(&ByteString::from_static("nice bytes")).unwrap();
assert_eq!(s, r#""nice bytes""#);
}
2022-11-08 04:16:46 +08:00
2023-02-26 16:24:48 +00:00
#[test]
fn slice_ref() {
let string = ByteString::from_static(" foo ");
let subset = string.trim();
// subset is derived from original byte string
let substring = string.slice_ref(subset);
assert_eq!(substring, "foo");
}
2022-11-08 04:16:46 +08:00
#[test]
#[should_panic]
2023-04-01 22:45:18 +01:00
fn slice_ref_catches_not_a_subset() {
2023-02-26 16:24:48 +00:00
// panics because the given slice is not derived from the original byte string, despite
// being a logical subset of the string
2022-11-08 04:16:46 +08:00
ByteString::from_static("foo bar").slice_ref("foo");
}
2019-12-07 09:59:39 +06:00
}