summaryrefslogtreecommitdiffstats
path: root/internals/src/bind/idna.rs
blob: be11a71b9cea907524db774453fb77b6c4f1545f (plain)
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
use idna;
use soft_ascii_string::SoftAsciiString;

use error::{EncodingError, EncodingErrorKind};

/// uses puny code on given domain to return a ascii representation
///
/// # Implementation Detail
/// this function uses `idna::domain_to_ascii`, see the
/// `idna` crates documentation fore more details on how
/// exactly all edgecase are handled
///
/// # Note
/// that this function does not validate the domain, e.g.
/// if you puny code the domain `"this seems\0so;wrong"` it
/// will return `Ok("this seems\0so;wrong")`
///
pub fn puny_code_domain<R: AsRef<str>>(domain: R) -> Result<SoftAsciiString, EncodingError> {
    _puny_code_domain(domain.as_ref())
}

fn _puny_code_domain(domain: &str) -> Result<SoftAsciiString, EncodingError> {
    match idna::domain_to_ascii(domain) {
        Ok(asciified) => {
            //SAFE: well we converted it to ascii, so it's ascii
            Ok(SoftAsciiString::from_unchecked(asciified))
        }
        Err(_non_informative_err) => Err(EncodingErrorKind::NotEncodable {
            encoding: "punycode",
        }
        .into()),
    }
}

#[cfg(test)]
mod test {
    use super::puny_code_domain;
    use idna;

    #[test]
    fn idna_does_not_validate() {
        let domain = "this seems\0so;wrong";
        assert_eq!(domain.to_owned(), assert_ok!(idna::domain_to_ascii(domain)));
    }

    #[test]
    fn nop_puny_code() {
        let domain = "is_ascii.notadomain";

        let encoded = assert_ok!(puny_code_domain(domain));
        assert_eq!(&*encoded, "is_ascii.notadomain");
    }
    #[test]
    fn puny_code_ascii_mail() {
        let domain = "nöt_ascii.ü";
        let encoded = assert_ok!(puny_code_domain(domain));
        assert_eq!(&*encoded, "xn--nt_ascii-n4a.xn--tda");
    }
}