use std::{
borrow::{Borrow, BorrowMut, Cow},
cmp::Ordering,
convert::Infallible,
ffi::OsStr,
fmt::{self, Debug, Display},
hash::{Hash, Hasher},
net::{SocketAddr, ToSocketAddrs},
ops::{Add, AddAssign, Deref, DerefMut, Index, IndexMut},
path::Path,
slice::SliceIndex,
str::{FromStr, Utf8Error},
};
use bytes::{Bytes, BytesMut};
#[derive(Clone, Default, PartialEq, Eq)]
pub struct BytesString {
pub(crate) bytes: BytesMut,
}
impl BytesString {
pub fn new() -> Self {
Self {
bytes: BytesMut::new(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
bytes: BytesMut::with_capacity(capacity),
}
}
pub fn len(&self) -> usize {
self.bytes.len()
}
pub fn capacity(&self) -> usize {
self.bytes.capacity()
}
pub fn reserve(&mut self, additional: usize) {
self.bytes.reserve(additional);
}
pub fn split_off(&mut self, at: usize) -> Self {
Self {
bytes: self.bytes.split_off(at),
}
}
pub fn as_bytes(&self) -> &[u8] {
self.bytes.as_ref()
}
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
pub fn truncate(&mut self, new_len: usize) {
if new_len <= self.len() {
assert!(self.is_char_boundary(new_len));
self.bytes.truncate(new_len);
}
}
pub fn clear(&mut self) {
self.bytes.clear();
}
pub fn push(&mut self, ch: char) {
let mut buf = [0; 4];
let bytes = ch.encode_utf8(&mut buf);
self.bytes.extend_from_slice(bytes.as_bytes());
}
pub fn push_str(&mut self, s: &str) {
self.bytes.extend_from_slice(s.as_bytes());
}
pub fn as_str(&self) -> &str {
unsafe { std::str::from_utf8_unchecked(&self.bytes) }
}
pub fn as_mut_str(&mut self) -> &mut str {
unsafe { std::str::from_utf8_unchecked_mut(&mut self.bytes) }
}
pub fn into_bytes(self) -> BytesMut {
self.bytes
}
pub unsafe fn from_bytes_unchecked(bytes: BytesMut) -> Self {
Self { bytes }
}
pub fn from_utf8(bytes: BytesMut) -> Result<Self, Utf8Error> {
std::str::from_utf8(bytes.as_ref())?;
Ok(Self { bytes })
}
pub fn from_utf8_slice(bytes: &[u8]) -> Result<Self, Utf8Error> {
std::str::from_utf8(bytes)?;
Ok(Self {
bytes: BytesMut::from(bytes),
})
}
pub fn into_vec(self) -> Vec<u8> {
self.bytes.into()
}
pub fn into_string(self) -> String {
self.into()
}
}
impl Deref for BytesString {
type Target = str;
fn deref(&self) -> &Self::Target {
self.as_str()
}
}
impl DerefMut for BytesString {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_str()
}
}
impl AsRef<str> for BytesString {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl Borrow<str> for BytesString {
fn borrow(&self) -> &str {
self.as_str()
}
}
impl From<String> for BytesString {
fn from(s: String) -> Self {
Self {
bytes: Bytes::from(s.into_bytes()).into(),
}
}
}
impl From<BytesString> for String {
fn from(s: BytesString) -> Self {
let vec: Vec<_> = s.bytes.freeze().into();
unsafe {
String::from_utf8_unchecked(vec)
}
}
}
impl From<&str> for BytesString {
fn from(s: &str) -> Self {
Self {
bytes: BytesMut::from(s),
}
}
}
impl From<BytesString> for BytesMut {
fn from(s: BytesString) -> Self {
s.bytes
}
}
impl From<BytesString> for Bytes {
fn from(s: BytesString) -> Self {
s.bytes.into()
}
}
impl From<char> for BytesString {
fn from(ch: char) -> Self {
let mut bytes = BytesString::with_capacity(ch.len_utf8());
bytes.push(ch);
bytes
}
}
impl PartialEq<str> for BytesString {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<&'_ str> for BytesString {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl PartialEq<Cow<'_, str>> for BytesString {
fn eq(&self, other: &Cow<'_, str>) -> bool {
self.as_str() == *other
}
}
impl PartialEq<BytesString> for str {
fn eq(&self, other: &BytesString) -> bool {
self == other.as_str()
}
}
impl PartialEq<BytesString> for &'_ str {
fn eq(&self, other: &BytesString) -> bool {
*self == other.as_str()
}
}
impl PartialEq<BytesString> for Bytes {
fn eq(&self, other: &BytesString) -> bool {
self == other.as_bytes()
}
}
impl PartialEq<String> for BytesString {
fn eq(&self, other: &String) -> bool {
self.as_str() == other
}
}
impl PartialEq<BytesString> for String {
fn eq(&self, other: &BytesString) -> bool {
self == other.as_str()
}
}
impl Add<&str> for BytesString {
type Output = Self;
fn add(mut self, other: &str) -> Self::Output {
self += other;
self
}
}
impl AddAssign<&str> for BytesString {
fn add_assign(&mut self, other: &str) {
self.push_str(other);
}
}
impl Add<BytesString> for BytesString {
type Output = Self;
fn add(mut self, other: BytesString) -> Self::Output {
self += other;
self
}
}
impl AddAssign<BytesString> for BytesString {
fn add_assign(&mut self, other: BytesString) {
self.bytes.extend(other.bytes);
}
}
impl AsMut<str> for BytesString {
fn as_mut(&mut self) -> &mut str {
self.as_mut_str()
}
}
impl AsRef<[u8]> for BytesString {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl AsRef<OsStr> for BytesString {
fn as_ref(&self) -> &OsStr {
OsStr::new(self.as_str())
}
}
impl AsRef<Path> for BytesString {
fn as_ref(&self) -> &Path {
Path::new(self.as_str())
}
}
impl BorrowMut<str> for BytesString {
fn borrow_mut(&mut self) -> &mut str {
self.as_mut_str()
}
}
impl Debug for BytesString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(self.as_str(), f)
}
}
impl Display for BytesString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(self.as_str(), f)
}
}
impl PartialOrd for BytesString {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for BytesString {
fn cmp(&self, other: &Self) -> Ordering {
self.as_str().cmp(other.as_str())
}
}
impl<'a> Extend<&'a char> for BytesString {
fn extend<T: IntoIterator<Item = &'a char>>(&mut self, iter: T) {
self.extend(iter.into_iter().copied());
}
}
impl Extend<char> for BytesString {
fn extend<T: IntoIterator<Item = char>>(&mut self, iter: T) {
let mut buf = [0; 4];
for ch in iter {
let bytes = ch.encode_utf8(&mut buf);
self.bytes.extend_from_slice(bytes.as_bytes());
}
}
}
impl<'a> Extend<&'a str> for BytesString {
fn extend<T: IntoIterator<Item = &'a str>>(&mut self, iter: T) {
for s in iter {
self.push_str(s);
}
}
}
impl<'a, 'b> Extend<&'a &'b str> for BytesString {
fn extend<T: IntoIterator<Item = &'a &'b str>>(&mut self, iter: T) {
for s in iter {
self.push_str(s);
}
}
}
impl Extend<Box<str>> for BytesString {
fn extend<T: IntoIterator<Item = Box<str>>>(&mut self, iter: T) {
for s in iter {
self.push_str(&s);
}
}
}
impl<'a> Extend<Cow<'a, str>> for BytesString {
fn extend<T: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: T) {
for s in iter {
self.push_str(&s);
}
}
}
impl Extend<String> for BytesString {
fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
for s in iter {
self.push_str(&s);
}
}
}
impl<'a> Extend<&'a String> for BytesString {
fn extend<T: IntoIterator<Item = &'a String>>(&mut self, iter: T) {
for s in iter {
self.push_str(s);
}
}
}
impl Extend<BytesString> for BytesString {
fn extend<T: IntoIterator<Item = BytesString>>(&mut self, iter: T) {
for s in iter {
self.bytes.extend(s.bytes);
}
}
}
impl FromIterator<char> for BytesString {
fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
let mut bytes = BytesString::new();
bytes.extend(iter);
bytes
}
}
impl<'a> FromIterator<&'a str> for BytesString {
fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
let mut bytes = BytesString::new();
bytes.extend(iter);
bytes
}
}
impl FromIterator<Box<str>> for BytesString {
fn from_iter<T: IntoIterator<Item = Box<str>>>(iter: T) -> Self {
let mut bytes = BytesString::new();
bytes.extend(iter);
bytes
}
}
impl<'a> FromIterator<Cow<'a, str>> for BytesString {
fn from_iter<T: IntoIterator<Item = Cow<'a, str>>>(iter: T) -> Self {
let mut bytes = BytesString::new();
bytes.extend(iter);
bytes
}
}
impl FromIterator<String> for BytesString {
fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
let mut bytes = BytesString::new();
bytes.extend(iter);
bytes
}
}
impl FromIterator<BytesString> for BytesString {
fn from_iter<T: IntoIterator<Item = BytesString>>(iter: T) -> Self {
let mut bytes = BytesString::new();
bytes.extend(iter);
bytes
}
}
impl FromStr for BytesString {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self {
bytes: BytesMut::from(s),
})
}
}
impl<I> Index<I> for BytesString
where
I: SliceIndex<str>,
{
type Output = I::Output;
fn index(&self, index: I) -> &Self::Output {
self.as_str().index(index)
}
}
impl<I> IndexMut<I> for BytesString
where
I: SliceIndex<str>,
{
fn index_mut(&mut self, index: I) -> &mut Self::Output {
self.as_mut_str().index_mut(index)
}
}
impl ToSocketAddrs for BytesString {
type Iter = std::vec::IntoIter<SocketAddr>;
fn to_socket_addrs(&self) -> Result<Self::Iter, std::io::Error> {
self.as_str().to_socket_addrs()
}
}
impl Hash for BytesString {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_str().hash(state);
}
}
impl fmt::Write for BytesString {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.push_str(s);
Ok(())
}
fn write_char(&mut self, c: char) -> fmt::Result {
self.push(c);
Ok(())
}
}
#[cfg(feature = "serde")]
mod serde_impl {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::*;
impl<'de> Deserialize<'de> for BytesString {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Ok(Self::from(s))
}
}
impl Serialize for BytesString {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.as_str())
}
}
}
#[cfg(test)]
mod tests {
use std::{
collections::{hash_map::DefaultHasher, HashMap},
hash::{Hash, Hasher},
};
use super::*;
#[test]
fn test_new() {
let s = BytesString::new();
assert!(s.is_empty());
assert_eq!(s.len(), 0);
assert_eq!(s.as_str(), "");
}
#[test]
fn test_with_capacity() {
let s = BytesString::with_capacity(10);
assert!(s.capacity() >= 10);
assert!(s.is_empty());
assert_eq!(s.len(), 0);
}
#[test]
fn test_from_str() {
let s = BytesString::from("hello");
assert_eq!(s.as_str(), "hello");
assert_eq!(s.len(), 5);
assert!(!s.is_empty());
}
#[test]
fn test_from_string() {
let original = String::from("hello world");
let s = BytesString::from(original);
assert_eq!(s.as_str(), "hello world");
assert_eq!(s.len(), 11);
}
#[test]
fn test_from_char() {
let s = BytesString::from('H');
assert_eq!(s.as_str(), "H");
assert_eq!(s.len(), 1);
let s = BytesString::from('한');
assert_eq!(s.as_str(), "한");
assert_eq!(s.len(), 3); }
#[test]
fn test_push() {
let mut s = BytesString::from("hello");
s.push(' ');
s.push('w');
assert_eq!(s.as_str(), "hello w");
s.push('한');
assert_eq!(s.as_str(), "hello w한");
}
#[test]
fn test_push_str() {
let mut s = BytesString::from("hello");
s.push_str(" world");
assert_eq!(s.as_str(), "hello world");
s.push_str("!");
assert_eq!(s.as_str(), "hello world!");
s.push_str(" 한국어");
assert_eq!(s.as_str(), "hello world! 한국어");
}
#[test]
fn test_clear() {
let mut s = BytesString::from("hello");
assert!(!s.is_empty());
s.clear();
assert!(s.is_empty());
assert_eq!(s.len(), 0);
assert_eq!(s.as_str(), "");
}
#[test]
fn test_truncate() {
let mut s = BytesString::from("hello world");
s.truncate(5);
assert_eq!(s.as_str(), "hello");
s.truncate(20);
assert_eq!(s.as_str(), "hello");
let mut s = BytesString::from("한국어");
s.truncate(6); assert_eq!(s.as_str(), "한국");
}
#[test]
#[should_panic]
fn test_truncate_panic_on_char_boundary() {
let mut s = BytesString::from("한국어");
s.truncate(1); }
#[test]
fn test_split_off() {
let mut s = BytesString::from("hello world");
let other = s.split_off(6);
assert_eq!(s.as_str(), "hello ");
assert_eq!(other.as_str(), "world");
let mut s = BytesString::from("hello");
let other = s.split_off(0);
assert_eq!(s.as_str(), "");
assert_eq!(other.as_str(), "hello");
let mut s = BytesString::from("hello");
let other = s.split_off(5);
assert_eq!(s.as_str(), "hello");
assert_eq!(other.as_str(), "");
}
#[test]
fn test_as_bytes() {
let s = BytesString::from("hello");
assert_eq!(s.as_bytes(), b"hello");
let s = BytesString::from("한국어");
assert_eq!(s.as_bytes(), "한국어".as_bytes());
}
#[test]
fn test_as_mut_str() {
let mut s = BytesString::from("hello");
s.as_mut_str().make_ascii_uppercase();
assert_eq!(s.as_str(), "HELLO");
}
#[test]
fn test_into_bytes() {
let s = BytesString::from("hello");
let bytes = s.into_bytes();
assert_eq!(bytes.as_ref(), b"hello");
}
#[test]
fn test_from_utf8() {
let bytes = BytesMut::from(&b"hello"[..]);
let s = BytesString::from_utf8(bytes).unwrap();
assert_eq!(s.as_str(), "hello");
let invalid_bytes = BytesMut::from(&[0xff, 0xfe][..]);
assert!(BytesString::from_utf8(invalid_bytes).is_err());
}
#[test]
fn test_from_utf8_slice() {
let s = BytesString::from_utf8_slice(b"hello").unwrap();
assert_eq!(s.as_str(), "hello");
assert!(BytesString::from_utf8_slice(&[0xff, 0xfe]).is_err());
}
#[test]
fn test_from_bytes_unchecked() {
let bytes = BytesMut::from(&b"hello"[..]);
let s = unsafe { BytesString::from_bytes_unchecked(bytes) };
assert_eq!(s.as_str(), "hello");
}
#[test]
fn test_reserve() {
let mut s = BytesString::from("hello");
let initial_capacity = s.capacity();
s.reserve(100);
assert!(s.capacity() >= initial_capacity + 100);
assert_eq!(s.as_str(), "hello"); }
#[test]
fn test_deref() {
let s = BytesString::from("hello world");
assert_eq!(s.len(), 11);
assert!(s.contains("world"));
assert!(s.starts_with("hello"));
assert!(s.ends_with("world"));
}
#[test]
fn test_partial_eq() {
let s = BytesString::from("hello");
assert_eq!(s, "hello");
assert_ne!(s, "world");
assert_eq!(s, String::from("hello"));
assert_ne!(s, String::from("world"));
assert_eq!(s, Cow::Borrowed("hello"));
assert_eq!(s, Cow::Owned(String::from("hello")));
assert_eq!(Bytes::from("hello"), s);
assert_ne!(Bytes::from("world"), s);
assert_eq!("hello", s);
assert_eq!(String::from("hello"), s);
}
#[test]
fn test_ordering() {
let s1 = BytesString::from("apple");
let s2 = BytesString::from("banana");
let s3 = BytesString::from("apple");
assert!(s1 < s2);
assert!(s2 > s1);
assert_eq!(s1, s3);
assert!(s1 <= s3);
assert!(s1 >= s3);
}
#[test]
fn test_hash() {
let s1 = BytesString::from("hello");
let s2 = BytesString::from("hello");
let s3 = BytesString::from("world");
let mut hasher1 = DefaultHasher::new();
let mut hasher2 = DefaultHasher::new();
let mut hasher3 = DefaultHasher::new();
s1.hash(&mut hasher1);
s2.hash(&mut hasher2);
s3.hash(&mut hasher3);
assert_eq!(hasher1.finish(), hasher2.finish());
assert_ne!(hasher1.finish(), hasher3.finish());
let mut str_hasher = DefaultHasher::new();
"hello".hash(&mut str_hasher);
assert_eq!(hasher1.finish(), str_hasher.finish());
}
#[test]
fn test_add() {
let s1 = BytesString::from("hello");
let s2 = s1 + " world";
assert_eq!(s2.as_str(), "hello world");
let s3 = BytesString::from("foo");
let s4 = BytesString::from("bar");
let s5 = s3 + s4;
assert_eq!(s5.as_str(), "foobar");
}
#[test]
fn test_add_assign() {
let mut s = BytesString::from("hello");
s += " world";
assert_eq!(s.as_str(), "hello world");
let mut s1 = BytesString::from("foo");
let s2 = BytesString::from("bar");
s1 += s2;
assert_eq!(s1.as_str(), "foobar");
}
#[test]
fn test_extend_char() {
let mut s = BytesString::from("hello");
s.extend(['!', ' ', '🎉'].iter());
assert_eq!(s.as_str(), "hello! 🎉");
let mut s = BytesString::new();
s.extend(['a', 'b', 'c']);
assert_eq!(s.as_str(), "abc");
}
#[test]
fn test_extend_str() {
let mut s = BytesString::from("hello");
s.extend([" ", "world", "!"].iter());
assert_eq!(s.as_str(), "hello world!");
let strings = vec![String::from("foo"), String::from("bar")];
let mut s = BytesString::new();
s.extend(&strings);
assert_eq!(s.as_str(), "foobar");
}
#[test]
fn test_extend_bytes_string() {
let mut s = BytesString::from("hello");
let parts = vec![BytesString::from(" "), BytesString::from("world")];
s.extend(parts);
assert_eq!(s.as_str(), "hello world");
}
#[test]
fn test_from_iterator() {
let s: BytesString = ['h', 'e', 'l', 'l', 'o'].into_iter().collect();
assert_eq!(s.as_str(), "hello");
let s: BytesString = ["hello", " ", "world"].into_iter().collect();
assert_eq!(s.as_str(), "hello world");
let strings = vec![String::from("foo"), String::from("bar")];
let s: BytesString = strings.into_iter().collect();
assert_eq!(s.as_str(), "foobar");
}
#[test]
fn test_from_str_trait() {
let s: BytesString = "hello world".parse().unwrap();
assert_eq!(s.as_str(), "hello world");
}
#[test]
fn test_index() {
let s = BytesString::from("hello world");
assert_eq!(&s[0..5], "hello");
assert_eq!(&s[6..], "world");
assert_eq!(&s[..5], "hello");
assert_eq!(&s[6..11], "world");
}
#[test]
fn test_index_mut() {
let mut s = BytesString::from("hello world");
s[0..5].make_ascii_uppercase();
assert_eq!(s.as_str(), "HELLO world");
}
#[test]
fn test_as_ref_implementations() {
let s = BytesString::from("hello/world");
let str_ref: &str = s.as_ref();
assert_eq!(str_ref, "hello/world");
let bytes_ref: &[u8] = s.as_ref();
assert_eq!(bytes_ref, b"hello/world");
let os_str_ref: &OsStr = s.as_ref();
assert_eq!(os_str_ref, OsStr::new("hello/world"));
let path_ref: &Path = s.as_ref();
assert_eq!(path_ref, Path::new("hello/world"));
}
#[test]
fn test_borrow() {
let s = BytesString::from("hello");
let borrowed: &str = s.borrow();
assert_eq!(borrowed, "hello");
let mut s = BytesString::from("hello");
let borrowed_mut: &mut str = s.borrow_mut();
borrowed_mut.make_ascii_uppercase();
assert_eq!(s.as_str(), "HELLO");
}
#[test]
fn test_debug() {
let s = BytesString::from("hello");
assert_eq!(format!("{:?}", s), "\"hello\"");
}
#[test]
fn test_display() {
let s = BytesString::from("hello world");
assert_eq!(format!("{}", s), "hello world");
}
#[test]
fn test_conversions() {
let s = BytesString::from("hello");
let bytes_mut: BytesMut = s.clone().into();
assert_eq!(bytes_mut.as_ref(), b"hello");
let bytes: Bytes = s.into();
assert_eq!(bytes.as_ref(), b"hello");
}
#[test]
fn test_to_socket_addrs() {
let s = BytesString::from("127.0.0.1:8080");
let addrs: Vec<_> = s.to_socket_addrs().unwrap().collect();
assert!(!addrs.is_empty());
let s = BytesString::from("localhost:8080");
let result = s.to_socket_addrs();
let _ = result;
}
#[test]
fn test_unicode_handling() {
let s = BytesString::from("Hello 🌍 한국어 🎉");
assert_eq!(s.as_str(), "Hello 🌍 한국어 🎉");
assert!(s.len() > 13);
let mut s = BytesString::new();
s.push('🌍');
s.push_str(" 한국어");
assert_eq!(s.as_str(), "🌍 한국어");
}
#[test]
fn test_empty_operations() {
let mut s = BytesString::new();
assert!(s.is_empty());
s.push_str("");
assert!(s.is_empty());
s.clear();
assert!(s.is_empty());
let other = s.split_off(0);
assert!(s.is_empty());
assert!(other.is_empty());
}
#[test]
fn test_large_string() {
let large_str = "a".repeat(10000);
let s = BytesString::from(large_str.as_str());
assert_eq!(s.len(), 10000);
assert_eq!(s.as_str(), large_str);
let mut s = BytesString::with_capacity(10000);
for _ in 0..10000 {
s.push('a');
}
assert_eq!(s.len(), 10000);
assert_eq!(s.as_str(), large_str);
}
#[test]
fn test_clone() {
let s1 = BytesString::from("hello world");
let s2 = s1.clone();
assert_eq!(s1, s2);
assert_eq!(s1.as_str(), s2.as_str());
}
#[test]
fn test_default() {
let s: BytesString = Default::default();
assert!(s.is_empty());
assert_eq!(s.as_str(), "");
}
#[test]
fn test_hash_map_usage() {
let mut map = HashMap::new();
let key = BytesString::from("key");
map.insert(key, "value");
let lookup_key = BytesString::from("key");
assert_eq!(map.get(&lookup_key), Some(&"value"));
assert_eq!(map.get("key"), Some(&"value"));
}
}