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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
#![no_std] use containers::collections::Vec; use core::{borrow::{Borrow, BorrowMut}, convert::TryFrom, ops::{Deref, DerefMut}, str::{self, Utf8Error}}; #[repr(transparent)] #[derive(Debug, PartialEq, Eq, Hash)] pub struct String(Vec<u8>); impl String { #[inline] pub fn new() -> Self { Self(Vec::new()) } #[inline] pub fn from_str(s: &str) -> Option<Self> { Vec::from_slice(s.as_bytes()).map(|x| unsafe { Self::from_vec_unchecked(x) }) } #[inline(always)] pub unsafe fn from_vec_unchecked(x: Vec<u8>) -> Self { Self(x) } } impl From<String> for Vec<u8> { #[inline(always)] fn from(x: String) -> Self { x.0 } } impl TryFrom<Vec<u8>> for String { type Error = FromUtf8Error; #[inline] fn try_from(bs: Vec<u8>) -> Result<Self, FromUtf8Error> { match str::from_utf8(&bs) { Ok(_) => Ok(String(bs)), Err(e) => Err(FromUtf8Error { bytes: bs, error: e }) } } } #[derive(Debug, PartialEq, Eq)] pub struct FromUtf8Error { bytes: Vec<u8>, error: Utf8Error, } impl FromUtf8Error { #[inline] pub fn into_bytes(self) -> Vec<u8> { self.bytes } #[inline] pub fn utf8_error(&self) -> Utf8Error { self.error } } impl Deref for String { type Target = str; #[inline] fn deref(&self) -> &str { unsafe { core::str::from_utf8_unchecked(&self.0) } } } impl DerefMut for String { #[inline] fn deref_mut(&mut self) -> &mut str { unsafe { core::str::from_utf8_unchecked_mut(&mut self.0) } } } impl Borrow<str> for String { #[inline] fn borrow(&self) -> &str { self.deref() } } impl BorrowMut<str> for String { fn borrow_mut(&mut self) -> &mut str { self.deref_mut() } } impl core::fmt::Display for String { #[inline] fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { self.deref().fmt(fmt) } } #[macro_export] macro_rules! format { ($($x:tt)*) => ({ let s = $crate::String::new(); core::fmt::write(&mut s, format_args!($($x)*)).ok().map(|()| s) }); }