multiversx_sc/hex_call_data/
cd_de.rsuse super::SEPARATOR;
use crate::{
codec::{DecodeError, DecodeErrorHandler, TopDecodeMultiInput},
err_msg,
formatter::hex_util::hex_digits_to_byte,
};
use alloc::{boxed::Box, vec::Vec};
pub struct HexCallDataDeserializer<'a> {
source: &'a [u8],
index: usize,
func_name_output: &'a [u8],
}
impl<'a> HexCallDataDeserializer<'a> {
pub fn new(source: &'a [u8]) -> Self {
let mut de = HexCallDataDeserializer {
source,
index: 0,
func_name_output: &[],
};
if let Some(func_name) = de.next_argument_hex() {
de.func_name_output = func_name
}
de
}
#[inline]
pub fn get_func_name(&self) -> &'a [u8] {
self.func_name_output
}
fn next_argument_hex(&mut self) -> Option<&'a [u8]> {
let initial_index = self.index;
loop {
if !self.has_next() {
return None;
}
if self.index == self.source.len() {
let slice = &self.source[initial_index..self.index];
self.index += 1; return Some(slice);
}
let c = self.source[self.index];
if c == SEPARATOR {
let slice = &self.source[initial_index..self.index];
self.index += 1;
return Some(slice);
}
self.index += 1;
}
}
#[inline]
pub fn has_next(&self) -> bool {
self.index <= self.source.len()
}
pub fn next_argument(&mut self) -> Result<Option<Vec<u8>>, &'static str> {
match self.next_argument_hex() {
None => Ok(None),
Some(arg_hex) => {
if arg_hex.len() % 2 != 0 {
return Err(err_msg::DESERIALIZATION_ODD_DIGITS);
}
let res_len = arg_hex.len() / 2;
let mut res_vec = Vec::with_capacity(res_len);
for i in 0..res_len {
match hex_digits_to_byte(arg_hex[2 * i], arg_hex[2 * i + 1]) {
None => {
return Err(err_msg::DESERIALIZATION_INVALID_BYTE);
},
Some(byte) => {
res_vec.push(byte);
},
}
}
Ok(Some(res_vec))
},
}
}
}
impl TopDecodeMultiInput for HexCallDataDeserializer<'_> {
type ValueInput = Box<[u8]>;
fn has_next(&self) -> bool {
self.has_next()
}
fn next_value_input<H>(&mut self, h: H) -> Result<Self::ValueInput, H::HandledErr>
where
H: DecodeErrorHandler,
{
match self.next_argument() {
Ok(Some(arg_bytes)) => Ok(arg_bytes.into_boxed_slice()),
Ok(None) => Err(h.handle_error(DecodeError::MULTI_TOO_FEW_ARGS)),
Err(sc_err) => Err(h.handle_error(DecodeError::from(sc_err))),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_next_raw_bytes_1() {
let input: &[u8] = b"func@1111@2222";
let mut de = HexCallDataDeserializer::new(input);
assert_eq!(de.get_func_name(), &b"func"[..]);
assert_eq!(de.next_argument_hex(), Some(&b"1111"[..]));
assert_eq!(de.next_argument(), Ok(Some([0x22, 0x22].to_vec())));
assert_eq!(de.next_argument(), Ok(None));
assert_eq!(de.next_argument(), Ok(None));
}
#[test]
fn test_next_raw_bytes_empty() {
let mut de = HexCallDataDeserializer::new(&[]);
assert_eq!(de.get_func_name(), &[][..]);
assert_eq!(de.next_argument(), Ok(None));
}
#[test]
fn test_next_raw_bytes_only_func() {
let input: &[u8] = b"func";
let mut de = HexCallDataDeserializer::new(input);
assert_eq!(de.get_func_name(), &b"func"[..]);
assert_eq!(de.next_argument(), Ok(None));
assert_eq!(de.next_argument(), Ok(None));
}
#[test]
fn test_next_raw_bytes_some_empty() {
let input: &[u8] = b"func@@2222";
let mut de = HexCallDataDeserializer::new(input);
assert_eq!(de.next_argument(), Ok(Some(Vec::new())));
assert_eq!(de.next_argument(), Ok(Some([0x22, 0x22].to_vec())));
assert_eq!(de.next_argument(), Ok(None));
assert_eq!(de.next_argument(), Ok(None));
assert_eq!(de.get_func_name(), &b"func"[..]);
}
#[test]
fn test_next_raw_bytes_ends_empty() {
let input: &[u8] = b"func@";
let mut de = HexCallDataDeserializer::new(input);
assert_eq!(de.get_func_name(), &b"func"[..]);
assert_eq!(de.next_argument(), Ok(Some(Vec::new())));
assert_eq!(de.next_argument(), Ok(None));
assert_eq!(de.next_argument(), Ok(None));
}
#[test]
fn test_next_raw_bytes_many_empty() {
let input: &[u8] = b"func@@2222@@";
let mut de = HexCallDataDeserializer::new(input);
assert_eq!(de.get_func_name(), &b"func"[..]);
assert_eq!(de.next_argument(), Ok(Some(Vec::new())));
assert_eq!(de.next_argument(), Ok(Some([0x22, 0x22].to_vec())));
assert_eq!(de.next_argument(), Ok(Some(Vec::new())));
assert_eq!(de.next_argument(), Ok(Some(Vec::new())));
assert_eq!(de.next_argument(), Ok(None));
assert_eq!(de.next_argument(), Ok(None));
}
#[test]
fn test_next_raw_bytes_all_empty() {
let input: &[u8] = b"@@@";
let mut de = HexCallDataDeserializer::new(input);
assert_eq!(de.get_func_name(), &[][..]);
assert_eq!(de.next_argument(), Ok(Some(Vec::new())));
assert_eq!(de.next_argument(), Ok(Some(Vec::new())));
assert_eq!(de.next_argument(), Ok(Some(Vec::new())));
assert_eq!(de.next_argument(), Ok(None));
assert_eq!(de.next_argument(), Ok(None));
}
#[test]
fn test_next_raw_bytes_all_empty_but_last() {
let input: &[u8] = b"@@@1234";
let mut de = HexCallDataDeserializer::new(input);
assert_eq!(de.get_func_name(), &[][..]);
assert_eq!(de.next_argument(), Ok(Some(Vec::new())));
assert_eq!(de.next_argument(), Ok(Some(Vec::new())));
assert_eq!(de.next_argument(), Ok(Some([0x12, 0x34].to_vec())));
assert_eq!(de.next_argument(), Ok(None));
assert_eq!(de.next_argument(), Ok(None));
}
#[test]
fn test_next_argument_large() {
let input: &[u8] = b"func@0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
let mut de = HexCallDataDeserializer::new(input);
let expected: [u8; 32] = [
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab,
0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67,
0x89, 0xab, 0xcd, 0xef,
];
assert_eq!(de.get_func_name(), &b"func"[..]);
assert!(de.next_argument() == Ok(Some(expected.to_vec())));
assert_eq!(de.next_argument(), Ok(None));
assert_eq!(de.next_argument(), Ok(None));
}
#[test]
fn test_next_vec_odd() {
let input: &[u8] = b"func@123";
let mut de = HexCallDataDeserializer::new(input);
assert_eq!(de.get_func_name(), &b"func"[..]);
assert_eq!(de.next_argument(), Err(err_msg::DESERIALIZATION_ODD_DIGITS));
assert_eq!(de.next_argument(), Ok(None));
assert_eq!(de.next_argument(), Ok(None));
}
}