taos_query/util/
inline_str.rs

1use std::fmt;
2
3// use super::{Inlinable, AsyncInlinable};
4use tokio::io::*;
5
6#[repr(C)]
7#[repr(packed(1))]
8pub struct InlineStr<T = u16> {
9    len: T,
10    data: [u8; 0],
11}
12macro_rules! _impl_inline_str {
13    ($($ty:ty) *) => {
14        $(
15
16            impl fmt::Debug for InlineStr<$ty> {
17                #[inline]
18                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19                    f.debug_struct("InlineStr")
20                        .field("len", &self.len())
21                        .field("data", &self.as_str())
22                        .finish()
23                }
24            }
25
26            impl fmt::Display for InlineStr<$ty> {
27                #[inline]
28                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29                    f.write_str(self.as_str())
30                }
31            }
32
33            impl AsRef<str> for InlineStr<$ty> {
34                #[inline]
35                fn as_ref(&self) -> &str {
36                    self.as_str()
37                }
38            }
39
40            impl AsRef<[u8]> for InlineStr<$ty> {
41                #[inline]
42                fn as_ref(&self) -> &[u8] {
43                    self.as_bytes()
44                }
45            }
46
47            impl super::Inlinable for InlineStr<$ty> {
48                #[inline]
49                fn write_inlined<W: std::io::Write>(&self, wtr: &mut W) -> std::io::Result<usize> {
50                    let l = wtr.write(&self.len.to_le_bytes())?;
51                    Ok(l + wtr.write(self.as_bytes())?)
52                }
53
54                #[inline]
55                fn read_inlined<R: std::io::Read>(_: &mut R) -> std::io::Result<Self> {
56                    Err(std::io::Error::new(std::io::ErrorKind::Other, "can't read into a inlined string"))
57                }
58            }
59
60            #[async_trait::async_trait]
61            impl super::AsyncInlinable for InlineStr<$ty> {
62                #[inline]
63                async fn write_inlined<W: AsyncWrite + Unpin + Send>(&self, wtr: &mut W) -> std::io::Result<usize> {
64                    let l = wtr.write(&self.len.to_le_bytes()).await?;
65                    Ok(l + wtr.write(self.as_bytes()).await?)
66                }
67
68                async fn read_inlined<R: AsyncRead + Send + Unpin>(_: &mut R) -> std::io::Result<Self> {
69                    Err(std::io::Error::new(std::io::ErrorKind::Other, "can't read into a inlined string"))
70                }
71            }
72
73            impl InlineStr<$ty> {
74
75                /// # Safety
76                ///
77                /// Do not use it directly.
78                pub unsafe fn from_ptr<'a>(ptr: *const u8) -> &'a Self {
79                    &*std::mem::transmute::<*const u8, *const InlineStr<$ty>>(ptr)
80                }
81
82                #[inline]
83                pub const fn as_ptr(&self) -> *const u8 {
84                    self.data.as_ptr()
85                }
86                #[inline]
87                pub fn as_mut_ptr(&mut self) -> *mut u8 {
88                    self.data.as_mut_ptr()
89                }
90
91                #[inline]
92                #[rustversion::attr(nightly, const)]
93                pub fn as_bytes(&self) -> &[u8] {
94                    if self.len() == 0 {
95                        return &[]
96                    }
97                    unsafe { std::slice::from_raw_parts(self.data.as_ptr(), self.len()) }
98                }
99
100                #[inline]
101                #[rustversion::attr(nightly, const)]
102                pub fn as_str(&self) -> &str {
103                    unsafe { std::str::from_utf8_unchecked(self.as_bytes()) }
104                }
105
106                #[inline]
107                pub const fn len(&self) -> usize {
108                    self.len as _
109                }
110
111                #[inline]
112                pub const fn is_empty(&self) -> bool {
113                    self.len == 0
114                }
115
116                #[inline(never)]
117                pub(crate) unsafe fn set_len(&mut self, len: usize) {
118                    self.len = len as _;
119                }
120                #[inline(never)]
121                pub(crate) unsafe fn replace_utf8(&mut self, s: &str, pos: usize) {
122                    std::ptr::copy(s.as_ptr(), self.as_mut_ptr().add(pos), s.len());
123                }
124            }
125        )*
126    };
127}
128_impl_inline_str!(u8 u16 u32 u64 usize);
129
130macro_rules! _impl_test_inline_str {
131    ($ty:ty, $bytes:literal, $print:literal) => {{
132        let bytes = $bytes;
133        use super::Inlinable;
134        let inline = unsafe { InlineStr::<$ty>::from_ptr(bytes.as_ptr()) };
135        dbg!(inline);
136        assert_eq!(inline.len(), 4);
137        assert_eq!(inline.as_str(), "abcd");
138        assert_eq!(format!("{}", inline), "abcd");
139        assert_eq!(inline.inlined(), bytes);
140        assert_eq!(inline.printable_inlined(), $print);
141    }};
142}
143
144#[test]
145fn test_inline_str() {
146    _impl_test_inline_str!(u8, b"\x04abcd", "\\x04abcd");
147    _impl_test_inline_str!(u16, b"\x04\x00abcd", "\\x04\\x00abcd");
148    _impl_test_inline_str!(u32, b"\x04\x00\x00\x00abcd", "\\x04\\x00\\x00\\x00abcd");
149    _impl_test_inline_str!(
150        u64,
151        b"\x04\x00\x00\x00\x00\x00\x00\x00abcd",
152        "\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00abcd"
153    );
154}
155
156#[test]
157fn test_empty_inline() {
158    let inline = unsafe { InlineStr::<u8>::from_ptr(b"\0".as_ptr()) };
159    dbg!(inline);
160}