macro_toolset/string/general/
string.rs

1//! Implementations for string.
2//!
3//! - &str
4//! - &mut str
5//! - &&str
6//! - &mut &str
7//! - &&mut str
8//! - &mut &mut str
9//! - Arc<str>
10//! - Rc<str>
11//! - Box<str>
12//! - Cow<str>
13//! - String
14//! - &String
15//! - &mut String
16//! - &&String
17//! - &mut &String
18
19use std::{borrow::Cow, ops::Deref, rc::Rc, sync::Arc};
20
21use super::{StringExtT, StringT};
22use crate::{impl_for_shared_ref, impl_for_wrapper, wrapper};
23
24macro_rules! impl_for_string {
25    ($($ty:ty),*) => {
26        $(
27            // So ugly, but it works.
28            impl_for_string!(@INTERNAL $ty);
29            impl_for_string!(@INTERNAL &$ty);
30            impl_for_string!(@INTERNAL &mut $ty);
31            impl_for_string!(@INTERNAL &&$ty);
32            impl_for_string!(@INTERNAL &&mut $ty);
33            impl_for_string!(@INTERNAL &mut &$ty);
34            impl_for_string!(@INTERNAL &mut &mut $ty);
35            impl_for_string!(@INTERNAL &&&$ty);
36        )*
37    };
38
39    (@INTERNAL $ty:ty) => {
40        impl StringT for $ty {
41            #[inline]
42            fn encode_to_buf(self, string: &mut Vec<u8>) {
43                string.extend(self.as_bytes());
44            }
45
46            #[inline]
47            fn encode_to_buf_with_separator(self, string: &mut Vec<u8>, separator: &str) {
48                string.extend(self.as_bytes());
49                string.extend(separator.as_bytes());
50            }
51
52            #[inline]
53            fn encode_to_bytes_buf(self, string: &mut bytes::BytesMut) {
54                string.extend(self.as_bytes());
55            }
56
57            #[inline]
58            fn encode_to_bytes_buf_with_separator(self, string: &mut bytes::BytesMut, separator: &str) {
59                string.extend(self.as_bytes());
60                string.extend(separator.as_bytes());
61            }
62        }
63
64        impl StringExtT for $ty {}
65    }
66}
67
68impl_for_string! {
69    &str,
70    Arc<str>,
71    Rc<str>,
72    Box<str>,
73    Cow<'_, str>,
74    String
75}
76
77impl StringT for char {
78    #[inline]
79    fn encode_to_buf(self, string: &mut Vec<u8>) {
80        // ! '�' != "�" in utf8 world. see [`String::push`].
81        match self.len_utf8() {
82            1 => string.push(self as u8),
83            _ => string.extend(self.encode_utf8(&mut [0; 4]).as_bytes()),
84        }
85    }
86
87    #[inline]
88    fn encode_to_buf_with_separator(self, string: &mut Vec<u8>, separator: &str) {
89        self.encode_to_buf(string);
90        string.extend(separator.as_bytes());
91    }
92
93    #[inline]
94    fn encode_to_bytes_buf(self, string: &mut bytes::BytesMut) {
95        // ! '�' != "�" in utf8 world. see [`String::push`].
96        match self.len_utf8() {
97            1 => string.extend([self as u8]),
98            _ => string.extend(self.encode_utf8(&mut [0; 4]).as_bytes()),
99        }
100    }
101
102    fn encode_to_bytes_buf_with_separator(self, string: &mut bytes::BytesMut, separator: &str) {
103        self.encode_to_bytes_buf(string);
104        string.extend(separator.as_bytes());
105    }
106}
107
108impl StringExtT for char {}
109
110impl_for_shared_ref!(COPIED: char);
111
112#[macro_export]
113/// See [`StrWrapper`] and [`StringWrapper`].
114///
115/// # Example
116///
117/// ```
118/// # use std::sync::Arc;
119/// # use macro_toolset::{str_wrapper, string::StringExtT};
120/// let general_str = str_wrapper!(str = "hello");
121/// # assume_string_ext_t(general_str);
122/// let smart_pointer_str = str_wrapper!(str = Arc::<str>::from("hello"));
123/// # assume_string_ext_t(smart_pointer_str);
124/// let general_string = str_wrapper!(str = "hello".to_string());
125/// # assume_string_ext_t(general_string);
126/// let smart_pointer_string = str_wrapper!(string = Arc::<String>::from("hello".to_string()));
127/// # assume_string_ext_t(smart_pointer_string);
128/// # fn assume_string_ext_t<T: StringExtT>(_: T) {}
129/// ```
130macro_rules! str_wrapper {
131    (str = $data:expr) => {
132        $crate::string::general::string::StrWrapper { inner: $data }
133    };
134    (string = $data:expr) => {
135        $crate::string::general::string::StringWrapper { inner: $data }
136    };
137}
138
139wrapper! {
140    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
141    /// Since the compiler will complain that *upstream crates may add a new impl
142    /// of trait *** for type `{I}`*, we have to wrap it with newtype.
143    ///
144    /// Just `StrWrapper::from`.
145    ///
146    /// For `Arc<String>`, etc, use [`StringWrapper`] since it just implements `Deref<Target = String>` but not `Deref<Target = str>`.
147    pub StrWrapper<T>(pub T)
148}
149
150wrapper! {
151    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
152    /// Since the compiler will complain that *upstream crates may add a new impl
153    /// of trait *** for type `{I}`*, we have to wrap it with newtype.
154    ///
155    /// Just `StrWrapper::from`.
156    ///
157    /// For `Arc<str>`, etc, use [`StrWrapper`] since it just implements `Deref<Target = str>` but not `Deref<Target = String>`.
158    pub StringWrapper<T>(pub T)
159}
160
161impl_for_wrapper!(STRING_T: impl<T> StringT for StrWrapper<T> where T: Deref<Target = str>);
162impl_for_wrapper!(STRING_T: impl<T> StringT for StringWrapper<T> where T: Deref<Target = String>);
163impl_for_wrapper!(STRING_EXT_T: impl<T> StringExtT for StrWrapper<T> where T: Deref<Target = str>);
164impl_for_wrapper!(STRING_EXT_T: impl<T> StringExtT for StringWrapper<T> where T: Deref<Target = String>);