use super::definitions::load_definition_map;
use super::definitions::DefinitionHandler;
use super::definitions::FieldHeader;
use super::definitions::CODE_MAX_VALUE;
use super::definitions::CODE_MIN_VALUE;
use crate::core::binarycodec::exceptions::XRPLBinaryCodecException;
use crate::core::exceptions::XRPLCoreResult;
use alloc::vec;
use alloc::vec::Vec;
pub const MAX_SINGLE_BYTE_LENGTH: usize = 192;
pub const MAX_DOUBLE_BYTE_LENGTH: usize = 12481;
pub const MAX_SECOND_BYTE_VALUE: usize = 240;
pub const MAX_DOUBLE_BYTE_VALUE: usize = 65536;
pub const MAX_LENGTH_VALUE: usize = 918744;
pub const MAX_BYTE_VALUE: usize = 256;
fn _encode_field_id(field_header: &FieldHeader) -> XRPLCoreResult<Vec<u8>> {
let type_code = field_header.type_code;
let field_code = field_header.field_code;
let range = CODE_MIN_VALUE..CODE_MAX_VALUE;
if !range.contains(&field_code) {
Err(XRPLBinaryCodecException::UnexpectedFieldCodeRange {
min: CODE_MIN_VALUE as usize,
max: CODE_MAX_VALUE as usize,
}
.into())
} else if !range.contains(&type_code) {
Err(XRPLBinaryCodecException::UnexpectedTypeCodeRange {
min: CODE_MIN_VALUE as usize,
max: CODE_MAX_VALUE as usize,
}
.into())
} else if type_code < 16 && field_code < 16 {
let combined_code = (type_code << 4) | field_code;
Ok([combined_code as u8].to_vec())
} else if type_code >= 16 && field_code < 16 {
let mut result = vec![];
let byte1 = [field_code as u8];
let byte2 = [type_code as u8];
result.extend_from_slice(&byte1);
result.extend_from_slice(&byte2);
Ok(result)
} else if type_code < 16 && field_code >= 16 {
let mut result = vec![];
let byte1 = [(type_code << 4) as u8];
let byte2 = [field_code as u8];
result.extend_from_slice(&byte1);
result.extend_from_slice(&byte2);
Ok(result)
} else {
let mut result = vec![];
let byte2 = [type_code as u8];
let byte3 = [field_code as u8];
result.extend_from_slice(&[0]);
result.extend_from_slice(&byte2);
result.extend_from_slice(&byte3);
Ok(result)
}
}
fn _decode_field_id(field_id: &str) -> XRPLCoreResult<FieldHeader> {
let bytes = hex::decode(field_id)?;
match bytes.len() {
1 => {
let type_code = (bytes[0] >> 4) as i16;
let field_code = (bytes[0] & 0x0F) as i16;
Ok(FieldHeader {
type_code,
field_code,
})
}
2 => {
let first_byte = bytes[0];
let second_byte = bytes[1];
let first_byte_high_bits = first_byte >> 4;
let first_byte_low_bits = first_byte & 0x0F;
if first_byte_high_bits == 0 {
let type_code = second_byte as i16;
let field_code = first_byte_low_bits as i16;
Ok(FieldHeader {
type_code,
field_code,
})
} else {
let type_code = first_byte_high_bits as i16;
let field_code = second_byte as i16;
Ok(FieldHeader {
type_code,
field_code,
})
}
}
3 => {
let type_code = bytes[1] as i16;
let field_code = bytes[2] as i16;
Ok(FieldHeader {
type_code,
field_code,
})
}
_ => Err(XRPLBinaryCodecException::UnexpectedFieldIdByteRange { min: 1, max: 3 }.into()),
}
}
pub fn encode_field_name(field_name: &str) -> XRPLCoreResult<Vec<u8>> {
let definitions = load_definition_map();
let field_header = definitions.get_field_header_from_name(field_name);
if let Some(header) = field_header {
_encode_field_id(&header)
} else {
Err(XRPLBinaryCodecException::UnknownFieldName.into())
}
}
pub fn decode_field_name(field_id: &str) -> XRPLCoreResult<&str> {
let definitions = load_definition_map();
let field_header = _decode_field_id(field_id)?;
let field_name = definitions.get_field_name_from_header(&field_header);
if let Some(name) = field_name {
Ok(name)
} else {
Err(XRPLBinaryCodecException::UnknownFieldName.into())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::core::binarycodec::test_cases::load_field_tests;
#[test]
fn test_encode_field_name() {
for test in load_field_tests() {
let result = hex::encode_upper(encode_field_name(&test.name).expect(""));
assert_eq!(test.expected_hex, result)
}
}
#[test]
fn test_decode_field_name() {
for test in load_field_tests() {
assert_eq!(
decode_field_name(&test.expected_hex),
Ok(test.name.as_ref())
)
}
}
}