1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*!
  Robust domain name parsing using the Public Suffix List

  This library allows you to easily and accurately parse any given domain name.

  ## Examples

  ```rust
  extern crate addr;

  use addr::{DomainName, DnsName, Email};
  # use addr::Result;

  # fn main() -> Result<()> {
    // You can find out the root domain
    // or extension of any given domain name
    let domain: DomainName = "www.example.com".parse().unwrap();
    assert_eq!(domain.root(), "example.com");
    assert_eq!(domain.root().suffix(), "com");

    let domain: DomainName = "www.食狮.中国".parse()?;
    assert_eq!(domain.root(), "xn--85x722f.xn--fiqs8s");
    assert_eq!(domain.root().suffix(), "xn--fiqs8s");

    let domain: DomainName = "www.xn--85x722f.xn--55qx5d.cn".parse()?;
    assert_eq!(domain.root(), "xn--85x722f.xn--55qx5d.cn");
    assert_eq!(domain.root().suffix(), "xn--55qx5d.cn");

    let domain: DomainName = "a.b.example.uk.com".parse()?;
    assert_eq!(domain.root(), "example.uk.com");
    assert_eq!(domain.root().suffix(), "uk.com");

    let name: DnsName = "_tcp.example.com.".parse()?;
    assert_eq!(name.root(), "example.com.");
    assert_eq!(name.root().suffix(), "com.");

    let email: Email = "чебурашка@ящик-с-апельсинами.рф".parse()?;
    assert_eq!(email.user(), "чебурашка");
    assert_eq!(email.host(), "xn-----8kcayoeblonkwzf2jqc1b.xn--p1ai");

    // In any case if the domain's suffix is in the list
    // then this is definately a registrable domain name
    assert!(domain.root().suffix().is_known());
  # Ok(())
  # }
  ```
!*/

#![recursion_limit = "1024"]

#[macro_use]
extern crate error_chain;
extern crate psl;
#[macro_use]
extern crate rental;
#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate idna;

mod parser;
mod host;
mod domain_impls;
mod dns_impls;
mod email;
pub mod errors;

use std::net::IpAddr;

pub use errors::{Result, Error};

rental! {
    mod inner {
        use psl::Domain as Root;

        #[rental(debug)]
        pub struct Domain {
            full: String,
            root: Root<'full>,
        }

        #[rental(debug)]
        pub struct Dns {
            full: String,
            root: Root<'full>,
        }
    }
}

#[derive(Debug)]
//#[derive(Clone, Ord, PartialOrd, Hash, Debug)]
pub struct DomainName {
    inner: inner::Domain,
}

/// Holds information about a particular DNS name
///
/// This is created by `List::parse_dns_name`.
//#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
#[derive(Debug)]
pub struct DnsName {
    inner: inner::Dns,
}

/// Holds information about a particular host
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum Host {
    Ip(IpAddr),
    Domain(DomainName),
}

#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Email {
    name: String,
    host: Host,
}