1#![no_std]
21
22#![deny(missing_debug_implementations)]
23#![deny(missing_docs)]
24
25#![feature(const_raw_ptr_deref)]
26#![feature(extern_types)]
27
28extern crate unreachable;
29
30#[cfg(feature = "utf")]
31extern crate utf;
32
33#[cfg(test)] extern crate quickcheck;
34
35#[cfg(test)] #[macro_use] extern crate quickcheck_macros;
36#[cfg(test)] extern crate std;
37
38#[doc(hidden)]
39pub extern crate byte_strings_proc_macros as __byte_strings;
40
41use core::{cmp::*, convert::TryFrom, fmt::{self, Debug, Display}, hash::{Hash, Hasher},
42 marker::PhantomData, mem, ops::*, slice};
43
44extern { type Opaque; }
45unsafe impl Send for Opaque {}
46unsafe impl Sync for Opaque {}
47
48#[repr(C)]
67pub struct Nul<A>([A; 0], Opaque);
68
69impl<A> Nul<A> {
70 #[inline]
72 pub const fn as_ptr(&self) -> *const A { self as *const Self as *const A }
73
74 #[inline]
76 pub fn as_mut_ptr(&mut self) -> *mut A { self as *mut Self as *mut A }
77
78 #[inline]
80 pub const fn iter(&self) -> Iter<A> { Iter(self.as_ptr(), PhantomData) }
81
82 #[inline]
84 pub fn iter_mut(&mut self) -> IterMut<A> { IterMut(self.as_mut_ptr(), PhantomData) }
85
86 #[inline]
92 pub const unsafe fn new_unchecked(p: *const A) -> &'static Self { &*(p as *const Nul<A>) }
93
94 #[inline]
100 pub unsafe fn new_unchecked_mut(p: *mut A) -> &'static mut Self { &mut *(p as *mut Nul<A>) }
101
102 #[inline]
104 pub fn len(&self) -> usize { unsafe {
105 if 0 == mem::size_of::<A>() { return 0; }
106 let mut p = self.as_ptr();
107 while !is_null(&*p) { p = p.offset(1); }
108 ptr_diff(p, self.as_ptr())
109 } }
110
111 #[inline]
113 pub fn get(&self, i: usize) -> Option<&A> { self[..].get(i) }
114
115 #[inline]
117 pub fn get_mut(&mut self, i: usize) -> Option<&mut A> { self[..].get_mut(i) }
118
119 #[inline]
125 pub fn split_at(&self, i: usize) -> (&[A], &Self) {
126 self.try_split_at(i).expect("index out of bounds")
127 }
128
129 #[inline]
135 pub fn split_at_mut(&mut self, i: usize) -> (&mut [A], &mut Self) {
136 self.try_split_at_mut(i).expect("index out of bounds")
137 }
138
139 #[inline]
141 pub fn try_split_at(&self, i: usize) -> Option<(&[A], &Self)> {
142 let mut it = self.iter();
143 for _ in 0..i { if let None = it.next() { return None; } }
144 Some(unsafe { (slice::from_raw_parts(self.as_ptr(), i), <&Self>::from(it)) })
145 }
146
147 #[inline]
149 pub fn try_split_at_mut(&mut self, i: usize) -> Option<(&mut [A], &mut Self)> {
150 let p = self.as_mut_ptr();
151 let mut it = self.iter_mut();
152 for _ in 0..i { if let None = it.next() { return None; } }
153 Some(unsafe { (slice::from_raw_parts_mut(p, i), <&mut Self>::from(it)) })
154 }
155}
156
157pub const unsafe fn cast<A, B>(a: &Nul<A>) -> &Nul<B> { &*(a as *const Nul<A> as *const Nul<B>) }
159
160impl<A, I> Index<I> for Nul<A> where [A]: Index<I> {
161 type Output = <[A] as Index<I>>::Output;
162 #[inline]
163 fn index(&self, i: I) -> &Self::Output {
164 unsafe { slice::from_raw_parts(self.as_ptr(), self.len()).index(i) }
165 }
166}
167
168impl<A, I> IndexMut<I> for Nul<A> where [A]: IndexMut<I> {
169 #[inline]
170 fn index_mut(&mut self, i: I) -> &mut Self::Output {
171 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len()).index_mut(i) }
172 }
173}
174
175impl<A: Debug> Debug for Nul<A> {
176 #[inline]
177 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self[..].fmt(f) }
178}
179
180impl<A: PartialEq> PartialEq for Nul<A> {
181 #[inline]
182 fn eq(&self, other: &Self) -> bool { self[..] == other[..] }
183}
184
185impl<A: Eq> Eq for Nul<A> {}
186
187impl<A: PartialOrd> PartialOrd for Nul<A> {
188 #[inline]
189 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
190 <[A]>::partial_cmp(&self[..], &other[..])
191 }
192}
193
194impl<A: Ord> Ord for Nul<A> {
195 #[inline]
196 fn cmp(&self, other: &Self) -> Ordering { <[A]>::cmp(&self[..], &other[..]) }
197}
198
199impl<A: Hash> Hash for Nul<A> {
200 #[inline]
201 fn hash<H: Hasher>(&self, h: &mut H) { self.iter().for_each(|a| a.hash(h)) }
202}
203
204impl<'a, A> TryFrom<&'a [A]> for &'a Nul<A> {
205 type Error = ();
206 #[inline]
207 fn try_from(xs: &'a [A]) -> Result<Self, ()> {
208 if xs.last().map_or(false, is_null) { Ok(unsafe { &*(xs.as_ptr() as *const Nul<A>) }) }
209 else { Err(()) }
210 }
211}
212
213impl<'a, A> TryFrom<&'a mut [A]> for &'a mut Nul<A> {
214 type Error = ();
215 #[inline]
216 fn try_from(xs: &'a mut [A]) -> Result<Self, ()> {
217 if xs.last().map_or(false, is_null) { Ok(unsafe { &mut *(xs.as_mut_ptr() as *mut Nul<A>) }) }
218 else { Err(()) }
219 }
220}
221
222impl<'a, A> IntoIterator for &'a Nul<A> {
223 type Item = &'a A;
224 type IntoIter = Iter<'a, A>;
225 #[inline]
226 fn into_iter(self) -> Iter<'a, A> { self.iter() }
227}
228
229impl<'a, A> IntoIterator for &'a mut Nul<A> {
230 type Item = &'a mut A;
231 type IntoIter = IterMut<'a, A>;
232 #[inline]
233 fn into_iter(self) -> IterMut<'a, A> { self.iter_mut() }
234}
235
236impl<'a, A> From<Iter<'a, A>> for &'a Nul<A> {
237 #[inline]
238 fn from(it: Iter<'a, A>) -> Self { unsafe { &*(it.0 as *const Nul<A>) } }
239}
240
241impl<'a, A> From<IterMut<'a, A>> for &'a mut Nul<A> {
242 #[inline]
243 fn from(it: IterMut<'a, A>) -> Self { unsafe { &mut *(it.0 as *mut Nul<A>) } }
244}
245
246#[derive(Debug, Clone, Copy)]
248pub struct Iter<'a, A: 'a>(*const A, PhantomData<&'a A>);
249
250unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}
251unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
252
253impl<'a, A: 'a> Iterator for Iter<'a, A> {
254 type Item = &'a A;
255 #[inline]
256 fn next(&mut self) -> Option<&'a A> { unsafe {
257 if is_null(&*self.0) { None } else {
258 let ptr = self.0;
259 self.0 = ptr.offset(1);
260 Some(&*ptr)
261 }
262 } }
263}
264
265#[derive(Debug)]
267pub struct IterMut<'a, A: 'a>(*mut A, PhantomData<&'a mut A>);
268
269unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
270unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
271
272impl<'a, A: 'a> Iterator for IterMut<'a, A> {
273 type Item = &'a mut A;
274 #[inline]
275 fn next(&mut self) -> Option<&'a mut A> { unsafe {
276 if is_null(&*self.0) { None } else {
277 let ptr = self.0;
278 self.0 = ptr.offset(1);
279 Some(&mut *ptr)
280 }
281 } }
282}
283
284impl Display for Nul<char> {
285 #[inline]
286 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
287 use fmt::Write;
288 for &x in self { f.write_char(x)?; }
289 Ok(())
290 }
291}
292
293impl<A> AsRef<Nul<A>> for Nul<A> { #[inline] fn as_ref(&self) -> &Self { self } }
294
295#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
302#[repr(transparent)]
303pub struct NulStr(Nul<u8>);
304
305impl Debug for NulStr {
306 #[inline]
307 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "{:?}", &self[..]) }
308}
309
310#[cfg(feature = "utf")]
311impl fmt::Display for NulStr {
312 #[inline]
313 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_str(&self[..]) }
314}
315
316impl Index<RangeFull> for NulStr {
317 type Output = str;
318
319 #[inline]
320 fn index(&self, _: RangeFull) -> &str { unsafe {
321 ::core::str::from_utf8_unchecked(&self.0[..])
322 } }
323}
324
325impl IndexMut<RangeFull> for NulStr {
326 #[inline]
327 fn index_mut(&mut self, _: RangeFull) -> &mut str { unsafe {
328 ::core::str::from_utf8_unchecked_mut(&mut self.0[..])
329 } }
330}
331
332impl NulStr {
333 #[inline]
339 pub const unsafe fn new_unchecked(p: *const u8) -> &'static Self { &*(p as *const Self) }
340
341 #[inline]
347 pub unsafe fn new_unchecked_mut(p: *mut u8) -> &'static mut Self { &mut *(p as *mut Self) }
348
349 #[inline]
351 pub fn as_bytes(&self) -> &Nul<u8> { &self.0 }
352
353 #[inline]
355 pub fn as_bytes_mut(&mut self) -> &mut Nul<u8> { &mut self.0 }
356
357 #[inline]
359 pub fn as_ptr(&self) -> *const u8 { self.0.as_ptr() }
360
361 #[inline]
363 pub fn as_mut_ptr(&mut self) -> *const u8 { self.0.as_mut_ptr() }
364
365 #[cfg(feature = "utf")]
367 #[inline]
368 pub fn chars(&self) -> Chars { Chars(::utf::decode_utf8(self.0.iter().cloned())) }
369
370 #[cfg(feature = "utf")]
372 #[inline]
373 pub fn char_indices(&self) -> CharIndices { CharIndices(self.chars(), 0) }
374
375 #[inline]
377 pub fn is_char_boundary(&self, k: usize) -> bool { self[..].is_char_boundary(k) }
378}
379
380#[cfg(feature = "utf")]
382#[derive(Debug, Clone)]
383pub struct Chars<'a>(::utf::DecodeUtf8<::core::iter::Cloned<Iter<'a, u8>>>);
384
385#[cfg(feature = "utf")]
386impl<'a> Iterator for Chars<'a> {
387 type Item = char;
388 #[inline]
389 fn next(&mut self) -> Option<char> {
390 use unreachable::UncheckedResultExt;
391 self.0.next().map(|r| unsafe { r.unchecked_unwrap_ok() })
392 }
393}
394
395#[cfg(feature = "utf")]
397#[derive(Debug, Clone)]
398pub struct CharIndices<'a>(Chars<'a>, usize);
399
400#[cfg(feature = "utf")]
401impl<'a> Iterator for CharIndices<'a> {
402 type Item = (usize, char);
403 #[inline]
404 fn next(&mut self) -> Option<(usize, char)> {
405 let x = self.0.next()?;
406 let k = self.1;
407 self.1 += x.len_utf8();
408 Some((k, x))
409 }
410}
411
412impl<'a> TryFrom<&'a Nul<u8>> for &'a NulStr {
413 type Error = ::core::str::Utf8Error;
414
415 #[inline]
416 fn try_from(s: &'a Nul<u8>) -> Result<Self, Self::Error> {
417 ::core::str::from_utf8(&s[..])?;
418 Ok(unsafe { NulStr::new_unchecked(s.as_ptr()) })
419 }
420}
421
422impl<'a> TryFrom<&'a mut Nul<u8>> for &'a mut NulStr {
423 type Error = ::core::str::Utf8Error;
424
425 #[inline]
426 fn try_from(s: &'a mut Nul<u8>) -> Result<Self, Self::Error> {
427 ::core::str::from_utf8_mut(&mut s[..])?;
428 Ok(unsafe { NulStr::new_unchecked_mut(s.as_mut_ptr()) })
429 }
430}
431
432#[inline]
433fn is_null<A>(a: &A) -> bool { unsafe {
434 let l = mem::size_of_val(a);
435 let p = a as *const A as *const u8;
436 slice::from_raw_parts(p, l).iter().all(|&b| 0 == b)
437} }
438
439#[inline]
440fn ptr_diff<A>(p: *const A, q: *const A) -> usize {
441 use ::core::num::Wrapping as w;
442 (w(p as usize) - w(q as usize)).0/mem::size_of::<A>()
443}
444
445#[macro_export]
455macro_rules! str0 {
456 ($s:expr) => (unsafe {
457 $crate::Nul::<u8>::new_unchecked($crate::__byte_strings::concat_bytes!([$crate] $s, "\0").as_ptr() as *mut _)
458 })
459}
460
461#[macro_export]
471macro_rules! str0_utf8 {
472 ($s:expr) => (unsafe {
473 $crate::NulStr::new_unchecked(concat!($s, "\0").as_ptr() as *mut _)
474 })
475}
476
477
478#[macro_export]
497macro_rules! nul_of_ref {
498 ($($reference:expr),* $(,)?) => (unsafe {
499 enum Opt<T> { Nil, Just(T) }
500 #[inline(always)]
501 const unsafe fn cast_helper<'a, 'b, A: ?Sized>(a: &'b Nul<Opt<&'a A>>) -> &'b Nul<&'a A> { $crate::cast(a) }
502 cast_helper($crate::Nul::new_unchecked([$(Opt::Just($reference),)* Opt::Nil].as_ptr()))
503 })
504}
505
506#[cfg(doctest)]
522pub struct NoNulOfRefInvalid;
523
524#[cfg(test)]
525mod tests {
526 use super::*;
527
528 #[quickcheck]
529 fn test(mut xs: ::std::vec::Vec<usize>) -> bool {
530 xs.push(0);
531 let l = xs.iter().take_while(|&&x| 0usize != x).count();
532 xs[0..l] == <&Nul<_>>::try_from(&xs[..]).unwrap()[..]
533 }
534
535 #[quickcheck]
536 fn iter(mut xs: ::std::vec::Vec<usize>) -> bool {
537 xs.push(0);
538 let l = xs.iter().take_while(|&&x| 0usize != x).count();
539 Iterator::eq(xs.iter().take(l), <&Nul<_>>::try_from(&xs[..]).unwrap().iter())
540 }
541}