use crate::{derivation::attached_signature_code::num_to_b64, error::Error};
use serde::{Deserialize, Serialize};
use std::{convert::TryFrom, fmt::Display};
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub enum PayloadType {
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
#[serde(rename = "0A")]
OA,
#[serde(rename = "0B")]
OB,
#[serde(rename = "0C")]
OC,
#[serde(rename = "0D")]
OD,
#[serde(rename = "0E")]
OE,
#[serde(rename = "0F")]
OF,
#[serde(rename = "0G")]
OG,
#[serde(rename = "0H")]
OH,
#[serde(rename = "1AAA")]
IAAA,
#[serde(rename = "1AAB")]
IAAB,
#[serde(rename = "1AAC")]
IAAC,
#[serde(rename = "1AAD")]
IAAD,
#[serde(rename = "1AAE")]
IAAE,
#[serde(rename = "1AAF")]
IAAF,
#[serde(rename = "1AAG")]
IAAG,
#[serde(rename = "-A")]
MA,
#[serde(rename = "-B")]
MB,
#[serde(rename = "-C")]
MC,
#[serde(rename = "-D")]
MD,
#[serde(rename = "-E")]
ME,
#[serde(rename = "-F")]
MF,
#[serde(rename = "-G")]
MG,
#[serde(rename = "-H")]
MH,
#[serde(rename = "-U")]
MU,
#[serde(rename = "-V")]
MV,
#[serde(rename = "-W")]
MW,
#[serde(rename = "-X")]
MX,
#[serde(rename = "-Y")]
MY,
#[serde(rename = "-Z")]
MZ,
}
impl PayloadType {
pub(crate) fn size(&self) -> usize {
match self {
Self::A
| Self::B
| Self::C
| Self::D
| Self::E
| Self::F
| Self::G
| Self::H
| Self::I
| Self::J => 44,
Self::K | Self::L => 76,
Self::M => 4,
Self::OA => 24,
Self::OB | Self::OC | Self::OD | Self::OE | Self::OF | Self::OG => 88,
Self::OH | Self::IAAF => 8,
Self::IAAA | Self::IAAB => 48,
Self::IAAC | Self::IAAD => 80,
Self::IAAE => 156,
Self::IAAG => 36,
Self::MA | Self::MB => 88,
_ => 0, }
}
pub(crate) fn master_code_size(&self, qb2: bool) -> usize {
match self {
Self::A
| Self::B
| Self::C
| Self::D
| Self::E
| Self::F
| Self::G
| Self::H
| Self::I
| Self::J
| Self::K
| Self::L
| Self::M => 1,
Self::OA | Self::OB | Self::OC | Self::OD | Self::OE | Self::OF | Self::OH => 2,
Self::MA
| Self::MB
| Self::MC
| Self::MD
| Self::ME
| Self::MF
| Self::MG
| Self::MU
| Self::MV
| Self::MW
| Self::MX
| Self::MY
| Self::MZ => {
if qb2 {
3
} else {
4
}
}
_ => 0,
}
}
pub(crate) fn index_length(&self) -> usize {
match self {
Self::A
| Self::B
| Self::C
| Self::D
| Self::E
| Self::F
| Self::G
| Self::H
| Self::I
| Self::J
| Self::K
| Self::L
| Self::M => 0,
Self::OA | Self::OB | Self::OC | Self::OD | Self::OE | Self::OF | Self::OH => 0,
Self::MA
| Self::MB
| Self::MC
| Self::MD
| Self::ME
| Self::MF
| Self::MG
| Self::MU
| Self::MV
| Self::MW
| Self::MX
| Self::MY
| Self::MZ => 2,
_ => todo!(),
}
}
pub fn adjust_with_num(&self, sn: u16) -> String {
let expected_length = self.index_length();
if expected_length > 0 {
let i = num_to_b64(sn);
if i.len() < expected_length {
let missing_part = "A".repeat(expected_length - i.len());
[self.to_string(), missing_part, i].join("")
} else {
[self.to_string(), i].join("")
}
} else {
self.to_string()
}
}
}
impl TryFrom<&str> for PayloadType {
type Error = Error;
fn try_from(data: &str) -> Result<Self, Error> {
match data {
"A" => Ok(Self::A),
"B" => Ok(Self::B),
"C" => Ok(Self::C),
"D" => Ok(Self::D),
"E" => Ok(Self::E),
"F" => Ok(Self::F),
"G" => Ok(Self::G),
"H" => Ok(Self::H),
"I" => Ok(Self::I),
"J" => Ok(Self::J),
"K" => Ok(Self::K),
"L" => Ok(Self::L),
"M" => Ok(Self::M),
"0A" => Ok(Self::OA),
"0B" => Ok(Self::OB),
"0C" => Ok(Self::OC),
"0D" => Ok(Self::OD),
"0E" => Ok(Self::OE),
"0F" => Ok(Self::OF),
"0G" => Ok(Self::OG),
"0H" => Ok(Self::OH),
"1AAA" => Ok(Self::IAAA),
"1AAB" => Ok(Self::IAAB),
"1AAC" => Ok(Self::IAAC),
"1AAD" => Ok(Self::IAAD),
"1AAE" => Ok(Self::IAAE),
"1AAF" => Ok(Self::IAAF),
"1AAG" => Ok(Self::IAAG),
"-A" => Ok(Self::MA),
"-B" => Ok(Self::MB),
"-C" => Ok(Self::MC),
"-D" => Ok(Self::MD),
"-E" => Ok(Self::ME),
"-F" => Ok(Self::MF),
"-G" => Ok(Self::MG),
"-H" => Ok(Self::MH),
"-U" => Ok(Self::MU),
"-V" => Ok(Self::MV),
"-W" => Ok(Self::MW),
"-X" => Ok(Self::MX),
"-Y" => Ok(Self::MY),
"-Z" => Ok(Self::MZ),
_ => Err(Error::ImproperPrefixType),
}
}
}
impl Display for PayloadType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::A => f.write_str("A"),
Self::B => f.write_str("B"),
Self::C => f.write_str("C"),
Self::D => f.write_str("D"),
Self::E => f.write_str("D"),
Self::F => f.write_str("F"),
Self::G => f.write_str("G"),
Self::H => f.write_str("H"),
Self::I => f.write_str("I"),
Self::J => f.write_str("J"),
Self::K => f.write_str("K"),
Self::L => f.write_str("L"),
Self::M => f.write_str("M"),
Self::OA => f.write_str("0A"),
Self::OB => f.write_str("0B"),
Self::OC => f.write_str("0C"),
Self::OD => f.write_str("0D"),
Self::OE => f.write_str("0E"),
Self::OF => f.write_str("0F"),
Self::OG => f.write_str("0G"),
Self::OH => f.write_str("0H"),
Self::IAAA => f.write_str("1AAA"),
Self::IAAB => f.write_str("1AAB"),
Self::IAAC => f.write_str("1AAC"),
Self::IAAD => f.write_str("1AAD"),
Self::IAAE => f.write_str("1AAE"),
Self::IAAF => f.write_str("1AAF"),
Self::IAAG => f.write_str("1AAG"),
Self::MA => f.write_str("-A"),
Self::MB => f.write_str("-B"),
Self::MC => f.write_str("-C"),
Self::MD => f.write_str("-D"),
Self::ME => f.write_str("-E"),
Self::MF => f.write_str("-F"),
Self::MG => f.write_str("-G"),
Self::MH => f.write_str("-H"),
Self::MU => f.write_str("-U"),
Self::MV => f.write_str("-V"),
Self::MW => f.write_str("-W"),
Self::MX => f.write_str("-X"),
Self::MY => f.write_str("-Y"),
Self::MZ => f.write_str("-Z"),
}
}
}
#[test]
fn test_adjust_with_num() {
assert_eq!(PayloadType::MA.adjust_with_num(2), "-AAC");
assert_eq!(PayloadType::MA.adjust_with_num(27), "-AAb");
}