slen 0.1.1

A library for encoding and decoding loadouts from the Splatoon series.
Documentation
extern crate array_init;
extern crate substring;

pub mod splat1;
pub use splat1::S1Loadout;

pub mod splat2;
pub use splat2::S2Loadout;

/// A Splatoon-series loadout.
///
/// Loadouts can be parsed using their [`std::str::FromStr`] implementation,
/// with a prefix of `sx:` (where `x` is the series entry) to signal what kind
/// of loadout to parse.
#[derive(Debug, PartialEq, Eq)]
pub enum Loadout {
    Splat1(S1Loadout),
    Splat2(S2Loadout),
}

impl std::str::FromStr for Loadout {
    type Err = ParseFailure;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Some((prefix, code)) = s.split_once(':') {
            match prefix {
                "s1" => Ok(Self::Splat1(code.parse()?)),
                "s2" => Ok(Self::Splat2(code.parse()?)),
                _ => Err(ParseFailure::Prefix),
            }
        } else {
            Err(ParseFailure::Value)
        }
    }
}

impl std::fmt::Display for Loadout {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Loadout::Splat1(s) => write!(f, "s1:{}", s),
            Loadout::Splat2(s) => write!(f, "s2:{}", s),
        }
    }
}

#[derive(Debug)]
pub enum ParseFailure {
    Length,
    Value,
    Prefix,
}

fn hexstr_to_bin(s: &str) -> Option<String> {
    let mut ret = String::new();
    for c in s.chars() {
        if let Some(c) = hexchar_to_bin(&c) {
            ret.push_str(c);
        } else {
            return None;
        }
    }
    Some(ret)
}

#[inline]
fn hexchar_to_bin(c: &char) -> Option<&str> {
    Some(match c {
        '0' => "0000",
        '1' => "0001",
        '2' => "0010",
        '3' => "0011",
        '4' => "0100",
        '5' => "0101",
        '6' => "0110",
        '7' => "0111",
        '8' => "1000",
        '9' => "1001",
        'a' => "1010",
        'b' => "1011",
        'c' => "1100",
        'd' => "1101",
        'e' => "1110",
        'f' => "1111",
        'A' => "1010",
        'B' => "1011",
        'C' => "1100",
        'D' => "1101",
        'E' => "1110",
        _ => return None,
    })
}