sark_http/field/head/
mod.rs1pub mod headers;
2pub(super) mod known;
3mod parse;
4
5use core::mem;
6
7use known::Known;
8
9use crate::{
10 field::text::IntError,
11 h1::{
12 field::{self, TokenError, value},
13 switch, target,
14 },
15};
16
17#[derive(Clone, Copy, PartialEq, Eq, Debug)]
18pub enum Error {
19 Value,
20 Connection(TokenError),
21 ContentLength(IntError),
22 TransferEncoding(value::Error),
23 Host(target::HostError),
24 Message(field::Error),
25 Routing(target::Invalid),
26 Upgrade(switch::UpgradeError),
27}
28
29const _: () = {
30 assert!(mem::size_of::<Error>() == 3 * mem::size_of::<usize>());
31 assert!(mem::size_of::<Option<Error>>() == mem::size_of::<Error>());
32 assert!(!mem::needs_drop::<Error>());
33};
34
35#[derive(Clone, Copy, Default, PartialEq, Eq)]
36pub struct Flags(u16);
37
38impl Flags {
39 pub const CONNECTION_CLOSE: u16 = 1 << 9;
40 pub const CONNECTION_KEEP_ALIVE: u16 = 1 << 10;
41
42 pub fn is_set(self, bit: u16) -> bool {
43 (self.0 & bit) != 0
44 }
45
46 pub fn set(&mut self, bit: u16) {
47 self.0 |= bit;
48 }
49
50 pub fn is_close(self, version: &[u8]) -> bool {
51 if self.is_set(Self::CONNECTION_CLOSE) {
52 return true;
53 }
54 if self.is_set(Self::CONNECTION_KEEP_ALIVE) {
55 return false;
56 }
57 version == b"HTTP/1.0"
58 }
59}
60
61#[repr(u8)]
62#[derive(Clone, Copy, PartialEq, Eq, Debug)]
63pub enum Name {
64 Invalid,
65 Method,
66 Scheme,
67 Path,
68 Status,
69 Authority,
70 Protocol,
71 Host,
72 Connection,
73 ContentLength,
74 TransferEncoding,
75 Expect,
76 AcceptEncoding,
77 Te,
78 KeepAlive,
79 ProxyConnection,
80 Upgrade,
81 Regular,
82}
83
84impl Name {
85 pub const H1: [Self; 7] = [
86 Self::Host,
87 Self::Connection,
88 Self::ContentLength,
89 Self::TransferEncoding,
90 Self::Expect,
91 Self::AcceptEncoding,
92 Self::Upgrade,
93 ];
94
95 pub const fn wire(&self) -> &[u8] {
96 match self {
97 Self::Method => b":method",
98 Self::Scheme => b":scheme",
99 Self::Path => b":path",
100 Self::Status => b":status",
101 Self::Authority => b":authority",
102 Self::Protocol => b":protocol",
103 Self::Host => Known::Host.as_str().as_bytes(),
104 Self::Connection => Known::Connection.as_str().as_bytes(),
105 Self::ContentLength => Known::ContentLength.as_str().as_bytes(),
106 Self::TransferEncoding => Known::TransferEncoding.as_str().as_bytes(),
107 Self::Expect => Known::Expect.as_str().as_bytes(),
108 Self::AcceptEncoding => Known::AcceptEncoding.as_str().as_bytes(),
109 Self::Te => Known::Te.as_str().as_bytes(),
110 Self::KeepAlive => Known::KeepAlive.as_str().as_bytes(),
111 Self::ProxyConnection => Known::ProxyConnection.as_str().as_bytes(),
112 Self::Upgrade => Known::Upgrade.as_str().as_bytes(),
113 Self::Invalid | Self::Regular => b"",
114 }
115 }
116
117 pub const fn is_required(self) -> bool {
118 matches!(
119 self,
120 Self::Host
121 | Self::Connection
122 | Self::ContentLength
123 | Self::TransferEncoding
124 | Self::Expect
125 | Self::Upgrade
126 )
127 }
128
129 pub fn from_h1(name: &[u8]) -> Option<Self> {
130 let known = match name.len() {
131 4 => Self::Host,
132 6 => Self::Expect,
133 7 => Self::Upgrade,
134 10 if name.first()?.eq_ignore_ascii_case(&b'k') => Self::KeepAlive,
135 10 => Self::Connection,
136 14 => Self::ContentLength,
137 15 => Self::AcceptEncoding,
138 17 => Self::TransferEncoding,
139 _ => return None,
140 };
141 name.eq_ignore_ascii_case(known.wire()).then_some(known)
142 }
143}
144
145pub const MAX_HEADER_LINE_BYTES: usize = 8 * 1024;