1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
use core::mem;

use std::net::SocketAddr;

use crate::http::{header::HeaderMap, Extensions};

/// Context is connection specific struct contain states for processing.
pub struct Context<'a, D, const HEADER_LIMIT: usize> {
    addr: SocketAddr,
    state: ContextState,
    // header map reused by next request.
    header: Option<HeaderMap>,
    // http extensions reused by next request.
    exts: Extensions,
    date: &'a D,
}

// A set of state for current request that are used after request's ownership is passed
// to service call.
struct ContextState(u8);

impl ContextState {
    // Enable when current request has 100-continue header.
    const EXPECT: u8 = 0b_0001;
    // Enable when current request is CONNECT method.
    const CONNECT: u8 = 0b_0010;
    // Enable when current request is HEAD method.
    const HEAD: u8 = 0b_0100;
    // Enable when current connection is supposed to be closed after current response is sent.
    const CLOSE: u8 = 0b_1000;

    const fn new() -> Self {
        Self(0)
    }

    fn insert(&mut self, other: u8) {
        self.0 |= other;
    }

    fn remove(&mut self, other: u8) {
        self.0 &= !other;
    }

    const fn contains(&self, other: u8) -> bool {
        (self.0 & other) == other
    }
}

impl<'a, D, const HEADER_LIMIT: usize> Context<'a, D, HEADER_LIMIT> {
    /// Context is constructed with reference of certain type that impl [DateTime] trait.
    ///
    /// [DateTime]: crate::date::DateTime
    #[inline]
    pub fn new(date: &'a D) -> Self {
        Self::with_addr(crate::unspecified_socket_addr(), date)
    }

    /// Context is constructed with [SocketAddr] and reference of certain type that impl [DateTime] trait.
    ///
    /// [DateTime]: crate::date::DateTime
    #[inline]
    pub fn with_addr(addr: SocketAddr, date: &'a D) -> Self {
        Self {
            addr,
            state: ContextState::new(),
            header: None,
            exts: Extensions::new(),
            date,
        }
    }

    /// Get Date type from Context.
    #[inline]
    pub fn date(&self) -> &D {
        self.date
    }

    /// Take ownership of HeaderMap stored in Context.
    ///
    /// When Context does not have one a new HeaderMap is constructed.
    #[inline]
    pub fn take_headers(&mut self) -> HeaderMap {
        self.header.take().unwrap_or_default()
    }

    /// Take ownership of Extensions stored in Context.
    #[inline]
    pub fn take_extensions(&mut self) -> Extensions {
        mem::take(&mut self.exts)
    }

    /// Replace a new HeaderMap in current Context.
    #[inline]
    pub fn replace_headers(&mut self, headers: HeaderMap) {
        debug_assert!(headers.is_empty());
        self.header = Some(headers);
    }

    /// Replace a new Extensions in current Context.
    #[inline]
    pub fn replace_extensions(&mut self, extensions: Extensions) {
        debug_assert!(extensions.is_empty());
        self.exts = extensions;
    }

    /// Reset Context's state to partial default state.
    #[inline]
    pub fn reset(&mut self) {
        self.state = ContextState::new();
    }

    /// Set Context's state to EXPECT header received.
    #[inline]
    pub fn set_expect_header(&mut self) {
        self.state.insert(ContextState::EXPECT)
    }

    /// Set Context's state to CONNECT method received.
    #[inline]
    pub fn set_connect_method(&mut self) {
        self.state.insert(ContextState::CONNECT)
    }

    /// Set Context's state to HEAD method received.
    #[inline]
    pub fn set_head_method(&mut self) {
        self.state.insert(ContextState::HEAD)
    }

    /// Set Context's state to Close.
    #[inline]
    pub fn set_close(&mut self) {
        self.state.insert(ContextState::CLOSE)
    }

    /// Remove Context's Close state.
    #[inline]
    pub fn remove_close(&mut self) {
        self.state.remove(ContextState::CLOSE)
    }

    /// Get expect header state.
    #[inline]
    pub const fn is_expect_header(&self) -> bool {
        self.state.contains(ContextState::EXPECT)
    }

    /// Get CONNECT method state.
    #[inline]
    pub const fn is_connect_method(&self) -> bool {
        self.state.contains(ContextState::CONNECT)
    }

    /// Get HEAD method state.
    #[inline]
    pub const fn is_head_method(&self) -> bool {
        self.state.contains(ContextState::HEAD)
    }

    /// Return true if connection type is `Connection: Close`.
    #[inline]
    pub const fn is_connection_closed(&self) -> bool {
        self.state.contains(ContextState::CLOSE)
    }

    /// Get remote socket address context associated with.
    #[inline]
    pub fn socket_addr(&self) -> &SocketAddr {
        &self.addr
    }
}