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