libpijul_compat/backend/
small_string.rs1use sanakirja::{Alignment, Representable};
2use std;
3pub const MAX_LENGTH: usize = 255;
4
5#[repr(packed)]
8pub struct SmallString {
9 pub len: u8,
10 pub str: [u8; MAX_LENGTH],
11}
12
13#[derive(Clone, Copy)]
15pub struct SmallStr<'a>(*const u8, std::marker::PhantomData<&'a ()>);
16
17impl Clone for SmallString {
18 fn clone(&self) -> Self {
19 Self::from_str(self.as_str())
20 }
21}
22
23impl std::fmt::Debug for SmallString {
24 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
25 self.as_small_str().fmt(fmt)
26 }
27}
28
29impl<'a> PartialEq for SmallStr<'a> {
30 fn eq(&self, x: &SmallStr) -> bool {
31 self.as_str().eq(x.as_str())
32 }
33}
34impl<'a> Eq for SmallStr<'a> {}
35
36impl PartialEq for SmallString {
37 fn eq(&self, x: &SmallString) -> bool {
38 self.as_str().eq(x.as_str())
39 }
40}
41impl Eq for SmallString {}
42
43impl<'a> std::hash::Hash for SmallStr<'a> {
44 fn hash<H: std::hash::Hasher>(&self, x: &mut H) {
45 self.as_str().hash(x)
46 }
47}
48
49impl std::hash::Hash for SmallString {
50 fn hash<H: std::hash::Hasher>(&self, x: &mut H) {
51 self.as_str().hash(x)
52 }
53}
54
55impl<'a> PartialOrd for SmallStr<'a> {
56 fn partial_cmp(&self, x: &SmallStr) -> Option<std::cmp::Ordering> {
57 self.as_str().partial_cmp(x.as_str())
58 }
59}
60impl<'a> Ord for SmallStr<'a> {
61 fn cmp(&self, x: &SmallStr) -> std::cmp::Ordering {
62 self.as_str().cmp(x.as_str())
63 }
64}
65
66impl<'a> std::fmt::Debug for SmallStr<'a> {
67 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
68 self.as_str().fmt(fmt)
69 }
70}
71
72impl SmallString {
73 pub fn len(&self) -> usize {
74 self.len as usize
75 }
76
77 pub fn is_empty(&self) -> bool {
78 self.len() == 0
79 }
80
81 pub fn from_str(s: &str) -> Self {
82 let mut b = SmallString {
83 len: s.len() as u8,
84 str: [0; MAX_LENGTH],
85 };
86 b.clone_from_str(s);
87 b
88 }
89 pub fn clone_from_str(&mut self, s: &str) {
90 self.len = s.len() as u8;
91 (&mut self.str[..s.len()]).copy_from_slice(s.as_bytes());
92 }
93 pub fn clear(&mut self) {
94 self.len = 0;
95 }
96 pub fn push_str(&mut self, s: &str) {
97 let l = self.len as usize;
98 assert!(l + s.len() <= 0xff);
99 (&mut self.str[l..l + s.len()]).copy_from_slice(s.as_bytes());
100 self.len += s.len() as u8;
101 }
102
103 pub fn as_small_str(&self) -> SmallStr {
104 SmallStr(
105 self as *const SmallString as *const u8,
106 std::marker::PhantomData,
107 )
108 }
109
110 pub fn as_str(&self) -> &str {
111 self.as_small_str().as_str()
112 }
113}
114
115impl<'a> SmallStr<'a> {
116 pub fn is_empty(&self) -> bool {
117 self.len() == 0
118 }
119
120 pub fn len(&self) -> usize {
121 unsafe { (*self.0) as usize }
122 }
123
124 pub fn as_str(&self) -> &'a str {
125 unsafe {
126 std::str::from_utf8_unchecked(std::slice::from_raw_parts(
127 self.0.offset(1),
128 *self.0 as usize,
129 ))
130 }
131 }
132 pub fn to_unsafe(&self) -> UnsafeSmallStr {
133 UnsafeSmallStr(self.0)
134 }
135 pub unsafe fn from_unsafe(u: UnsafeSmallStr) -> Self {
136 SmallStr(u.0, std::marker::PhantomData)
137 }
138 pub fn to_owned(&self) -> SmallString {
139 SmallString::from_str(self.as_str())
140 }
141}
142
143#[derive(Clone, Copy)]
144pub struct UnsafeSmallStr(*const u8);
145impl std::fmt::Debug for UnsafeSmallStr {
146 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
147 unsafe { SmallStr::from_unsafe(*self).fmt(fmt) }
148 }
149}
150
151impl Representable for UnsafeSmallStr {
152 fn alignment() -> Alignment {
153 Alignment::B1
154 }
155 fn onpage_size(&self) -> u16 {
156 unsafe {
157 let len = (*self.0) as u16;
158 1 + len
159 }
160 }
161 unsafe fn write_value(&self, p: *mut u8) {
162 trace!("write_value {:?}", p);
163 std::ptr::copy(self.0, p, self.onpage_size() as usize)
164 }
165 unsafe fn read_value(p: *const u8) -> Self {
166 trace!("read_value {:?}", p);
167 UnsafeSmallStr(p)
168 }
169 unsafe fn cmp_value<T>(&self, _: &T, x: Self) -> std::cmp::Ordering {
170 let a = SmallStr::from_unsafe(UnsafeSmallStr(self.0));
171 let b = SmallStr::from_unsafe(x);
172 a.as_str().cmp(b.as_str())
173 }
174 type PageOffsets = std::iter::Empty<u64>;
175 fn page_offsets(&self) -> Self::PageOffsets {
176 std::iter::empty()
177 }
178}