Skip to main content

sark_http/field/storage/
mod.rs

1//! Owners whose shared projections preserve admitted field bytes.
2
3use std::{borrow::Cow, marker::PhantomData};
4
5use o3::{
6    alloc::{self, StrExt as _},
7    buffer::storage::Shared,
8};
9
10pub(in crate::field) mod encoded;
11mod lower;
12mod name;
13mod sealed;
14mod value;
15
16pub use lower::Lower;
17pub use name::Name;
18pub(crate) use sealed::Sealed;
19pub use value::Value;
20
21/// Failure to validate and own one field component.
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum Error {
24    Syntax(crate::field::Error),
25    Allocation(alloc::Exhausted),
26}
27
28fn try_own(value: Cow<'_, str>) -> Result<String, alloc::Exhausted> {
29    match value {
30        Cow::Borrowed(value) => value.try_to_owned(),
31        Cow::Owned(value) => Ok(value),
32    }
33}
34
35/// Immutable bytes while their field owner is shared.
36pub trait Bytes: Sealed {
37    fn as_bytes(&self) -> &[u8];
38}
39
40/// Immutable UTF-8 text while its field owner is shared.
41pub trait Text: Bytes {
42    fn as_str(&self) -> &str;
43}
44
45/// One immutable text value selected by its type.
46pub trait Constant {
47    const VALUE: &'static str;
48}
49
50/// A zero-sized owner of a type's immutable text constant.
51#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
52pub struct Static<T>(PhantomData<fn() -> T>);
53
54impl<T: Constant> Static<T> {
55    pub const fn new() -> Self {
56        Self(PhantomData)
57    }
58}
59
60impl<T: Constant> Bytes for Static<T> {
61    fn as_bytes(&self) -> &[u8] {
62        T::VALUE.as_bytes()
63    }
64}
65impl<T: Constant> Text for Static<T> {
66    fn as_str(&self) -> &str {
67        T::VALUE
68    }
69}
70
71impl Bytes for str {
72    fn as_bytes(&self) -> &[u8] {
73        str::as_bytes(self)
74    }
75}
76impl Text for str {
77    fn as_str(&self) -> &str {
78        self
79    }
80}
81
82impl Bytes for String {
83    fn as_bytes(&self) -> &[u8] {
84        self.as_str().as_bytes()
85    }
86}
87impl Text for String {
88    fn as_str(&self) -> &str {
89        String::as_str(self)
90    }
91}
92
93impl Bytes for [u8] {
94    fn as_bytes(&self) -> &[u8] {
95        self
96    }
97}
98
99impl<const N: usize> Bytes for [u8; N] {
100    fn as_bytes(&self) -> &[u8] {
101        self
102    }
103}
104
105impl Bytes for Vec<u8> {
106    fn as_bytes(&self) -> &[u8] {
107        self.as_slice()
108    }
109}
110
111impl Bytes for Shared {
112    fn as_bytes(&self) -> &[u8] {
113        self
114    }
115}
116
117impl Bytes for Cow<'_, str> {
118    fn as_bytes(&self) -> &[u8] {
119        self.as_ref().as_bytes()
120    }
121}
122impl Text for Cow<'_, str> {
123    fn as_str(&self) -> &str {
124        self.as_ref()
125    }
126}
127
128impl Bytes for Cow<'_, [u8]> {
129    fn as_bytes(&self) -> &[u8] {
130        self.as_ref()
131    }
132}
133
134impl<T: Bytes + ?Sized> Bytes for &T {
135    fn as_bytes(&self) -> &[u8] {
136        T::as_bytes(self)
137    }
138}
139impl<T: Text + ?Sized> Text for &T {
140    fn as_str(&self) -> &str {
141        T::as_str(self)
142    }
143}
144
145impl<T: Bytes + ?Sized> Bytes for Box<T> {
146    fn as_bytes(&self) -> &[u8] {
147        T::as_bytes(self)
148    }
149}
150impl<T: Text + ?Sized> Text for Box<T> {
151    fn as_str(&self) -> &str {
152        T::as_str(self)
153    }
154}