rama_haproxy/protocol/
mod.rs1mod ip;
9
10pub mod v1;
11pub mod v2;
12
13pub trait PartialResult {
16 fn is_complete(&self) -> bool {
20 !self.is_incomplete()
21 }
22
23 fn is_incomplete(&self) -> bool;
27}
28
29impl<T, E: PartialResult> PartialResult for Result<T, E> {
30 fn is_incomplete(&self) -> bool {
31 match self {
32 Ok(_) => false,
33 Err(error) => error.is_incomplete(),
34 }
35 }
36}
37
38impl PartialResult for v1::ParseError {
39 fn is_incomplete(&self) -> bool {
40 matches!(
41 self,
42 v1::ParseError::Partial
43 | v1::ParseError::MissingPrefix
44 | v1::ParseError::MissingProtocol
45 | v1::ParseError::MissingSourceAddress
46 | v1::ParseError::MissingDestinationAddress
47 | v1::ParseError::MissingSourcePort
48 | v1::ParseError::MissingDestinationPort
49 | v1::ParseError::MissingNewLine
50 )
51 }
52}
53
54impl PartialResult for v1::BinaryParseError {
55 fn is_incomplete(&self) -> bool {
56 match self {
57 v1::BinaryParseError::Parse(error) => error.is_incomplete(),
58 v1::BinaryParseError::InvalidUtf8(_) => false,
59 }
60 }
61}
62
63impl PartialResult for v2::ParseError {
64 fn is_incomplete(&self) -> bool {
65 matches!(
66 self,
67 v2::ParseError::Incomplete(..) | v2::ParseError::Partial(..)
68 )
69 }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq)]
85#[must_use = "this `HeaderResult` may contain a V1 or V2 `Err` variant, which should be handled"]
86pub enum HeaderResult<'a> {
87 V1(Result<v1::Header<'a>, v1::BinaryParseError>),
89 V2(Result<v2::Header<'a>, v2::ParseError>),
91}
92
93impl<'a> From<Result<v1::Header<'a>, v1::BinaryParseError>> for HeaderResult<'a> {
94 fn from(result: Result<v1::Header<'a>, v1::BinaryParseError>) -> Self {
95 HeaderResult::V1(result)
96 }
97}
98
99impl<'a> From<Result<v2::Header<'a>, v2::ParseError>> for HeaderResult<'a> {
100 fn from(result: Result<v2::Header<'a>, v2::ParseError>) -> Self {
101 HeaderResult::V2(result)
102 }
103}
104
105impl PartialResult for HeaderResult<'_> {
106 fn is_incomplete(&self) -> bool {
107 match self {
108 Self::V1(result) => result.is_incomplete(),
109 Self::V2(result) => result.is_incomplete(),
110 }
111 }
112}
113
114impl<'a> HeaderResult<'a> {
115 pub fn parse(input: &'a [u8]) -> HeaderResult<'a> {
118 let header = v2::Header::try_from(input);
119
120 if header.is_complete() && header.is_err() {
121 v1::Header::try_from(input).into()
122 } else {
123 header.into()
124 }
125 }
126}