turbopack_dev_server/source/
headers.rs1use std::{collections::BTreeMap, hash::Hash, mem::replace, ops::DerefMut};
2
3use serde::{Deserialize, Serialize};
4use turbo_tasks::{NonLocalValue, trace::TraceRawVcs};
5
6#[derive(
8 Clone, Debug, PartialEq, Eq, Default, Hash, TraceRawVcs, Serialize, Deserialize, NonLocalValue,
9)]
10#[serde(transparent)]
11pub struct Headers(BTreeMap<String, HeaderValue>);
12
13#[derive(Clone, Debug, PartialEq, Eq, Hash, TraceRawVcs, Serialize, Deserialize, NonLocalValue)]
16#[serde(untagged)]
17pub enum HeaderValue {
18 SingleString(String),
19 SingleBytes(Vec<u8>),
20 MultiStrings(Vec<String>),
21 MultiBytes(Vec<Vec<u8>>),
22}
23
24impl std::ops::Deref for Headers {
25 type Target = BTreeMap<String, HeaderValue>;
26 fn deref(&self) -> &Self::Target {
27 &self.0
28 }
29}
30
31impl DerefMut for Headers {
32 fn deref_mut(&mut self) -> &mut Self::Target {
33 &mut self.0
34 }
35}
36
37impl HeaderValue {
38 pub fn extend_with_string(&mut self, new: String) {
41 *self = match replace(self, HeaderValue::SingleBytes(Vec::new())) {
42 HeaderValue::SingleString(s) => HeaderValue::MultiStrings(vec![s, new]),
43 HeaderValue::SingleBytes(b) => HeaderValue::MultiBytes(vec![b, new.into()]),
44 HeaderValue::MultiStrings(mut v) => {
45 v.push(new);
46 HeaderValue::MultiStrings(v)
47 }
48 HeaderValue::MultiBytes(mut v) => {
49 v.push(new.into());
50 HeaderValue::MultiBytes(v)
51 }
52 }
53 }
54 pub fn extend_with_bytes(&mut self, new: Vec<u8>) {
57 *self = match replace(self, HeaderValue::SingleBytes(Vec::new())) {
58 HeaderValue::SingleString(s) => HeaderValue::MultiBytes(vec![s.into(), new]),
59 HeaderValue::SingleBytes(b) => HeaderValue::MultiBytes(vec![b, new]),
60 HeaderValue::MultiStrings(v) => {
61 let mut v: Vec<Vec<u8>> = v.into_iter().map(|s| s.into()).collect();
62 v.push(new);
63 HeaderValue::MultiBytes(v)
64 }
65 HeaderValue::MultiBytes(mut v) => {
66 v.push(new);
67 HeaderValue::MultiBytes(v)
68 }
69 }
70 }
71
72 pub fn contains(&self, string_value: &str) -> bool {
73 match self {
74 HeaderValue::SingleString(s) => s.contains(string_value),
75 HeaderValue::MultiStrings(s) => s.iter().any(|s| s.contains(string_value)),
76 _ => false,
77 }
78 }
79}