fn int()

in starlark/src/stdlib/funcs.rs [515:597]


    fn int(ref a: Option<Value>, base: Option<Value>) -> anyhow::Result<i32> {
        if a.is_none() {
            return Ok(0);
        }
        let a = a.unwrap();
        if let Some(s) = a.unpack_str() {
            let base = match base {
                Some(base) => base.to_int()?,
                None => 0,
            };
            if base == 1 || base < 0 || base > 36 {
                return Err(anyhow!(
                    "{} is not a valid base, int() base must be >= 2 and <= 36",
                    base
                ));
            }
            let (sign, s) = {
                match s.chars().next() {
                    Some('+') => (1, s.get(1..).unwrap()),
                    Some('-') => (-1, s.get(1..).unwrap()),
                    _ => (1, s),
                }
            };
            let base = if base == 0 {
                match s.get(0..2) {
                    Some("0b") | Some("0B") => 2,
                    Some("0o") | Some("0O") => 8,
                    Some("0x") | Some("0X") => 16,
                    _ => 10,
                }
            } else {
                base as u32
            };
            let s = match base {
                16 => {
                    if s.starts_with("0x") || s.starts_with("0X") {
                        s.get(2..).unwrap()
                    } else {
                        s
                    }
                }
                8 => {
                    if s.starts_with("0o") || s.starts_with("0O") {
                        s.get(2..).unwrap()
                    } else {
                        s
                    }
                }
                2 => {
                    if s.starts_with("0b") || s.starts_with("0B") {
                        s.get(2..).unwrap()
                    } else {
                        s
                    }
                }
                _ => s,
            };
            match i32::from_str_radix(s, base) {
                Ok(i) => Ok(sign * i),
                Err(x) => Err(anyhow!(
                    "{} is not a valid number in base {}: {}",
                    a.to_repr(),
                    base,
                    x,
                )),
            }
        } else if let Some(base) = base {
            Err(anyhow!(
                "int() cannot convert non-string with explicit base '{}'",
                base.to_repr()
            ))
        } else if let Some(Num::Float(f)) = a.unpack_num() {
            match Num::from(f.trunc()).as_int() {
                Some(i) => Ok(i),
                None => Err(anyhow!(
                    "int() cannot convert float to integer: {}",
                    a.to_repr()
                )),
            }
        } else {
            Ok(a.to_int()?)
        }
    }