Coverage Report

Created: 2025-12-28 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ppp-2.3.0/src/v1/mod.rs
Line
Count
Source
1
//! Version 1 of the HAProxy protocol (text version).
2
//!
3
//! See <https://haproxy.org/download/1.8/doc/proxy-protocol.txt>
4
5
mod error;
6
mod model;
7
8
pub use crate::ip::{IPv4, IPv6};
9
pub use error::{BinaryParseError, ParseError};
10
pub use model::{Addresses, Header, SEPARATOR, TCP4, TCP6, UNKNOWN};
11
pub use model::{PROTOCOL_PREFIX, PROTOCOL_SUFFIX};
12
use std::borrow::Cow;
13
use std::cmp::min;
14
use std::net::{AddrParseError, Ipv4Addr, Ipv6Addr};
15
use std::str::{from_utf8, FromStr};
16
17
const ZERO: &str = "0";
18
const NEWLINE: &str = "\n";
19
const CARRIAGE_RETURN: char = '\r';
20
21
/// The maximum length of a header in bytes.
22
const MAX_LENGTH: usize = 107;
23
/// The total number of parts in the header.
24
const PARTS: usize = 7;
25
26
/// Parses a text PROXY protocol header.
27
/// The given string is expected to only include the header and to end in \r\n.
28
0
fn parse_header(header: &str) -> Result<Header, ParseError> {
29
0
    if header.is_empty() {
30
0
        return Err(ParseError::MissingPrefix);
31
0
    } else if header.len() > MAX_LENGTH {
32
0
        return Err(ParseError::HeaderTooLong);
33
0
    }
34
35
0
    let mut iterator = header
36
0
        .splitn(PARTS, |c| c == SEPARATOR || c == CARRIAGE_RETURN)
37
0
        .peekable();
38
39
0
    let prefix = iterator.next().ok_or(ParseError::MissingPrefix)?;
40
41
0
    if !prefix.is_empty() && PROTOCOL_PREFIX.starts_with(prefix) && header.ends_with(prefix) {
42
0
        return Err(ParseError::Partial);
43
0
    } else if prefix != PROTOCOL_PREFIX {
44
0
        return Err(ParseError::InvalidPrefix);
45
0
    }
46
47
0
    let addresses = match iterator.next() {
48
0
        Some(TCP4) => {
49
0
            let (source_address, destination_address, source_port, destination_port) =
50
0
                parse_addresses::<Ipv4Addr, _>(&mut iterator)?;
51
52
0
            Addresses::Tcp4(IPv4 {
53
0
                source_address,
54
0
                source_port,
55
0
                destination_address,
56
0
                destination_port,
57
0
            })
58
        }
59
0
        Some(TCP6) => {
60
0
            let (source_address, destination_address, source_port, destination_port) =
61
0
                parse_addresses::<Ipv6Addr, _>(&mut iterator)?;
62
63
0
            Addresses::Tcp6(IPv6 {
64
0
                source_address,
65
0
                source_port,
66
0
                destination_address,
67
0
                destination_port,
68
0
            })
69
        }
70
0
        Some(UNKNOWN) => {
71
0
            while iterator.next_if(|&s| s != NEWLINE).is_some() {}
72
73
0
            Addresses::Unknown
74
        }
75
0
        Some(protocol) if protocol.is_empty() && iterator.peek().is_none() => {
76
0
            return Err(ParseError::MissingProtocol)
77
        }
78
0
        Some(protocol)
79
0
            if !protocol.is_empty()
80
0
                && header.ends_with(protocol)
81
0
                && (TCP4.starts_with(protocol) || UNKNOWN.starts_with(protocol)) =>
82
        {
83
0
            return Err(ParseError::Partial)
84
        }
85
0
        Some(_) => return Err(ParseError::InvalidProtocol),
86
0
        None => return Err(ParseError::MissingProtocol),
87
    };
88
89
0
    let newline = iterator
90
0
        .next()
91
0
        .filter(|s| !s.is_empty())
92
0
        .ok_or(ParseError::MissingNewLine)?;
93
94
0
    if newline != NEWLINE {
95
0
        return Err(ParseError::InvalidSuffix);
96
0
    }
97
98
0
    Ok(Header {
99
0
        header: Cow::Borrowed(header),
100
0
        addresses,
101
0
    })
102
0
}
103
104
/// Parses the addresses and ports from a PROXY protocol header for IPv4 and IPv6.
105
0
fn parse_addresses<'a, T: FromStr<Err = AddrParseError>, I: Iterator<Item = &'a str>>(
106
0
    iterator: &mut I,
107
0
) -> Result<(T, T, u16, u16), ParseError> {
108
0
    let source_address = iterator.next().ok_or(ParseError::MissingSourceAddress)?;
109
0
    let destination_address = iterator
110
0
        .next()
111
0
        .ok_or(ParseError::MissingDestinationAddress)?;
112
0
    let source_port = iterator.next().ok_or(ParseError::MissingSourcePort)?;
113
0
    let destination_port = iterator.next().ok_or(ParseError::MissingDestinationPort)?;
114
115
0
    let source_address = source_address
116
0
        .parse::<T>()
117
0
        .map_err(ParseError::InvalidSourceAddress)?;
118
0
    let destination_address = destination_address
119
0
        .parse::<T>()
120
0
        .map_err(ParseError::InvalidDestinationAddress)?;
121
122
0
    if source_port.starts_with(ZERO) && source_port != ZERO {
123
0
        return Err(ParseError::InvalidSourcePort(None));
124
0
    }
125
126
0
    let source_port = source_port
127
0
        .parse::<u16>()
128
0
        .map_err(|e| ParseError::InvalidSourcePort(Some(e)))?;
Unexecuted instantiation: ppp::v1::parse_addresses::<core::net::ip_addr::Ipv4Addr, core::iter::adapters::peekable::Peekable<core::str::iter::SplitN<ppp::v1::parse_header::{closure#0}>>>::{closure#0}
Unexecuted instantiation: ppp::v1::parse_addresses::<core::net::ip_addr::Ipv6Addr, core::iter::adapters::peekable::Peekable<core::str::iter::SplitN<ppp::v1::parse_header::{closure#0}>>>::{closure#0}
129
130
0
    if destination_port.starts_with(ZERO) && destination_port != ZERO {
131
0
        return Err(ParseError::InvalidDestinationPort(None));
132
0
    }
133
134
0
    let destination_port = destination_port
135
0
        .parse::<u16>()
136
0
        .map_err(|e| ParseError::InvalidDestinationPort(Some(e)))?;
Unexecuted instantiation: ppp::v1::parse_addresses::<core::net::ip_addr::Ipv4Addr, core::iter::adapters::peekable::Peekable<core::str::iter::SplitN<ppp::v1::parse_header::{closure#0}>>>::{closure#1}
Unexecuted instantiation: ppp::v1::parse_addresses::<core::net::ip_addr::Ipv6Addr, core::iter::adapters::peekable::Peekable<core::str::iter::SplitN<ppp::v1::parse_header::{closure#0}>>>::{closure#1}
137
138
0
    Ok((
139
0
        source_address,
140
0
        destination_address,
141
0
        source_port,
142
0
        destination_port,
143
0
    ))
144
0
}
Unexecuted instantiation: ppp::v1::parse_addresses::<core::net::ip_addr::Ipv4Addr, core::iter::adapters::peekable::Peekable<core::str::iter::SplitN<ppp::v1::parse_header::{closure#0}>>>
Unexecuted instantiation: ppp::v1::parse_addresses::<core::net::ip_addr::Ipv6Addr, core::iter::adapters::peekable::Peekable<core::str::iter::SplitN<ppp::v1::parse_header::{closure#0}>>>
145
146
impl<'a> TryFrom<&'a str> for Header<'a> {
147
    type Error = ParseError;
148
149
0
    fn try_from(input: &'a str) -> Result<Self, Self::Error> {
150
0
        let length = match input.find(CARRIAGE_RETURN) {
151
0
            Some(suffix) => min(suffix + PROTOCOL_SUFFIX.len(), input.len()),
152
0
            None if input.len() >= MAX_LENGTH => return Err(ParseError::HeaderTooLong),
153
0
            None => input.len(),
154
        };
155
156
0
        parse_header(&input[..length])
157
0
    }
158
}
159
160
impl<'a> TryFrom<&'a [u8]> for Header<'a> {
161
    type Error = BinaryParseError;
162
163
0
    fn try_from(input: &'a [u8]) -> Result<Self, Self::Error> {
164
0
        let length = match input.iter().position(|&c| CARRIAGE_RETURN == (c as char)) {
165
0
            Some(suffix) => min(suffix + PROTOCOL_SUFFIX.len(), input.len()),
166
0
            None if input.len() >= MAX_LENGTH => return Err(ParseError::HeaderTooLong.into()),
167
0
            None => input.len(),
168
        };
169
0
        let header = from_utf8(&input[..length])?;
170
171
0
        parse_header(header).map_err(BinaryParseError::Parse)
172
0
    }
173
}
174
175
impl FromStr for Addresses {
176
    type Err = ParseError;
177
178
0
    fn from_str(s: &str) -> Result<Self, Self::Err> {
179
0
        Ok(Header::try_from(s)?.addresses)
180
0
    }
181
}
182
183
impl FromStr for Header<'static> {
184
    type Err = ParseError;
185
186
0
    fn from_str(s: &str) -> Result<Self, Self::Err> {
187
0
        Ok(Header::try_from(s)?.to_owned())
188
0
    }
189
}
190
191
#[cfg(test)]
192
mod tests {
193
    use super::*;
194
195
    #[test]
196
    fn bytes_invalid_utf8() {
197
        let text = b"Hello \xF0\x90\x80World\r\n";
198
199
        assert_eq!(
200
            Header::try_from(&text[..]).unwrap_err(),
201
            BinaryParseError::InvalidUtf8(from_utf8(text).unwrap_err())
202
        );
203
    }
204
205
    #[test]
206
    fn exact_tcp4() {
207
        let ip: Ipv4Addr = "255.255.255.255".parse().unwrap();
208
        let port = 65535;
209
        let text = "PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n";
210
        let expected = Header::new(text, Addresses::new_tcp4(ip, ip, port, port));
211
212
        assert_eq!(Header::try_from(text), Ok(expected.to_owned()));
213
        assert_eq!(Header::try_from(text.as_bytes()), Ok(expected));
214
    }
215
216
    #[test]
217
    fn valid_tcp4() {
218
        let ip: Ipv4Addr = "255.255.255.255".parse().unwrap();
219
        let port = 65535;
220
        let text = "PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\nFoobar";
221
        let expected = Header::new(
222
            "PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n",
223
            Addresses::new_tcp4(ip, ip, port, port),
224
        );
225
226
        assert_eq!(Header::try_from(text), Ok(expected.to_owned()));
227
        assert_eq!(Header::try_from(text.as_bytes()), Ok(expected));
228
    }
229
230
    #[test]
231
    fn parse_partial() {
232
        let text = "PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535";
233
234
        assert_eq!(
235
            Header::try_from(text).unwrap_err(),
236
            ParseError::MissingNewLine
237
        );
238
        assert_eq!(
239
            Header::try_from(text.as_bytes()).unwrap_err(),
240
            ParseError::MissingNewLine.into()
241
        );
242
    }
243
244
    #[test]
245
    fn parse_tcp4_invalid() {
246
        let text = "PROXY TCP4 255.255.255.255 256.255.255.255 65535 65535\r\n";
247
248
        assert_eq!(
249
            Header::try_from(text),
250
            Err(ParseError::InvalidDestinationAddress(
251
                "".parse::<Ipv4Addr>().unwrap_err()
252
            ))
253
        );
254
        assert_eq!(
255
            Header::try_from(text.as_bytes()),
256
            Err(ParseError::InvalidDestinationAddress("".parse::<Ipv4Addr>().unwrap_err()).into())
257
        );
258
    }
259
260
    #[test]
261
    fn parse_tcp4_leading_zeroes() {
262
        let text = "PROXY TCP4 255.0255.255.255 255.255.255.255 65535 65535\r\n";
263
264
        assert_eq!(
265
            Header::try_from(text),
266
            Err(ParseError::InvalidSourceAddress(
267
                "".parse::<Ipv4Addr>().unwrap_err()
268
            ))
269
        );
270
        assert_eq!(
271
            Header::try_from(text.as_bytes()),
272
            Err(ParseError::InvalidSourceAddress("".parse::<Ipv4Addr>().unwrap_err()).into())
273
        );
274
    }
275
276
    #[test]
277
    fn parse_unknown_connection() {
278
        let text = "PROXY UNKNOWN\r\nTwo";
279
280
        assert_eq!(
281
            Header::try_from(text),
282
            Ok(Header::new("PROXY UNKNOWN\r\n", Addresses::default()))
283
        );
284
        assert_eq!(
285
            Header::try_from(text.as_bytes()),
286
            Ok(Header::new("PROXY UNKNOWN\r\n", Addresses::default()))
287
        );
288
    }
289
290
    #[test]
291
    fn valid_tcp6() {
292
        let ip: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap();
293
        let port = 65535;
294
        let text = "PROXY TCP6 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\nHi!";
295
        let expected = Header::new("PROXY TCP6 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n", Addresses::new_tcp6(ip, ip, port, port));
296
297
        assert_eq!(Header::try_from(text), Ok(expected.to_owned()));
298
        assert_eq!(Header::try_from(text.as_bytes()), Ok(expected));
299
    }
300
301
    #[test]
302
    fn valid_tcp6_short() {
303
        let ip: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap();
304
        let port = 65535;
305
        let short_ip = "::1".parse().unwrap();
306
        let text = "PROXY TCP6 ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\nHi!";
307
        let expected = Header::new(
308
            "PROXY TCP6 ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n",
309
            Addresses::new_tcp6(short_ip, ip, port, port),
310
        );
311
312
        assert_eq!(Header::try_from(text), Ok(expected.to_owned()));
313
        assert_eq!(Header::try_from(text.as_bytes()), Ok(expected));
314
    }
315
316
    #[test]
317
    fn parse_tcp6_invalid() {
318
        let text = "PROXY TCP6 ffff:gggg:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n";
319
320
        assert_eq!(
321
            Header::try_from(text),
322
            Err(ParseError::InvalidSourceAddress(
323
                "".parse::<Ipv6Addr>().unwrap_err()
324
            ))
325
        );
326
        assert_eq!(
327
            Header::try_from(text.as_bytes()),
328
            Err(ParseError::InvalidSourceAddress("".parse::<Ipv6Addr>().unwrap_err()).into())
329
        );
330
    }
331
332
    #[test]
333
    fn parse_tcp6_leading_zeroes() {
334
        let text = "PROXY TCP6 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:0ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n";
335
336
        assert_eq!(
337
            Header::try_from(text),
338
            Err(ParseError::InvalidDestinationAddress(
339
                "".parse::<Ipv6Addr>().unwrap_err()
340
            ))
341
        );
342
        assert_eq!(
343
            Header::try_from(text.as_bytes()),
344
            Err(ParseError::InvalidDestinationAddress("".parse::<Ipv6Addr>().unwrap_err()).into())
345
        );
346
    }
347
348
    #[test]
349
    fn parse_tcp6_shortened_connection() {
350
        let ip: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap();
351
        let short_ip = "ffff::ffff".parse().unwrap();
352
        let port = 65535;
353
        let text = "PROXY TCP6 ffff::ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n";
354
        let expected = Header::new(text, Addresses::new_tcp6(short_ip, ip, port, port));
355
356
        assert_eq!(Header::try_from(text), Ok(expected.to_owned()));
357
        assert_eq!(Header::try_from(text.as_bytes()), Ok(expected));
358
    }
359
360
    #[test]
361
    fn parse_tcp6_single_zero() {
362
        let ip: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap();
363
        let short_ip = "ffff:ffff:ffff:ffff::ffff:ffff:ffff".parse().unwrap();
364
        let port = 65535;
365
        let text = "PROXY TCP6 ffff:ffff:ffff:ffff::ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n";
366
        let expected = Header::new(text, Addresses::new_tcp6(short_ip, ip, port, port));
367
368
        assert_eq!(Header::try_from(text), Ok(expected.to_owned()));
369
        assert_eq!(Header::try_from(text.as_bytes()), Ok(expected));
370
    }
371
372
    #[test]
373
    fn parse_tcp6_wildcard() {
374
        let ip: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap();
375
        let short_ip = "::".parse().unwrap();
376
        let port = 65535;
377
        let text = "PROXY TCP6 :: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n";
378
        let expected = Header::new(text, Addresses::new_tcp6(short_ip, ip, port, port));
379
380
        assert_eq!(Header::try_from(text), Ok(expected.to_owned()));
381
        assert_eq!(Header::try_from(text.as_bytes()), Ok(expected));
382
    }
383
384
    #[test]
385
    fn parse_tcp6_implied() {
386
        let ip: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap();
387
        let short_ip = "ffff::".parse().unwrap();
388
        let port = 65535;
389
        let text = "PROXY TCP6 ffff:: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n";
390
        let expected = Header::new(text, Addresses::new_tcp6(short_ip, ip, port, port));
391
392
        assert_eq!(Header::try_from(text), Ok(expected.to_owned()));
393
        assert_eq!(Header::try_from(text.as_bytes()), Ok(expected));
394
    }
395
396
    #[test]
397
    fn parse_tcp6_over_shortened() {
398
        let text = "PROXY TCP6 ffff::ffff:ffff:ffff:ffff::ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n";
399
400
        assert_eq!(
401
            Header::try_from(text),
402
            Err(ParseError::InvalidSourceAddress(
403
                "".parse::<Ipv6Addr>().unwrap_err()
404
            ))
405
        );
406
        assert_eq!(
407
            Header::try_from(text.as_bytes()),
408
            Err(ParseError::InvalidSourceAddress("".parse::<Ipv6Addr>().unwrap_err()).into())
409
        );
410
    }
411
412
    #[test]
413
    fn parse_worst_case() {
414
        let text = "PROXY UNKNOWN ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n";
415
        let expected = Header::new(text, Addresses::Unknown);
416
417
        assert_eq!(Header::try_from(text), Ok(expected.to_owned()));
418
        assert_eq!(Header::try_from(text.as_bytes()), Ok(expected));
419
    }
420
421
    #[test]
422
    fn parse_leading_zeroes_in_source_port() {
423
        let text = "PROXY TCP4 255.255.255.255 255.255.255.255 05535 65535\r\n";
424
425
        assert_eq!(
426
            Header::try_from(text),
427
            Err(ParseError::InvalidSourcePort(None))
428
        );
429
        assert_eq!(
430
            Header::try_from(text.as_bytes()),
431
            Err(ParseError::InvalidSourcePort(None).into())
432
        );
433
    }
434
435
    #[test]
436
    fn parse_leading_zeroes_in_destination_port() {
437
        let text = "PROXY TCP4 255.255.255.255 255.255.255.255 65535 05535\r\n";
438
439
        assert_eq!(
440
            Header::try_from(text),
441
            Err(ParseError::InvalidDestinationPort(None))
442
        );
443
        assert_eq!(
444
            Header::try_from(text.as_bytes()),
445
            Err(ParseError::InvalidDestinationPort(None).into())
446
        );
447
    }
448
449
    #[test]
450
    fn parse_source_port_too_large() {
451
        let text = "PROXY TCP6 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65536 65535\r\n";
452
453
        assert_eq!(
454
            Header::try_from(text),
455
            Err(ParseError::InvalidSourcePort(Some(
456
                "65536".parse::<u16>().unwrap_err()
457
            )))
458
        );
459
        assert_eq!(
460
            Header::try_from(text.as_bytes()),
461
            Err(ParseError::InvalidSourcePort(Some("65536".parse::<u16>().unwrap_err())).into())
462
        );
463
    }
464
465
    #[test]
466
    fn parse_destination_port_too_large() {
467
        let text = "PROXY TCP6 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65536\r\n";
468
469
        assert_eq!(
470
            Header::try_from(text),
471
            Err(ParseError::InvalidDestinationPort(Some(
472
                "65536".parse::<u16>().unwrap_err()
473
            )))
474
        );
475
        assert_eq!(
476
            Header::try_from(text.as_bytes()),
477
            Err(
478
                ParseError::InvalidDestinationPort(Some("65536".parse::<u16>().unwrap_err()))
479
                    .into()
480
            )
481
        );
482
    }
483
484
    #[test]
485
    fn parse_lowercase_proxy() {
486
        let text = "proxy UNKNOWN\r\n";
487
488
        assert_eq!(Header::try_from(text), Err(ParseError::InvalidPrefix));
489
        assert_eq!(
490
            Header::try_from(text.as_bytes()),
491
            Err(ParseError::InvalidPrefix.into())
492
        );
493
    }
494
495
    #[test]
496
    fn parse_lowercase_protocol_family() {
497
        let text = "PROXY tcp4\r\n";
498
499
        assert_eq!(Header::try_from(text), Err(ParseError::InvalidProtocol));
500
        assert_eq!(
501
            Header::try_from(text.as_bytes()),
502
            Err(ParseError::InvalidProtocol.into())
503
        );
504
    }
505
506
    #[test]
507
    fn parse_too_long() {
508
        let text = "PROXY UNKNOWN ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535  \r\n";
509
510
        assert_eq!(Header::try_from(text), Err(ParseError::HeaderTooLong));
511
        assert_eq!(
512
            Header::try_from(text.as_bytes()),
513
            Err(ParseError::HeaderTooLong.into())
514
        );
515
    }
516
517
    #[test]
518
    fn parse_more_than_one_space() {
519
        let text = "PROXY  TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n";
520
521
        assert_eq!(Header::try_from(text), Err(ParseError::InvalidProtocol));
522
        assert_eq!(
523
            Header::try_from(text.as_bytes()),
524
            Err(ParseError::InvalidProtocol.into())
525
        );
526
    }
527
528
    #[test]
529
    fn parse_more_than_one_space_source_address() {
530
        let text = "PROXY TCP4  255.255.255.255 255.255.255.255 65535 65535\r\n";
531
532
        assert_eq!(
533
            Header::try_from(text),
534
            Err(ParseError::InvalidSourceAddress("".parse::<Ipv4Addr>().unwrap_err()).into())
535
        );
536
        assert_eq!(
537
            Header::try_from(text.as_bytes()),
538
            Err(ParseError::InvalidSourceAddress("".parse::<Ipv4Addr>().unwrap_err()).into())
539
        );
540
    }
541
542
    #[test]
543
    fn parse_more_than_one_space_destination_address() {
544
        let text = "PROXY TCP4 255.255.255.255  255.255.255.255 65535 65535\r\n";
545
546
        assert_eq!(
547
            Header::try_from(text),
548
            Err(ParseError::InvalidDestinationAddress(
549
                "".parse::<Ipv4Addr>().unwrap_err()
550
            ))
551
        );
552
        assert_eq!(
553
            Header::try_from(text.as_bytes()),
554
            Err(ParseError::InvalidDestinationAddress("".parse::<Ipv4Addr>().unwrap_err()).into())
555
        );
556
    }
557
558
    #[test]
559
    fn parse_more_than_one_space_source_port() {
560
        let text = "PROXY TCP4 255.255.255.255 255.255.255.255  65535 65535\r\n";
561
562
        assert_eq!(
563
            Header::try_from(text),
564
            Err(ParseError::InvalidSourcePort(Some(
565
                "".parse::<u16>().unwrap_err()
566
            )))
567
        );
568
        assert_eq!(
569
            Header::try_from(text.as_bytes()),
570
            Err(ParseError::InvalidSourcePort(Some("".parse::<u16>().unwrap_err())).into())
571
        );
572
    }
573
574
    #[test]
575
    fn parse_more_than_one_space_destination_port() {
576
        let text = "PROXY TCP4 255.255.255.255 255.255.255.255 65535  65535\r\n";
577
578
        assert_eq!(
579
            Header::try_from(text),
580
            Err(ParseError::InvalidDestinationPort(Some(
581
                "".parse::<u16>().unwrap_err()
582
            )))
583
        );
584
        assert_eq!(
585
            Header::try_from(text.as_bytes()),
586
            Err(ParseError::InvalidDestinationPort(Some("".parse::<u16>().unwrap_err())).into())
587
        );
588
    }
589
590
    #[test]
591
    fn parse_more_than_one_space_end() {
592
        let text = "PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535 \r\n";
593
594
        assert_eq!(Header::try_from(text), Err(ParseError::InvalidSuffix));
595
        assert_eq!(
596
            Header::try_from(text.as_bytes()),
597
            Err(ParseError::InvalidSuffix.into())
598
        );
599
    }
600
601
    #[test]
602
    fn parse_partial_prefix() {
603
        let text = "PROX\r\n";
604
605
        assert_eq!(Header::try_from(text), Err(ParseError::InvalidPrefix));
606
        assert_eq!(
607
            Header::try_from(text.as_bytes()),
608
            Err(ParseError::InvalidPrefix.into())
609
        );
610
    }
611
612
    #[test]
613
    fn parse_empty_newline() {
614
        let text = "\r\n";
615
616
        assert_eq!(Header::try_from(text), Err(ParseError::InvalidPrefix));
617
        assert_eq!(
618
            Header::try_from(text.as_bytes()),
619
            Err(ParseError::InvalidPrefix.into())
620
        );
621
    }
622
623
    #[test]
624
    fn parse_partial_prefix_missing_newline() {
625
        let text = "PROX";
626
627
        assert_eq!(Header::try_from(text), Err(ParseError::Partial));
628
        assert_eq!(
629
            Header::try_from(text.as_bytes()),
630
            Err(ParseError::Partial.into())
631
        );
632
    }
633
634
    #[test]
635
    fn parse_partial_protocol_missing_newline() {
636
        let text = "PROXY UNKN";
637
638
        assert_eq!(Header::try_from(text), Err(ParseError::Partial));
639
        assert_eq!(
640
            Header::try_from(text.as_bytes()),
641
            Err(ParseError::Partial.into())
642
        );
643
    }
644
645
    #[test]
646
    fn parse_partial_protocol_with_newline() {
647
        let text = "PROXY UNKN\r\n";
648
649
        assert_eq!(Header::try_from(text), Err(ParseError::InvalidProtocol));
650
        assert_eq!(
651
            Header::try_from(text.as_bytes()),
652
            Err(ParseError::InvalidProtocol.into())
653
        );
654
    }
655
656
    #[test]
657
    fn parse_empty_protocol_with_newline() {
658
        let text = "PROXY \r\n";
659
660
        assert_eq!(Header::try_from(text), Err(ParseError::InvalidProtocol));
661
        assert_eq!(
662
            Header::try_from(text.as_bytes()),
663
            Err(ParseError::InvalidProtocol.into())
664
        );
665
    }
666
667
    #[test]
668
    fn parse_empty() {
669
        let text = "";
670
671
        assert_eq!(Header::try_from(text), Err(ParseError::MissingPrefix));
672
        assert_eq!(
673
            Header::try_from(text.as_bytes()),
674
            Err(ParseError::MissingPrefix.into())
675
        );
676
    }
677
678
    #[test]
679
    fn parse_no_new_line() {
680
        let text = "PROXY TCP4 127.0.0.1 192.168.1.1 80 443\r\t";
681
682
        assert_eq!(Header::try_from(text), Err(ParseError::InvalidSuffix));
683
        assert_eq!(
684
            Header::try_from(text.as_bytes()),
685
            Err(ParseError::InvalidSuffix.into())
686
        );
687
    }
688
689
    #[test]
690
    fn parse_invalid_prefix_missing_newline() {
691
        let text = "PRAX";
692
693
        assert_eq!(Header::try_from(text), Err(ParseError::InvalidPrefix));
694
        assert_eq!(
695
            Header::try_from(text.as_bytes()),
696
            Err(ParseError::InvalidPrefix.into())
697
        );
698
    }
699
700
    #[test]
701
    fn parse_partial_newline() {
702
        let text = "PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r";
703
        assert_eq!(
704
            Header::try_from(text).unwrap_err(),
705
            ParseError::MissingNewLine
706
        );
707
        assert_eq!(
708
            Header::try_from(text.as_bytes()).unwrap_err(),
709
            ParseError::MissingNewLine.into()
710
        );
711
    }
712
713
    #[test]
714
    fn parse_invalid_prefix_partial_newline() {
715
        let text = "abc\r";
716
        assert_eq!(
717
            Header::try_from(text).unwrap_err(),
718
            ParseError::InvalidPrefix
719
        );
720
        assert_eq!(
721
            Header::try_from(text.as_bytes()).unwrap_err(),
722
            ParseError::InvalidPrefix.into()
723
        );
724
    }
725
}