///|
pub fn base35_digit_to_int(code : UInt16) -> Int? {
  let c = code.to_int()
  match c {
    '0'..='9' => Some(c - '0')
    'A'..='N' => Some(c - 'A' + 10)
    'P'..='Z' => Some(c - 'P' + 24)
    _ => None
  }
}

///|
test "base35 digit to int accepts only valid boundary characters" {
  assert_true(base35_digit_to_int('0') == Some(0))
  assert_true(base35_digit_to_int('9') == Some(9))
  assert_true(base35_digit_to_int('A') == Some(10))
  assert_true(base35_digit_to_int('N') == Some(23))
  assert_true(base35_digit_to_int('O') == None)
  assert_true(base35_digit_to_int('P') == Some(24))
  assert_true(base35_digit_to_int('Z') == Some(34))
  assert_true(base35_digit_to_int('/') == None)
  assert_true(base35_digit_to_int(':') == None)
  assert_true(base35_digit_to_int('@') == None)
  assert_true(base35_digit_to_int('[') == None)
}

///|
pub fn base35_digit_from_int(value : Int) -> Char? {
  match value {
    0..=9 => Some((value + '0').unsafe_to_char())
    10..=23 => Some((value - 10 + 'A').unsafe_to_char())
    24..=34 => Some((value - 24 + 'P').unsafe_to_char())
    _ => None
  }
}

///|
test "base35 digit from int accepts exactly 0 through 34" {
  assert_true(base35_digit_from_int(-1) == None)
  assert_true(base35_digit_from_int(0) == Some('0'))
  assert_true(base35_digit_from_int(9) == Some('9'))
  assert_true(base35_digit_from_int(10) == Some('A'))
  assert_true(base35_digit_from_int(23) == Some('N'))
  assert_true(base35_digit_from_int(24) == Some('P'))
  assert_true(base35_digit_from_int(34) == Some('Z'))
  assert_true(base35_digit_from_int(35) == None)
}