rlibdns 0.1.211

Rust DNS Library
Documentation
use std::io;

pub fn to_octal(n: u16) -> String {
    if n == 0 {
        return "00".to_string();
    }

    let mut tmp = n;
    let mut rev = Vec::with_capacity(6);

    while tmp > 0 {
        let d = (tmp & 0b111) as u8;
        rev.push(b'0' + d);
        tmp >>= 3;
    }

    let mut out = String::with_capacity(rev.len() + 1);
    out.push('0');
    for &b in rev.iter().rev() {
        out.push(b as char);
    }
    out
}

pub fn from_octal(input: &str) -> io::Result<u16> {
    let mut s = input.trim();

    if let Some(rest) = s.strip_prefix("0o").or_else(|| s.strip_prefix("0O")) {
        s = rest;
    } else if s.len() > 1 && s.starts_with('0') {
        s = &s[1..];
    }

    if s.is_empty() {
        return Err(io::Error::new(io::ErrorKind::InvalidInput, "empty octal string"));
    }

    let mut val: u16 = 0;
    for &c in s.as_bytes() {
        let d = oct_val(c).ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "invalid octal digit"))?;
        val = val
            .checked_mul(8)
            .and_then(|v| v.checked_add(d as u16))
            .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "octal value out of u16 range"))?;
    }

    Ok(val)
}

fn oct_val(c: u8) -> Option<u8> {
    match c {
        b'0'..=b'7' => Some(c - b'0'),
        _ => None,
    }
}