sark_http/payload/response/headers/
list.rs1use std::{borrow::Cow, slice};
2
3use o3::alloc;
4
5use crate::{
6 field::{self, Lower, Value, storage},
7 h1::{codec::decode::fields, field::Entry},
8 payload::response::headers,
9};
10
11type Field<'field, N> = (N, Value<Cow<'field, [u8]>>);
12
13#[derive(PartialEq, Eq)]
14pub struct List<'field, N = Lower<Cow<'field, str>>> {
15 entries: Vec<Field<'field, N>>,
16}
17
18impl<N> Default for List<'_, N> {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl<'field, N> List<'field, N> {
25 pub fn new() -> Self {
26 Self {
27 entries: Vec::new(),
28 }
29 }
30
31 pub fn is_empty(&self) -> bool {
32 self.entries.is_empty()
33 }
34
35 pub fn len(&self) -> usize {
36 self.entries.len()
37 }
38
39 pub fn iter(&self) -> slice::Iter<'_, Field<'field, N>> {
40 self.entries.iter()
41 }
42
43 fn try_append(&mut self, field: Field<'field, N>) -> Result<(), alloc::Error> {
44 alloc::try_vacant(&mut self.entries)?(field);
45 Ok(())
46 }
47}
48
49impl<'field, N: AsRef<[u8]>> List<'field, N> {
50 pub fn get(&self, name: &str) -> Option<&Value<Cow<'field, [u8]>>> {
51 self.entries
52 .iter()
53 .find(|entry| entry.0.as_ref().eq_ignore_ascii_case(name.as_bytes()))
54 .map(|entry| &entry.1)
55 }
56
57 pub fn contains_key(&self, name: &str) -> bool {
58 self.get(name).is_some()
59 }
60}
61
62impl field::Source for List<'_> {
63 fn emit<'field>(&'field self, sink: &mut impl field::Sink<'field>) {
64 for (name, value) in &self.entries {
65 sink.entry(field::Entry::new(name.borrow(), value.borrow()));
66 }
67 }
68}
69
70impl headers::Source for List<'_, headers::Name<Cow<'_, str>>> {
71 fn emit<'field>(&'field self, sink: &mut impl headers::Sink<'field>) {
72 for (name, value) in &self.entries {
73 sink.entry(headers::Entry::new(name.borrow(), value.borrow()));
74 }
75 }
76}
77
78impl<'input> fields::Sink<'input> for List<'_> {
79 type Error = fields::Error;
80
81 fn push(&mut self, name: &'input [u8], value: &'input [u8]) -> Result<(), Self::Error> {
82 let name = Lower::try_copy(name).map_err(fields::Error::Name)?;
83 let value = Value::try_copy(value).map_err(fields::Error::Value)?;
84 self.try_append((name, value))
85 .map_err(fields::Error::Allocation)
86 }
87
88 fn entry(&mut self, field: Entry<'input>) -> Result<(), Self::Error> {
89 let name = Lower::try_entry(field)
90 .map_err(storage::Error::Allocation)
91 .map_err(fields::Error::Name)?;
92 let value = Value::try_entry(field)
93 .map_err(storage::Error::Allocation)
94 .map_err(fields::Error::Value)?;
95 self.try_append((name, value))
96 .map_err(fields::Error::Allocation)
97 }
98}
99
100impl<'a, 'field, N> IntoIterator for &'a List<'field, N> {
101 type Item = &'a Field<'field, N>;
102 type IntoIter = slice::Iter<'a, Field<'field, N>>;
103
104 fn into_iter(self) -> Self::IntoIter {
105 self.iter()
106 }
107}