use clap::{Args, Parser, Subcommand, ValueEnum};
use deku::DekuError;
use lib::{
app::command::Command,
file::{File, FileId},
link::{BackgroundFrame, ForegroundFrame},
};
#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
#[clap(subcommand)]
command: Commands,
}
#[derive(Debug, Subcommand)]
enum Commands {
Parse(ParseArgs),
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
enum ParseType {
#[clap(alias = "fg")]
Foreground,
#[clap(alias = "bg")]
Background,
#[clap(alias = "a")]
Alp,
#[clap(alias = "e")]
Serial,
#[clap(alias = "s")]
Systemfile,
}
#[derive(Debug, Args)]
struct ParseArgs {
#[arg(value_enum, short='t', long="type")]
parse_type: Option<ParseType>,
#[arg(short='f')]
file_id: Option<u8>,
#[arg()]
hex: String,
}
fn remove_whitespace(s: &str) -> String {
s.chars().filter(|c| !c.is_whitespace()).collect()
}
fn parse_foreground_frame(input: &[u8]) -> Result<(), DekuError> {
let frame = ForegroundFrame::try_from(input)?;
println!("{:?}", frame);
Ok(())
}
fn parse_background_frame(input: &[u8]) -> Result<(), DekuError> {
let frame = BackgroundFrame::try_from(input)?;
println!("{:?}", frame);
Ok(())
}
fn parse_alp_command(input: &[u8]) -> Result<(), DekuError> {
let command = Command::try_from(input)?;
println!("{}", command);
Ok(())
}
fn parse_serial(_input: &[u8]) -> Result<(), DekuError> {
Err(DekuError::Assertion("Not implemented".to_string()))
}
fn parse_file(input: &[u8], file_id: FileId) -> Result<(), DekuError> {
let file = File::from_bytes((input, 0), file_id, 0)?;
println!("{:?}", file);
Ok(())
}
fn parse_any_file(input: &[u8]) -> Result<(), DekuError> {
for file_id_raw in 0..=0x2Eu8 {
let file_id: FileId = file_id_raw.try_into()?;
if parse_file(input, file_id).is_ok() {
return Ok(());
}
}
Ok(())
}
fn parse_any(input: &[u8]) -> Result<(), DekuError> {
if parse_foreground_frame(input).is_ok() {
return Ok(())
}
if parse_background_frame(input).is_ok() {
return Ok(())
}
if parse_alp_command(input).is_ok() {
return Ok(())
}
if parse_serial(input).is_ok() {
return Ok(())
}
if parse_any_file(input).is_ok() {
return Ok(())
}
Err(DekuError::Parse("Could not parse input".to_string()))
}
fn parse(args: ParseArgs) {
let input_vec = hex::decode(remove_whitespace(&args.hex)).expect("Could not parse input hex");
let input = input_vec.as_slice();
match args.parse_type {
Some(ParseType::Foreground) => {
parse_foreground_frame(input).expect("Could not foreground frame")
}
Some(ParseType::Background) => {
parse_background_frame(input).expect("Could not foreground frame")
}
Some(ParseType::Alp) => parse_alp_command(input).expect("Could not parse command"),
Some(ParseType::Serial) => parse_serial(input).expect("Could not parse serial"),
Some(ParseType::Systemfile) => {
if let Some(file_id_raw) = args.file_id {
let file_id: FileId = file_id_raw.try_into().expect("File id invalid");
parse_file(input, file_id).expect("Could not parse file")
} else {
parse_any_file(input).expect("Could not parse file")
}
},
None => parse_any(input).expect("Could not parse input")
}
}
pub fn main() {
let cli = Cli::parse();
match cli.command {
Commands::Parse(args) => parse(args),
}
}