Fully implemented everything in query_utils.ts, ran cargo fmt

This commit is contained in:
G2-Games 2023-09-25 01:33:57 -05:00
parent e39e95d555
commit 54b0977b44
6 changed files with 415 additions and 142 deletions

View file

@ -6,7 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bcd-numbers = "1.0.11"
encoding_rs = "0.8.33"
nofmt = "1.0.0"
once_cell = "1.18.0"

View file

@ -36,6 +36,11 @@ fn main() {
println!("Track Count: {:?}", player_controller.track_count());
println!("Disc Title: {:?}", player_controller.disc_title(false));
println!("TEST CASE: {:?}", player_controller.operating_status());
let _ = player_controller.play();
/*
for i in 0..player_controller.track_count().unwrap() {
println!(
"Track {: >2}: {: >21} | {}",
@ -43,7 +48,7 @@ fn main() {
player_controller.track_title(i as u16, false).unwrap(),
player_controller.track_title(i as u16, true).unwrap()
);
}
}*/
/*
let mut request: [u8; 19] = [0x00, 0x18, 0x06, 0x02, 0x20, 0x18,

View file

@ -1,3 +1,4 @@
use crate::netmd::query_utils::{format_query, scan_query};
use crate::netmd::utils;
use crate::NetMD;
use encoding_rs::*;
@ -383,8 +384,6 @@ impl NetMDInterface {
let result = self.send_query(&mut query, false, false)?;
utils::check_result(result, &[0x18, 0xc5, 0x00, action as u8, 0x00, 0x00, 0x00])?;
Ok(())
}
@ -409,8 +408,6 @@ impl NetMDInterface {
let result = self.send_query(&mut query, false, false)?;
utils::check_result(result, &[0x18, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00])?;
Ok(())
}
@ -420,13 +417,8 @@ impl NetMDInterface {
0xff,
];
let reply = self.send_query(&mut query, false, false)?;
utils::check_result(
reply,
&[
0xff, 0x01, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff,
],
)
Ok(())
}
fn release(&self) -> Result<(), Box<dyn Error>> {
@ -435,13 +427,8 @@ impl NetMDInterface {
0xff,
];
let reply = self.send_query(&mut query, false, false)?;
utils::check_result(
reply,
&[
0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff,
],
)
Ok(())
}
fn status(&self) -> Result<Vec<u8>, Box<dyn Error>> {
@ -471,18 +458,26 @@ impl NetMDInterface {
}
fn full_operating_status(&self) -> Result<(u8, u16), Box<dyn Error>> {
// WARNING: Does not work for all devices. See https://github.com/cybercase/webminidisc/issues/21
self.change_descriptor_state(
&Descriptor::OperatingStatusBlock,
&DescriptorAction::OpenRead,
);
let mut query = vec![
0x18, 0x09, 0x80, 0x01, 0x03, 0x30, 0x88, 0x02, 0x00, 0x30, 0x88, 0x05, 0x00, 0x30,
0x88, 0x06, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let response = self.send_query(&mut query, false, false)?;
let mut query = format_query(
"1809 8001 0330 8802 0030 8805 0030 8806 00 ff00 00000000".to_string(),
vec![],
vec![],
)
.unwrap();
let reply = self.send_query(&mut query, false, false)?;
let operating_status = response[27..].to_vec();
let status_mode = response[20];
let result = scan_query(
reply,
"1809 8001 0330 8802 0030 8805 0030 8806 00 1000 00%?0000 00%b 8806 %x".to_string(),
)?;
let operating_status = result[1].to_vec().unwrap();
let status_mode = result[0].to_i64().unwrap() as u8;
self.change_descriptor_state(&Descriptor::OperatingStatusBlock, &DescriptorAction::Close);
@ -490,49 +485,48 @@ impl NetMDInterface {
return Err("Unparsable operating system".into());
}
let status_bytes = [operating_status[0], operating_status[1]];
let operating_status_number = u16::from_le_bytes(status_bytes);
let operating_status_number =
(operating_status[0] as u16) << 8 | operating_status[1] as u16;
Ok((status_mode, operating_status_number))
}
fn operating_status(&self) -> Result<u16, Box<dyn Error>> {
pub fn operating_status(&self) -> Result<u16, Box<dyn Error>> {
let status = self.full_operating_status()?.1;
Ok(status)
}
fn playback_status_query(&self, p1: [u8; 2], p2: [u8; 2]) -> Result<Vec<u8>, Box<dyn Error>> {
fn playback_status_query(&self, p1: u32, p2: u32) -> Result<Vec<u8>, Box<dyn Error>> {
self.change_descriptor_state(
&Descriptor::OperatingStatusBlock,
&DescriptorAction::OpenRead,
);
let mut query = vec![
0x18, 0x09, 0x80, 0x01, 0x03, 0x30, 0x00, 0x00, 0x00, 0x30, 0x88, 0x05, 0x00, 0x30,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut query = format_query(
"1809 8001 0330 %w 0030 8805 0030 %w 00 ff00 00000000".to_string(),
vec![Some(p1 as i64), Some(p2 as i64)],
vec![],
)
.unwrap();
query[6] = p1[0];
query[7] = p1[1];
query[14] = p2[0];
query[15] = p2[1];
let reply = self.send_query(&mut query, false, false)?;
let response = self.send_query(&mut query, false, false)?;
let playback_status = response[24..].to_vec();
let res = scan_query(
reply,
"1809 8001 0330 %?%? %?%? %?%? %?%? %?%? %? 1000 00%?0000 %x %?".to_string(),
);
self.change_descriptor_state(&Descriptor::OperatingStatusBlock, &DescriptorAction::Close);
Ok(playback_status)
Ok(res.unwrap()[0].to_vec().unwrap())
}
pub fn playback_status1(&self) -> Result<Vec<u8>, Box<dyn Error>> {
self.playback_status_query([0x88, 0x01], [0x88, 0x07])
self.playback_status_query(0x8801, 0x8807)
}
pub fn playback_status2(&self) -> Result<Vec<u8>, Box<dyn Error>> {
self.playback_status_query([0x88, 0x02], [0x88, 0x06])
self.playback_status_query(0x8802, 0x8806)
}
pub fn position(&self) -> Result<[u16; 5], Box<dyn Error>> {
@ -541,10 +535,12 @@ impl NetMDInterface {
&DescriptorAction::OpenRead,
);
let mut query = vec![
0x18, 0x09, 0x80, 0x01, 0x04, 0x30, 0x88, 0x02, 0x00, 0x30, 0x88, 0x05, 0x00, 0x30,
0x00, 0x03, 0x00, 0x30, 0x00, 0x02, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let mut query = format_query(
"1809 8001 0430 8802 0030 8805 0030 0003 0030 0002 00 ff00 00000000".to_string(),
vec![],
vec![],
)
.unwrap();
let reply = match self.send_query(&mut query, false, false) {
Ok(result) => result,
@ -552,19 +548,14 @@ impl NetMDInterface {
Err(e) => return Err(e),
};
let track_number = u16::from_be_bytes([reply[35], reply[36]]);
let hour = utils::byte_from_bcd(reply[37])?;
let minute = utils::byte_from_bcd(reply[38])?;
let second = utils::byte_from_bcd(reply[39])?;
let frame = utils::byte_from_bcd(reply[40])?;
let result = scan_query(reply, "1809 8001 0430 %?%? %?%? %?%? %?%? %?%? %?%? %?%? %? %?00 00%?0000 000b 0002 0007 00 %w %B %B %B %B".to_string())?;
let final_result = [
track_number,
hour as u16,
minute as u16,
second as u16,
frame as u16,
result[0].to_i64().unwrap() as u16,
result[1].to_i64().unwrap() as u16,
result[2].to_i64().unwrap() as u16,
result[3].to_i64().unwrap() as u16,
result[4].to_i64().unwrap() as u16,
];
self.change_descriptor_state(&Descriptor::OperatingStatusBlock, &DescriptorAction::Close);
@ -573,13 +564,15 @@ impl NetMDInterface {
}
pub fn eject_disc(&self) -> Result<(), Box<dyn Error>> {
let mut query = vec![0x18, 0xc1, 0xff, 0x60, 0x00];
let mut query = format_query("18c1 ff 6000".to_string(), vec![], vec![]).unwrap();
let _reply = self.send_query(&mut query, false, false)?;
Ok(())
}
pub fn can_eject_disc(&self) -> Result<bool, Box<dyn Error>> {
let mut query = vec![0x18, 0xc1, 0xff, 0x60, 0x00];
let mut query = format_query("18c1 ff 6000".to_string(), vec![], vec![]).unwrap();
match self.send_query(&mut query, true, false) {
Ok(_) => Ok(true),
Err(error) => Err(error),
@ -587,18 +580,21 @@ impl NetMDInterface {
}
/* Track control */
pub fn go_to_track(&self, track_number: u16) -> Result<u16, Box<dyn Error>> {
let mut query = vec![0x18, 0x50, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0b00, 0b00];
let bytes = track_number.to_le_bytes();
query[8] = bytes[1];
query[9] = bytes[0];
let mut query = format_query(
"1850 ff010000 0000 %w".to_string(),
vec![Some(track_number as i64)],
vec![],
)
.unwrap();
let reply = self.send_query(&mut query, false, false)?;
Ok(u16::from_be_bytes([reply[8], reply[9]]))
let res = scan_query(reply, "1850 00010000 0000 %w".to_string())?;
let value = res[0].to_i64()?;
Ok(value as u16)
}
pub fn go_to_time(
@ -609,34 +605,39 @@ impl NetMDInterface {
second: u8,
frame: u8,
) -> Result<u16, Box<dyn Error>> {
let mut query = vec![
0x18, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0b00, 0b00, 0b00, 0b00, 0b00, 0b00,
];
let bytes = track_number.to_le_bytes();
query[8] = bytes[1];
query[9] = bytes[0];
query[10] = utils::bcd_from_byte(hour)?;
query[11] = utils::bcd_from_byte(minute)?;
query[12] = utils::bcd_from_byte(second)?;
query[13] = utils::bcd_from_byte(frame)?;
let mut query = format_query(
"1850 ff000000 0000 %w %B%B%B%B".to_string(),
vec![
Some(track_number as i64),
Some(hour as i64),
Some(minute as i64),
Some(second as i64),
Some(frame as i64),
],
vec![],
)
.unwrap();
let reply = self.send_query(&mut query, false, false)?;
Ok(u16::from_be_bytes([reply[8], reply[9]]))
let res = scan_query(reply, "1850 00000000 %?%? %w %B%B%B%B".to_string())?;
let value = res[0].to_i64()?;
Ok(value as u16)
}
fn _track_change(&self, direction: Track) -> Result<(), Box<dyn Error>> {
let mut query = vec![0x18, 0x50, 0xff, 0x10, 0x00, 0x00, 0x00, 0x00, 0b00, 0b00];
let mut query = format_query(
"1850 ff10 00000000 %w".to_string(),
vec![Some(direction as i64)],
vec![],
)
.unwrap();
let direction_number = direction as u16;
let direction_bytes = direction_number.to_le_bytes();
let reply = self.send_query(&mut query, false, false)?;
query[8] = direction_bytes[1];
query[9] = direction_bytes[0];
let _ = self.send_query(&mut query, false, false);
scan_query(reply, "1850 0010 00000000 %?%?".to_string())?;
Ok(())
}
@ -655,42 +656,49 @@ impl NetMDInterface {
/* Content access and control */
pub fn erase_disc(&self) -> Result<(), Box<dyn Error>> {
let mut query = vec![0x18, 0x40, 0xff, 0x00, 0x00];
let mut query = format_query("1840 ff 0000".to_string(), vec![], vec![]).unwrap();
let reply = self.send_query(&mut query, false, false)?;
utils::check_result(reply, &[0x18, 0x40, 0x00, 0x00, 0x00])
scan_query(reply, "1840 00 0000".to_string())?;
Ok(())
}
// TODO: Ensure this is returning the correct value, it
// looks like it actually might be a 16 bit integer
pub fn disc_flags(&self) -> Result<u8, Box<dyn Error>> {
self.change_descriptor_state(&Descriptor::RootTD, &DescriptorAction::OpenRead);
let mut query = vec![
0x18, 0x06, 0x01, 0x10, 0x10, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0x0b,
];
let mut query =
format_query("1806 01101000 ff00 0001000b".to_string(), vec![], vec![]).unwrap();
let reply = self.send_query(&mut query, false, false)?;
let flags = reply[12];
let res = scan_query(reply, "1806 01101000 1000 0001000b %b".to_string()).unwrap();
self.change_descriptor_state(&Descriptor::RootTD, &DescriptorAction::Close);
Ok(flags)
Ok(res[0].to_i64().unwrap() as u8)
}
pub fn track_count(&self) -> Result<u8, Box<dyn Error>> {
self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead);
let mut query = vec![
0x18, 0x06, 0x02, 0x10, 0x10, 0x01, 0x30, 0x00, 0x10, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00,
];
let mut query = format_query(
"1806 02101001 3000 1000 ff00 00000000".to_string(),
vec![],
vec![],
)
.unwrap();
let reply = self.send_query(&mut query, false, false)?;
let track_count = reply[24];
let res = scan_query(
reply,
"1806 02101001 %?%? %?%? 1000 00%?0000 0006 0010000200%b".to_string(),
)
.unwrap();
self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::Close);
Ok(track_count)
Ok(res[0].to_i64().unwrap() as u8)
}
fn _disc_title(&self, wchar: bool) -> Result<String, Box<dyn Error>> {
@ -705,28 +713,26 @@ impl NetMDInterface {
let mut chunk = String::new();
while done < total {
let mut query = vec![
0x18, 0x06, 0x02, 0x20, 0x18, 0x01, 0x00, 0b00, 0x30, 0x00, 0x0a, 0x00, 0xff, 0x00,
0b00, 0b00, 0b00, 0b00,
];
query[7] = match wchar {
let wchar_value = match wchar {
true => 1,
false => 0,
};
let remain_bytes = remaining.to_le_bytes();
query[14] = remain_bytes[0];
query[15] = remain_bytes[1];
let done_bytes = done.to_le_bytes();
query[16] = done_bytes[0];
query[17] = done_bytes[1];
let mut query = format_query(
"1806 02201801 00%b 3000 0a00 ff00 %w%w".to_string(),
vec![
wchar_value.into(),
(remaining as i64).into(),
(done as i64).into(),
],
vec![],
)
.unwrap();
let reply = self.send_query(&mut query, false, false)?;
if remaining == 0 {
chunksize = u16::from_le_bytes([reply[13], reply[14]]);
let res = chunksize = u16::from_le_bytes([reply[13], reply[14]]);
total = u16::from_le_bytes([reply[22], reply[23]]);
chunk = SHIFT_JIS.decode(&reply[25..]).0.into();
@ -865,15 +871,18 @@ impl NetMDInterface {
/// Gets the title of a track at a specified index
pub fn track_title(&self, track: u16, wchar: bool) -> Result<String, Box<dyn Error>> {
let mut query = vec![
0x18, 0x06, 0x02, 0x20, 0x18, 0b00, 0b00, 0b00, 0x30, 0x00, 0x0a, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00,
];
query[5] = match wchar {
let wchar_value = match wchar {
true => 3,
false => 2,
};
let mut query = format_query(
"1806 022018%b %w 3000 0a00 ff00 00000000".to_string(),
vec![wchar_value.into(), (track as i64).into()],
vec![],
)
.unwrap();
let descriptor_type = match wchar {
true => Descriptor::AudioUTOC4TD,
false => Descriptor::AudioUTOC1TD,
@ -881,17 +890,19 @@ impl NetMDInterface {
self.change_descriptor_state(&descriptor_type, &DescriptorAction::OpenRead);
let track_bytes = track.to_le_bytes();
query[6] = track_bytes[1];
query[7] = track_bytes[0];
let reply = self.send_query(&mut query, false, false)?;
let array_len = u16::from_le_bytes([reply[24], reply[23]]);
let title_array = &reply[25..array_len as usize + 25];
let res = scan_query(
reply,
"1806 022018%? %?%? %?%? %?%? 1000 00%?0000 00%?000a %x".to_string(),
)
.unwrap();
self.change_descriptor_state(&descriptor_type, &DescriptorAction::Close);
Ok(SHIFT_JIS.decode(title_array).0.to_string())
Ok(encoding_rs::SHIFT_JIS
.decode(&res[0].to_vec().unwrap())
.0
.into())
}
}

View file

@ -1,4 +1,4 @@
pub mod base;
pub mod interface;
pub mod utils;
pub mod query_utils;
pub mod utils;

View file

@ -1,6 +1,7 @@
use crate::netmd::utils;
use once_cell::sync::Lazy;
use std::collections::hash_map::HashMap;
use std::error::Error;
use once_cell::sync::Lazy;
// prettier-ignore
const FORMAT_TYPE_LEN_DICT: Lazy<HashMap<char, i32>> = Lazy::new(|| {
@ -25,16 +26,237 @@ const FORMAT_TYPE_LEN_DICT: Lazy<HashMap<char, i32>> = Lazy::new(|| {
const DEBUG: bool = false;
/// Formats a query using a standard input to send to the player
pub fn format_query(format: String, args: Vec<i32>) -> Result<Vec<u8>, Box<dyn Error>> {
pub fn format_query(
format: String,
args: Vec<Option<i64>>,
array_args: Vec<Vec<u8>>,
) -> Result<Vec<u8>, Box<dyn Error>> {
if DEBUG {
println!("SENT>>> F: {}", format);
}
let mut result: Vec<u8> = Vec::new();
let mut half: Option<char> = None;
let mut arg_stack = args.into_iter();
let mut array_arg_stack = array_args.into_iter();
let mut endianness_override: Option<char> = None;
for character in format.into_bytes().into_iter() {
println!("{}", character);
let mut escaped = false;
for character in format.chars() {
if escaped {
if endianness_override.is_none() && ['<', '>'].contains(&character) {
endianness_override = Some(character);
continue;
}
escaped = false;
let value = arg_stack.next().unwrap().unwrap();
match character {
character if FORMAT_TYPE_LEN_DICT.contains_key(&character) => {
match character {
'b' => result.push(value as u8),
'w' => {
let mut value_bytes = (value as i16).to_be_bytes().to_vec();
result.append(&mut value_bytes)
}
'd' => {
let mut value_bytes = (value as i32).to_be_bytes().to_vec();
result.append(&mut value_bytes)
}
'q' => {
let mut value_bytes = value.to_be_bytes().to_vec();
result.append(&mut value_bytes)
}
_ => (),
};
endianness_override = None;
}
character if character == 'x' || character == 's' || character == 'z' => {
let mut array_value = array_arg_stack.next().unwrap();
let mut array_length = array_value.len();
if character == 's' {
array_length += 1;
}
if character != 'z' {
result.push(((array_length >> 8) & 0xFF) as u8)
}
result.push((array_length & 0xFF) as u8);
result.append(&mut array_value);
if character == 's' {
result.push(0);
}
}
character if character == '*' => {
let mut array_value = array_arg_stack.next().unwrap();
result.append(&mut array_value);
}
character if character == 'B' || character == 'W' => {
let converted = utils::int_to_bcd(value as i32);
if character == 'W' {
result.push(((converted >> 8) & 0xFF) as u8);
}
result.push((converted & 0xFF) as u8);
}
_ => return Err(format!("Unrecognized format char {}", character).into()),
}
continue;
}
if character == '%' {
escaped = true;
continue;
}
if character == ' ' {
continue;
}
if half.is_none() {
half = Some(character);
} else {
result.push(
u8::from_str_radix(&String::from_iter([half.unwrap(), character]), 16).unwrap(),
);
half = None;
}
}
Ok(Vec::new())
Ok(result)
}
pub enum QueryResults {
Number(i64),
Array(Vec<u8>),
}
impl QueryResults {
pub fn to_vec(&self) -> Result<Vec<u8>, Box<dyn Error>> {
match self {
QueryResults::Array(a) => Ok(a.to_vec()),
_ => Err("Result was a number".into()),
}
}
pub fn to_i64(&self) -> Result<i64, Box<dyn Error>> {
match self {
QueryResults::Number(a) => Ok(*a),
_ => Err("Result was a number".into()),
}
}
}
/// Scans a result using a standard input to recieve from the player
pub fn scan_query(
query_result: Vec<u8>,
format: String,
) -> Result<Vec<QueryResults>, Box<dyn Error>> {
let mut result: Vec<QueryResults> = Vec::new();
let initial_length = query_result.len();
let mut input_stack = query_result.into_iter();
let mut half: Option<char> = None;
let mut endianness_override: Option<char> = None;
let mut escaped = false;
// Remove an unknown byte at the beginning
// TODO: Find out what this is
input_stack.next();
for character in format.chars() {
println!("{}", character);
if escaped {
if endianness_override.is_none() && ['<', '>'].contains(&character) {
endianness_override = Some(character);
continue;
}
escaped = false;
if character == '?' {
input_stack.next();
continue;
}
match character {
character if FORMAT_TYPE_LEN_DICT.contains_key(&character) => {
println!("Character: {}", character);
match character {
'b' => {
let new_value =
u8::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
result.push(QueryResults::Number(new_value as i64));
}
'w' => {
let new_value =
i16::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
result.push(QueryResults::Number(new_value as i64));
}
'd' => {
let new_value =
i32::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
result.push(QueryResults::Number(new_value as i64));
}
'q' => {
let new_value =
i64::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
result.push(QueryResults::Number(new_value));
}
_ => unreachable!(),
};
endianness_override = None;
}
character if character == 'x' || character == 's' || character == 'z' => {
let length = match character {
'z' => input_stack.next().unwrap() as u16,
_ => u16::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap()),
};
let mut result_buffer: Vec<u8> = Vec::new();
for _ in 0..length {
result_buffer.push(input_stack.next().unwrap());
}
result.push(QueryResults::Array(result_buffer))
}
character if character == '*' || character == '#' => {
let mut result_buffer: Vec<i64> = Vec::new();
let temp_stack = input_stack.clone();
for entry in temp_stack.take(initial_length as usize) {
result_buffer.push(entry as i64);
}
}
character if character == 'B' => {
let v = input_stack.next().unwrap();
result.push(QueryResults::Number(utils::bcd_to_int(v as i32) as i64));
}
character if character == 'W' => {
let v = (input_stack.next().unwrap() as i32) << 8
| input_stack.next().unwrap() as i32;
result.push(QueryResults::Number(utils::bcd_to_int(v) as i64));
}
_ => return Err(format!("Unrecognized format char {}", character).into()),
}
continue;
}
if character == '%' {
assert_eq!(half, None);
escaped = true;
continue;
}
if character == ' ' {
continue;
}
if half.is_none() {
half = Some(character);
} else {
let input_value = input_stack.next().unwrap();
let format_value =
u8::from_str_radix(&String::from_iter([half.unwrap(), character]), 16).unwrap();
if format_value != input_value {
let i = initial_length - input_stack.len() - 1;
return Err(format!("Format and input mismatch at {i}: expected {format_value:#0x}, got {input_value:#0x} (format {format})").into());
}
half = None;
}
}
assert_eq!(input_stack.len(), 0);
Ok(result)
}

View file

@ -1,14 +1,35 @@
use std::collections::hash_map::HashMap;
use std::error::Error;
pub fn check_result(result: Vec<u8>, expected: &[u8]) -> Result<(), Box<dyn Error>> {
match result.as_slice().eq(expected) {
true => Ok(()),
false => Err("Response was not as expected!".into()),
pub fn bcd_to_int(bcd: i32) -> i32 {
let mut original = bcd;
let mut value = 0;
let mut nibble = 0;
while original != 0 {
let nibble_value = original & 0xf;
original = original >> 4;
value += nibble_value * i32::pow(10, nibble);
nibble += 1;
}
value
}
pub fn byte_from_bcd(byte: u8) -> Result<u8, Box<dyn Error>> {
pub fn int_to_bcd(mut value: i32) -> i32 {
let mut bcd = 0;
let mut shift = 0;
while value > 0 {
let digit = value % 10;
bcd |= digit << shift;
shift += 4;
value /= 10;
}
bcd
}
pub fn int_from_bcd(byte: u8) -> Result<u8, Box<dyn Error>> {
let upper = (byte & 0xF0) >> 4;
let lower = byte & 0x0F;
@ -23,7 +44,7 @@ pub fn byte_from_bcd(byte: u8) -> Result<u8, Box<dyn Error>> {
Ok(upper * 10 + lower)
}
pub fn bcd_from_byte(byte: u8) -> Result<u8, Box<dyn Error>> {
pub fn bcd_from_int(byte: u8) -> Result<u8, Box<dyn Error>> {
let mut new_byte: u8 = 0;
let upper = (byte / 10) << 4;
@ -57,3 +78,18 @@ pub fn half_width_to_full_width_range(range: &String) -> String {
.map(|char| mappings.get(&char).unwrap())
.collect()
}
pub fn get_bytes<const S: usize>(
iterator: &mut std::vec::IntoIter<u8>,
) -> Result<[u8; S], Box<dyn std::error::Error>> {
let mut bytes = [0; S];
for i in 0..S {
bytes[i] = match iterator.next() {
Some(byte) => byte,
None => return Err("Could not retrieve byte from file".into()),
};
}
Ok(bytes)
}