1 #![deny(warnings, missing_docs, missing_debug_implementations)] 2 #![doc(html_root_url = "https://docs.rs/string/0.2.1")] 3 4 //! A UTF-8 encoded string with configurable byte storage. 5 //! 6 //! This crate provides `String`, a type similar to its std counterpart, but 7 //! with one significant difference: the underlying byte storage is 8 //! configurable. In other words, `String<T>` is a marker type wrapping `T`, 9 //! indicating that it represents a UTF-8 encoded string. 10 //! 11 //! For example, one can represent small strings (stack allocated) by wrapping 12 //! an array: 13 //! 14 //! ``` 15 //! # use string::*; 16 //! let s: String<[u8; 2]> = String::try_from([b'h', b'i']).unwrap(); 17 //! assert_eq!(&s[..], "hi"); 18 //! ``` 19 20 #[cfg(feature = "bytes")] 21 extern crate bytes; 22 23 use std::{borrow, fmt, hash, ops, str}; 24 use std::default::Default; 25 26 /// A UTF-8 encoded string with configurable byte storage. 27 /// 28 /// This type differs from `std::String` in that it is generic over the 29 /// underlying byte storage, enabling it to use `Vec<[u8]>`, `&[u8]`, or third 30 /// party types, such as [`Bytes`]. 31 /// 32 /// In order to construct `String` via any of the non-unsafe constructors, 33 /// the backing storage needs to implement the `StableAsRef` marker trait. 34 /// If you wish to construct `String` with a type that does not implement `StableAsRef`, 35 /// you can use the `from_utf8_unchecked` constructor. 36 /// 37 /// [`Bytes`]: https://docs.rs/bytes/0.4.8/bytes/struct.Bytes.html 38 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd)] 39 pub struct String<T = Vec<u8>> { 40 value: T, 41 } 42 43 impl<T> String<T> { 44 /// Get a reference to the underlying byte storage. 45 /// 46 /// # Examples 47 /// 48 /// ``` 49 /// # use string::*; 50 /// let s = String::new(); 51 /// let vec = s.get_ref(); 52 /// ``` get_ref(&self) -> &T53 pub fn get_ref(&self) -> &T { 54 &self.value 55 } 56 57 /// Get a mutable reference to the underlying byte storage. 58 /// 59 /// It is inadvisable to directly manipulate the byte storage. This function 60 /// is unsafe as the bytes could no longer be valid UTF-8 after mutation. 61 /// 62 /// # Examples 63 /// 64 /// ``` 65 /// # use string::*; 66 /// let mut s = String::new(); 67 /// 68 /// unsafe { 69 /// let vec = s.get_mut(); 70 /// } 71 /// ``` get_mut(&mut self) -> &mut T72 pub unsafe fn get_mut(&mut self) -> &mut T { 73 &mut self.value 74 } 75 76 /// Unwraps this `String`, returning the underlying byte storage. 77 /// 78 /// # Examples 79 /// 80 /// ``` 81 /// # use string::*; 82 /// let s = String::new(); 83 /// let vec = s.into_inner(); 84 /// ``` into_inner(self) -> T85 pub fn into_inner(self) -> T { 86 self.value 87 } 88 89 /// Creates a new `String` from a &str. 90 /// 91 /// Use `TryFrom` for conversion from &[u8]. 92 /// 93 /// ``` 94 /// # use string::*; 95 /// let _: String<Vec<u8>> = String::from_str("nice str"); 96 /// ``` from_str<'a>(src: &'a str) -> String<T> where T: From<&'a [u8]> + StableAsRef,97 pub fn from_str<'a>(src: &'a str) -> String<T> 98 where T: From<&'a [u8]> + StableAsRef, 99 { 100 let value: T = src.as_bytes().into(); 101 Self { value } 102 } 103 } 104 105 impl String { 106 /// Creates a new empty `String`. 107 /// 108 /// Given that the `String` is empty, this will not allocate. 109 /// 110 /// # Examples 111 /// 112 /// Basic usage 113 /// 114 /// ``` 115 /// let s = String::new(); 116 /// assert_eq!(s, ""); 117 /// ``` new() -> String118 pub fn new() -> String { 119 String::default() 120 } 121 } 122 123 impl<T> String<T> 124 where T: AsRef<[u8]>, 125 { 126 /// Converts the provided value to a `String` without checking that the 127 /// given value is valid UTF-8. 128 /// 129 /// Use `TryFrom` for a safe conversion. 130 /// 131 /// # Safety 132 /// 133 /// You must ensure that: 134 /// 135 /// 1. The backing storage type `T` adheres to the contract as documented on the `StableAsRef` 136 /// marker trait. 137 /// 2. If `T` implements `AsRef<[u8]>` and/or `AsMut<[u8]>`, the byte slice returned 138 /// by calling `as_ref` and/or `as_mut` on the provided value represents valid utf-8. from_utf8_unchecked(value: T) -> String<T>139 pub unsafe fn from_utf8_unchecked(value: T) -> String<T> { 140 String { value } 141 } 142 } 143 144 impl<T> PartialEq<str> for String<T> 145 where T: AsRef<[u8]> 146 { eq(&self, other: &str) -> bool147 fn eq(&self, other: &str) -> bool { 148 &self[..] == other 149 } 150 } 151 152 impl<T> hash::Hash for String<T> 153 where T: AsRef<[u8]> 154 { hash<H: hash::Hasher>(&self, state: &mut H)155 fn hash<H: hash::Hasher>(&self, state: &mut H) { 156 ops::Deref::deref(self).hash(state); 157 } 158 } 159 160 impl<T> ops::Deref for String<T> 161 where T: AsRef<[u8]> 162 { 163 type Target = str; 164 165 #[inline] deref(&self) -> &str166 fn deref(&self) -> &str { 167 let b = self.value.as_ref(); 168 // SAFETY: The `StableAsRef` marker trait ensures that 169 // the impl of `AsRef<[u8]>` for `T` behaves sanely. 170 unsafe { str::from_utf8_unchecked(b) } 171 } 172 } 173 174 impl<T> ops::DerefMut for String<T> 175 where T: AsRef<[u8]> + AsMut<[u8]> 176 { 177 #[inline] deref_mut(&mut self) -> &mut str178 fn deref_mut(&mut self) -> &mut str { 179 let b = self.value.as_mut(); 180 // SAFETY: The `StableAsRef` marker trait ensures that 181 // the impl of `AsMut<[u8]>` for `T` behaves sanely. 182 unsafe { str::from_utf8_unchecked_mut(b) } 183 } 184 } 185 186 impl<T> borrow::Borrow<str> for String<T> 187 where T: AsRef<[u8]> 188 { borrow(&self) -> &str189 fn borrow(&self) -> &str { 190 &*self 191 } 192 } 193 194 impl From<::std::string::String> for String<::std::string::String> { from(value: ::std::string::String) -> Self195 fn from(value: ::std::string::String) -> Self { 196 String { value } 197 } 198 } 199 200 impl<T> Default for String<T> 201 where T: Default + StableAsRef 202 { default() -> Self203 fn default() -> Self { 204 String { value: T::default() } 205 } 206 } 207 208 impl<T> TryFrom<T> for String<T> 209 where T: AsRef<[u8]> + StableAsRef 210 { 211 type Error = str::Utf8Error; 212 try_from(value: T) -> Result<Self, Self::Error>213 fn try_from(value: T) -> Result<Self, Self::Error> { 214 let _ = str::from_utf8(value.as_ref())?; 215 Ok(String { value }) 216 } 217 } 218 219 impl<T: AsRef<[u8]>> fmt::Debug for String<T> { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result220 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 221 (**self).fmt(fmt) 222 } 223 } 224 225 impl<T: AsRef<[u8]>> fmt::Display for String<T> { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result226 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 227 (**self).fmt(fmt) 228 } 229 } 230 231 /// Attempt to construct `Self` via a conversion. 232 /// 233 /// This trait will be deprecated in favor of [std::convert::TryFrom] once it 234 /// reaches stable Rust. 235 pub trait TryFrom<T>: Sized + sealed::Sealed { 236 /// The type returned in the event of a conversion error. 237 type Error; 238 239 /// Performs the conversion. try_from(value: T) -> Result<Self, Self::Error>240 fn try_from(value: T) -> Result<Self, Self::Error>; 241 } 242 243 impl<T> sealed::Sealed for String<T> {} 244 245 mod sealed { 246 /// Private trait to this crate to prevent traits from being implemented in 247 /// downstream crates. 248 pub trait Sealed {} 249 } 250 251 /// Marker trait that indicates that a type is guaranteed safe to use as backing storage 252 /// for `String`. 253 /// 254 /// In order to be safe, a storage type `T` needs to guarantee the following: 255 /// 256 /// - If `T` implements `AsRef<[u8]>` and/or `AsMut<[u8]>`, the contents of `T` as visible 257 /// the byte slice returned by `as_ref` and `as_mut` may only be mutated through mutable 258 /// references or owned access. In other words, no use of interior mutability. 259 /// 260 /// - If `T` implements `AsRef<[u8]>`, the `as_ref` method must always return the same 261 /// slice of bytes (unless the storage is mutated). 262 /// 263 /// - If `T` implements `AsRef<[u8]>` and `AsMut<[u8]>`, the `as_mut` method must return 264 /// a mutable reference to the same slice of bytes as the `as_ref` method returns. 265 /// 266 /// - If `T` implements `AsRef<[u8]>` and `Default`, the default value must represent the 267 /// empty byte sequence. In other words, `T::default().as_ref().len() == 0`. 268 /// 269 /// - If `T` implements `AsRef<[u8]>` and `From<&[u8]>`, it must do so in such a way that 270 /// the byte slice returned by `as_ref` is equal to the byte slice provided to the `from` 271 /// method. 272 pub unsafe trait StableAsRef {} 273 274 unsafe impl<'a, T> StableAsRef for &'a T where T: StableAsRef {} 275 unsafe impl<'a, T> StableAsRef for &'a mut T where T: StableAsRef {} 276 unsafe impl<T> StableAsRef for Box<T> where T: StableAsRef {} 277 unsafe impl<T> StableAsRef for std::rc::Rc<T> where T: StableAsRef {} 278 unsafe impl<T> StableAsRef for std::sync::Arc<T> where T: StableAsRef {} 279 280 unsafe impl StableAsRef for std::string::String {} 281 unsafe impl StableAsRef for str {} 282 unsafe impl StableAsRef for Vec<u8> {} 283 unsafe impl StableAsRef for [u8] {} 284 285 #[cfg(feature = "bytes")] 286 unsafe impl StableAsRef for bytes::Bytes {} 287 288 #[cfg(feature = "bytes")] 289 unsafe impl StableAsRef for bytes::BytesMut {} 290 291 macro_rules! array_impls { 292 ($($len:expr)+) => { 293 $( 294 unsafe impl StableAsRef for [u8; $len] {} 295 )+ 296 } 297 } 298 299 array_impls!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16); 300 301 #[cfg(test)] 302 mod test { 303 use super::*; 304 305 #[test] test_from_std_string()306 fn test_from_std_string() { 307 let s: String<_> = "hello".to_string().into(); 308 assert_eq!(&s, "hello"); 309 } 310 311 #[test] test_from_str()312 fn test_from_str() { 313 let _: String<Vec<u8>> = String::from_str("nice str"); 314 } 315 316 #[test] test_try_from_bytes()317 fn test_try_from_bytes() { 318 let _ = String::try_from(b"nice bytes").unwrap(); 319 } 320 } 321