sark_http/field/storage/
name.rs1use std::borrow::Cow;
2
3use o3::alloc::{self, StrExt as _};
4
5use crate::{
6 field::{self, Error, head::known::Known, storage},
7 h1::field::Entry,
8};
9
10#[repr(transparent)]
12#[derive(Copy, Debug, PartialEq, Eq)]
13pub struct Name<T>(pub(in crate::field) T);
14
15impl<T: Copy> Clone for Name<T> {
16 fn clone(&self) -> Self {
17 *self
18 }
19}
20
21impl<T: storage::Bytes> Name<T> {
22 pub fn new(name: T) -> Result<Self, Error> {
23 Error::name(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 as_str(&self) -> &str {
32 field::raw::name(self.borrow())
33 }
34
35 pub fn borrow(&self) -> Name<&[u8]> {
36 Name(self.as_bytes())
37 }
38}
39
40impl<T> Name<T> {
41 pub fn into_inner(self) -> T {
42 self.0
43 }
44}
45
46impl<'a> Name<&'a [u8]> {
47 pub const fn try_bytes(name: &'a [u8]) -> Result<Self, Error> {
48 match Error::name(name) {
49 Ok(()) => Ok(Self(name)),
50 Err(cause) => Err(cause),
51 }
52 }
53
54 pub const fn get(self) -> &'a [u8] {
55 self.0
56 }
57}
58
59impl<'field> Name<Cow<'field, str>> {
60 pub const CONTENT_TYPE: Self = Self(Cow::Borrowed(Known::ContentType.as_str()));
61
62 pub fn try_copy(name: &[u8]) -> Result<Self, storage::Error> {
63 if let Some(known) = Known::from_bytes(name) {
64 return Ok(Self(Cow::from(known)));
65 }
66 let name = Name::try_bytes(name).map_err(storage::Error::Syntax)?;
67 Self::try_lowered(name).map_err(storage::Error::Allocation)
68 }
69
70 pub(crate) fn try_entry(field: Entry<'_>) -> Result<Self, alloc::Exhausted> {
71 let name = field.name();
72 match Known::from_bytes(name) {
73 Some(known) => Ok(Self(Cow::from(known))),
74 None => Self::try_lowered(Name(name)),
75 }
76 }
77
78 fn try_lowered(name: Name<&[u8]>) -> Result<Self, alloc::Exhausted> {
79 let mut name = name.as_str().try_to_owned()?;
80 name.make_ascii_lowercase();
81 Ok(Self(Cow::Owned(name)))
82 }
83
84 pub fn try_owned(self) -> Result<Name<String>, alloc::Exhausted> {
85 Ok(Name(storage::try_own(self.0)?))
86 }
87
88 pub(crate) fn try_lower(mut self) -> Result<Self, alloc::Exhausted> {
89 if self.0.bytes().any(|byte| byte.is_ascii_uppercase()) {
90 match Known::from_bytes(self.0.as_bytes()) {
91 Some(known) => self.0 = Cow::from(known),
92 None => {
93 let mut name = storage::try_own(self.0)?;
94 name.make_ascii_lowercase();
95 self.0 = Cow::Owned(name);
96 }
97 }
98 }
99 Ok(self)
100 }
101}