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