zino_core/validation/validator/
host.rs

1use self::InvalidHost::*;
2use super::Validator;
3use std::{fmt, num::ParseIntError};
4use url::{Host, ParseError};
5
6/// A validator for the host of a URL.
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct HostValidator;
9
10/// An error for the host validation.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum InvalidHost {
13    /// Invalid port.
14    InvalidPort(ParseIntError),
15    /// Invalid hostname.
16    InvalidHostname(ParseError),
17}
18
19impl fmt::Display for InvalidHost {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        match self {
22            InvalidPort(err) => write!(f, "invalid port: {err}"),
23            InvalidHostname(err) => write!(f, "invalid hostname: {err}"),
24        }
25    }
26}
27
28impl std::error::Error for InvalidHost {}
29
30impl Validator<str> for HostValidator {
31    type Error = InvalidHost;
32
33    #[inline]
34    fn validate(&self, data: &str) -> Result<(), Self::Error> {
35        if let Some((hostname, port)) = data.rsplit_once(':') {
36            if let Err(err) = port.parse::<u16>() {
37                Err(InvalidPort(err))
38            } else if let Err(err) = Host::parse(hostname) {
39                Err(InvalidHostname(err))
40            } else {
41                Ok(())
42            }
43        } else if let Err(err) = Host::parse(data) {
44            Err(InvalidHostname(err))
45        } else {
46            Ok(())
47        }
48    }
49}