const MAXGRID4: u16 = 32_400;
#[derive(Debug, Clone, PartialEq)]
pub enum GridField {
Grid(String), Report(i8), RReport(i8), RRR,
RR73,
Seventy3, None,
}
pub fn packgrid(extra: &str) -> u16 {
if extra.is_empty() {
return MAXGRID4 + 1; }
match extra {
"RRR" => return MAXGRID4 + 2,
"RR73" => return MAXGRID4 + 3,
"73" => return MAXGRID4 + 4,
_ => {}
}
let bytes = extra.as_bytes();
if bytes.len() == 4
&& bytes[0] >= b'A'
&& bytes[0] <= b'R'
&& bytes[1] >= b'A'
&& bytes[1] <= b'R'
&& bytes[2].is_ascii_digit()
&& bytes[3].is_ascii_digit()
{
let igrid4 = (bytes[0] - b'A') as u16 * 18 * 10 * 10
+ (bytes[1] - b'A') as u16 * 10 * 10
+ (bytes[2] - b'0') as u16 * 10
+ (bytes[3] - b'0') as u16;
return igrid4;
}
if bytes[0] == b'R' && bytes.len() >= 2 {
let dd = dd_to_int(&extra[1..]);
let irpt = (35i32 + dd as i32) as u16;
(MAXGRID4 + irpt) | 0x8000 } else {
let dd = dd_to_int(extra);
let irpt = (35i32 + dd as i32) as u16;
MAXGRID4 + irpt }
}
fn dd_to_int(s: &str) -> i8 {
let bytes = s.as_bytes();
if bytes.is_empty() {
return 0;
}
let (neg, start) = match bytes[0] {
b'-' => (true, 1),
b'+' => (false, 1),
_ => (false, 0),
};
let mut val: i8 = 0;
for &b in &bytes[start..] {
if b.is_ascii_digit() {
val = val.wrapping_mul(10).wrapping_add((b - b'0') as i8);
} else {
break;
}
}
if neg { -val } else { val }
}
pub fn unpackgrid(igrid4: u16, ir: bool) -> GridField {
if igrid4 <= MAXGRID4 {
let mut n = igrid4;
let d3 = (n % 10) as u8;
n /= 10;
let d2 = (n % 10) as u8;
n /= 10;
let c1 = (n % 18) as u8;
n /= 18;
let c0 = (n % 18) as u8;
let grid = format!(
"{}{}{}{}",
(b'A' + c0) as char,
(b'A' + c1) as char,
(b'0' + d2) as char,
(b'0' + d3) as char,
);
if ir {
return GridField::Grid(format!("R {}", grid));
}
return GridField::Grid(grid);
}
let irpt = (igrid4 - MAXGRID4) as i32;
match irpt {
1 => GridField::None,
2 => GridField::RRR,
3 => GridField::RR73,
4 => GridField::Seventy3,
_ => {
let dd = (irpt - 35) as i8;
if ir {
GridField::RReport(dd)
} else {
GridField::Report(dd)
}
}
}
}
pub fn gridfield_to_str(gf: &GridField) -> String {
match gf {
GridField::Grid(s) => s.clone(),
GridField::Report(n) => format!("{:+03}", n),
GridField::RReport(n) => format!("R{:+03}", n),
GridField::RRR => "RRR".to_string(),
GridField::RR73 => "RR73".to_string(),
GridField::Seventy3 => "73".to_string(),
GridField::None => String::new(),
}
}
pub fn gridfield_to_pack(gf: &GridField) -> (u16, bool) {
let raw = match gf {
GridField::Grid(s) => packgrid(s),
GridField::Report(n) => packgrid(&format!("{:+03}", n)),
GridField::RReport(n) => packgrid(&format!("R{:+03}", n)),
GridField::RRR => packgrid("RRR"),
GridField::RR73 => packgrid("RR73"),
GridField::Seventy3 => packgrid("73"),
GridField::None => packgrid(""),
};
let ir = (raw & 0x8000) != 0;
let igrid4 = raw & 0x7FFF;
(igrid4, ir)
}