1use std::{fmt, slice, str};
5
6#[repr(C)]
8pub struct Slice<T: 'static> {
9 ptr: *const T,
10 len: usize,
11}
12
13unsafe impl<T: Sync> Sync for Slice<T> {}
15
16impl<T> Slice<T> {
17 pub const PTR_OFFSET: usize = std::mem::offset_of!(Self, ptr);
19 pub const LEN_OFFSET: usize = std::mem::offset_of!(Self, len);
20
21 pub const EMPTY: Self = Self {
22 ptr: std::ptr::null(),
23 len: 0,
24 };
25
26 #[must_use]
27 pub const fn new(items: &'static [T]) -> Self {
28 Self {
29 ptr: items.as_ptr(),
30 len: items.len(),
31 }
32 }
33
34 #[must_use]
35 pub fn items(&self) -> &'static [T] {
36 if self.len == 0 {
37 return &[];
38 }
39 unsafe { slice::from_raw_parts(self.ptr, self.len) }
42 }
43}
44
45impl<T: fmt::Debug> fmt::Debug for Slice<T> {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 f.debug_list().entries(self.items()).finish()
48 }
49}
50
51#[repr(C)]
53pub struct Str(Slice<u8>);
54
55impl Str {
56 pub const EMPTY: Self = Self(Slice::EMPTY);
57
58 #[must_use]
59 pub const fn new(text: &'static str) -> Self {
60 Self(Slice::new(text.as_bytes()))
61 }
62
63 #[must_use]
65 pub fn lossy(&self) -> String {
66 String::from_utf8_lossy(self.0.items()).into_owned()
67 }
68
69 pub fn text(&self) -> Result<&'static str, str::Utf8Error> {
72 str::from_utf8(self.0.items())
73 }
74}
75
76impl fmt::Debug for Str {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 fmt::Debug::fmt(&self.lossy(), f)
79 }
80}