1use std::fmt::{Debug, Formatter};
2use std::ops::Deref;
3use std::str::Utf8Error;
4
5use crate::ByteBuffer;
6
7#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct BufferString(ByteBuffer);
10
11impl BufferString {
12 pub const unsafe fn new_unchecked(buffer: ByteBuffer) -> Self {
17 Self(buffer)
18 }
19
20 pub fn as_str(&self) -> &str {
22 unsafe { std::str::from_utf8_unchecked(self.0.as_ref()) }
24 }
25
26 pub fn into_inner(self) -> ByteBuffer {
28 self.0
29 }
30}
31
32impl Debug for BufferString {
33 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
34 f.debug_struct("BufferString")
35 .field("string", &self.as_str())
36 .finish()
37 }
38}
39
40impl From<BufferString> for ByteBuffer {
41 fn from(value: BufferString) -> Self {
42 value.0
43 }
44}
45
46impl From<String> for BufferString {
47 fn from(value: String) -> Self {
48 Self(ByteBuffer::from(value.into_bytes()))
49 }
50}
51
52impl From<&str> for BufferString {
53 fn from(value: &str) -> Self {
54 Self(ByteBuffer::from(String::from(value).into_bytes()))
55 }
56}
57
58impl TryFrom<ByteBuffer> for BufferString {
59 type Error = Utf8Error;
60
61 fn try_from(value: ByteBuffer) -> Result<Self, Self::Error> {
62 let _ = std::str::from_utf8(value.as_ref())?;
63 Ok(Self(value))
64 }
65}
66
67impl Deref for BufferString {
68 type Target = str;
69
70 fn deref(&self) -> &Self::Target {
71 self.as_str()
72 }
73}
74
75impl AsRef<str> for BufferString {
76 fn as_ref(&self) -> &str {
77 self.as_str()
78 }
79}
80
81impl AsRef<[u8]> for BufferString {
82 fn as_ref(&self) -> &[u8] {
83 self.as_str().as_bytes()
84 }
85}
86
87#[cfg(test)]
88mod test {
89 use crate::{Alignment, BufferString, buffer};
90
91 #[test]
92 fn buffer_string() {
93 let buf = BufferString::from("hello");
94 assert_eq!(buf.len(), 5);
95 assert_eq!(buf.into_inner().alignment(), Alignment::of::<u8>());
96 }
97
98 #[test]
99 fn buffer_string_non_ut8() {
100 assert!(BufferString::try_from(buffer![0u8, 255]).is_err());
101 }
102}