sark_http/field/storage/
lower.rs1use std::borrow::Cow;
2
3use o3::alloc::{self, BoxSliceExt as _};
4
5use crate::{
6 field::{Error, Name, storage},
7 h1::field,
8};
9
10#[repr(transparent)]
12#[derive(Copy, Debug, PartialEq, Eq)]
13pub struct Lower<T>(pub(in crate::field) T);
14
15impl<T: Copy> Clone for Lower<T> {
16 fn clone(&self) -> Self {
17 *self
18 }
19}
20
21impl<T: storage::Bytes> Lower<T> {
22 pub fn new(name: T) -> Result<Self, Error> {
23 Lower::try_bytes(name.as_bytes())?;
24 Ok(Self(name))
25 }
26
27 pub fn as_bytes(&self) -> &[u8] {
28 self.0.as_bytes()
29 }
30
31 pub fn borrow(&self) -> Lower<&[u8]> {
32 Lower(self.0.as_bytes())
33 }
34}
35
36impl<T: storage::Text> Lower<T> {
37 pub fn as_str(&self) -> &str {
38 self.0.as_str()
39 }
40}
41
42impl<T> Lower<T> {
43 pub fn into_inner(self) -> T {
44 self.0
45 }
46}
47
48impl<'a> Lower<&'a [u8]> {
49 pub const fn try_bytes(name: &'a [u8]) -> Result<Self, Error> {
50 if name.is_empty() {
51 return Err(Error::Empty);
52 }
53 let mut index = 0;
54 while index < name.len() {
55 let byte = name[index];
56 if !Error::is_name_byte(byte) || byte.is_ascii_uppercase() {
57 return Err(Error::InvalidByte { index, byte });
58 }
59 index += 1;
60 }
61 Ok(Self(name))
62 }
63
64 pub const fn get(self) -> &'a [u8] {
65 self.0
66 }
67}
68
69impl<'a> Lower<Cow<'a, [u8]>> {
70 pub const fn borrowed(name: Lower<&'a [u8]>) -> Self {
71 Self(Cow::Borrowed(name.0))
72 }
73}
74
75impl<'a> TryFrom<Name<&'a [u8]>> for Lower<Cow<'a, [u8]>> {
76 type Error = alloc::Exhausted;
77
78 fn try_from(name: Name<&'a [u8]>) -> Result<Self, Self::Error> {
79 let bytes = name.0;
80 if !bytes.iter().any(u8::is_ascii_uppercase) {
81 return Ok(Self(Cow::Borrowed(bytes)));
82 }
83 let mut bytes = Box::try_copy(bytes)?.into_vec();
84 bytes.make_ascii_lowercase();
85 Ok(Self(Cow::Owned(bytes)))
86 }
87}
88
89impl<'a> Lower<Cow<'a, str>> {
90 pub const CONTENT_TYPE: Self = Self(Cow::Borrowed("content-type"));
91
92 pub fn try_name(name: Name<Cow<'a, str>>) -> Result<Self, alloc::Exhausted> {
93 Ok(Self(name.try_lower()?.0))
94 }
95
96 pub(crate) fn try_entry(entry: field::Entry<'_>) -> Result<Self, alloc::Exhausted> {
97 Ok(Self(Name::try_entry(entry)?.0))
98 }
99
100 pub fn try_copy(name: &[u8]) -> Result<Self, storage::Error> {
101 Ok(Self(Name::try_copy(name)?.0))
102 }
103}
104
105impl<T: storage::Bytes> AsRef<[u8]> for Lower<T> {
106 fn as_ref(&self) -> &[u8] {
107 self.as_bytes()
108 }
109}