Skip to main content

sark_http/payload/response/headers/
mod.rs

1//! Admitted application response headers and their emission contract.
2
3pub mod head;
4mod list;
5mod name;
6pub mod set;
7pub mod value;
8
9pub use list::List;
10pub use name::Name;
11
12use crate::field;
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub enum Error {
16    Managed,
17    Syntax(field::Error),
18}
19
20/// An ordinary response field whose name cannot override framework framing.
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22#[repr(transparent)]
23pub struct Entry<'a>(field::Entry<'a>);
24
25/// A preencoded group whose fields cannot override framework framing.
26#[derive(Clone, Copy, Debug, PartialEq, Eq)]
27#[repr(transparent)]
28pub struct Group<'a>(field::Group<'a>);
29
30impl<'a> Group<'a> {
31    pub const fn try_new(group: field::Group<'a>) -> Result<Self, Error> {
32        let entries = group.entries();
33        let mut index = 0;
34        while index < entries.len() {
35            if let Err(error) = Name::try_bytes(entries[index].name()) {
36                return Err(error);
37            }
38            index += 1;
39        }
40        Ok(Self(group))
41    }
42
43    pub const fn as_fields(&self) -> &field::Group<'a> {
44        &self.0
45    }
46}
47
48impl<'a> Entry<'a> {
49    pub const fn new(name: Name<&'a [u8]>, value: field::Value<&'a [u8]>) -> Self {
50        Self(field::Entry::new(name.0, value))
51    }
52
53    pub const fn with_index(self, indexing: field::Indexing) -> Self {
54        Self(self.0.with_index(indexing))
55    }
56
57    pub const fn name(self) -> &'a [u8] {
58        self.0.name()
59    }
60
61    pub const fn value(self) -> field::Value<&'a [u8]> {
62        self.0.value()
63    }
64
65    pub const fn indexing(self) -> field::Indexing {
66        self.0.indexing()
67    }
68
69    pub const fn as_field(&self) -> field::Entry<'a> {
70        self.0
71    }
72}
73
74/// Receives admitted ordinary response fields, including generated values.
75pub trait Sink<'field> {
76    fn entry(&mut self, field: Entry<'field>);
77
78    /// Emits the admitted fields in their original order and indexing policy.
79    fn group(&mut self, group: &Group<'field>) {
80        for entry in group.0.entries() {
81            self.entry(Entry(*entry));
82        }
83    }
84
85    fn field(&mut self, name: Name<&'field [u8]>, value: field::Value<&'field [u8]>) {
86        self.entry(Entry::new(name, value));
87    }
88
89    fn encoded_with<E: field::Encode>(
90        &mut self,
91        name: Name<&'field [u8]>,
92        value: E,
93        indexing: field::Indexing,
94    );
95
96    fn generated<E: field::Encode>(&mut self, name: Name<&'field [u8]>, value: E) {
97        self.encoded_with(name, value, field::Indexing::Allowed);
98    }
99}
100
101/// Emits only ordinary headers whose admission survives every invocation.
102pub trait Source {
103    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>);
104}
105
106/// Projects response admission into the protocol-neutral field encoder.
107#[repr(transparent)]
108pub struct Fields<S>(S);
109
110impl<S: Source> Fields<S> {
111    pub const fn new(source: S) -> Self {
112        Self(source)
113    }
114}
115
116struct Adapter<'a, S>(&'a mut S);
117
118impl<S: Source> field::Source for Fields<S> {
119    fn emit<'field>(&'field self, sink: &mut impl field::Sink<'field>) {
120        self.0.emit(&mut Adapter(sink));
121    }
122}
123
124impl<'field, S: field::Sink<'field>> Sink<'field> for Adapter<'_, S> {
125    fn entry(&mut self, field: Entry<'field>) {
126        self.0.entry(field.0);
127    }
128
129    fn group(&mut self, group: &Group<'field>) {
130        self.0.group(group.as_fields());
131    }
132
133    fn encoded_with<E: field::Encode>(
134        &mut self,
135        name: Name<&'field [u8]>,
136        value: E,
137        indexing: field::Indexing,
138    ) {
139        self.0.encoded_with(name.0, value, indexing);
140    }
141}
142
143impl Source for () {
144    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
145        let fields: &[Entry<'_>] = &[];
146        fields.emit(sink);
147    }
148}
149
150impl Source for Group<'_> {
151    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
152        sink.group(self);
153    }
154}
155
156impl<S: Source + ?Sized> Source for &S {
157    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
158        (**self).emit(sink);
159    }
160}
161
162impl Source for [Entry<'_>] {
163    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
164        for entry in self {
165            sink.entry(*entry);
166        }
167    }
168}
169
170impl<const N: usize> Source for [Entry<'_>; N] {
171    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
172        self.as_slice().emit(sink);
173    }
174}
175
176impl Source for Vec<Entry<'_>> {
177    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
178        self.as_slice().emit(sink);
179    }
180}