ion/string/
byte.rs

1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7use std::marker::PhantomData;
8use std::ops::Deref;
9use std::ptr;
10
11#[derive(Debug)]
12pub enum VisibleAscii {}
13
14#[derive(Debug)]
15pub enum Latin1 {}
16
17pub trait BytePredicate: private::Sealed {}
18
19impl<T: private::Sealed> BytePredicate for T {}
20
21mod private {
22	use crate::string::byte::{Latin1, VisibleAscii};
23
24	pub trait Sealed {
25		fn predicate(_byte: u8) -> bool {
26			true
27		}
28	}
29
30	impl Sealed for VisibleAscii {
31		fn predicate(byte: u8) -> bool {
32			(0x20..=0x7E).contains(&byte)
33		}
34	}
35
36	impl Sealed for Latin1 {}
37}
38
39#[derive(Debug)]
40#[repr(transparent)]
41pub struct ByteStr<T: BytePredicate> {
42	_predicate: PhantomData<T>,
43	bytes: [u8],
44}
45
46impl<T: BytePredicate> ByteStr<T> {
47	pub fn from(bytes: &[u8]) -> Option<&ByteStr<T>> {
48		bytes.iter().copied().all(T::predicate).then(|| unsafe { ByteStr::from_unchecked(bytes) })
49	}
50
51	pub unsafe fn from_unchecked(bytes: &[u8]) -> &ByteStr<T> {
52		unsafe { &*(ptr::from_ref(bytes) as *const ByteStr<T>) }
53	}
54
55	pub fn as_bytes(&self) -> &[u8] {
56		&self.bytes
57	}
58}
59
60impl<T: BytePredicate> Deref for ByteStr<T> {
61	type Target = [u8];
62
63	fn deref(&self) -> &[u8] {
64		self.as_bytes()
65	}
66}
67
68#[derive(Clone, Debug, Default)]
69pub struct ByteString<T: BytePredicate = Latin1> {
70	_predicate: PhantomData<T>,
71	bytes: Vec<u8>,
72}
73
74impl<T: BytePredicate> ByteString<T> {
75	pub fn from(bytes: Vec<u8>) -> Option<ByteString<T>> {
76		bytes
77			.iter()
78			.copied()
79			.all(T::predicate)
80			.then(|| unsafe { ByteString::from_unchecked(bytes) })
81	}
82
83	pub unsafe fn from_unchecked(bytes: Vec<u8>) -> ByteString<T> {
84		ByteString { _predicate: PhantomData, bytes }
85	}
86
87	pub fn as_byte_str(&self) -> &ByteStr<T> {
88		unsafe { ByteStr::from_unchecked(&self.bytes) }
89	}
90
91	pub fn into_vec(self) -> Vec<u8> {
92		self.bytes
93	}
94}
95
96impl<T: BytePredicate> Deref for ByteString<T> {
97	type Target = ByteStr<T>;
98
99	fn deref(&self) -> &ByteStr<T> {
100		self.as_byte_str()
101	}
102}