use external_memory_tools::{AddressableBuffer, BufferError, ExternalMemory};
use parity_scale_codec::{Compact, Decode, HasCompact};
use crate::error::ParserError;
#[derive(Debug)]
pub struct FoundCompact<T: HasCompact> {
pub compact: T,
pub start_next_unit: usize,
}
pub const MAX_COMPACT_LEN: usize = 17;
pub fn find_compact<T, B, E>(
data: &B,
ext_memory: &mut E,
position: usize,
) -> Result<FoundCompact<T>, ParserError<E>>
where
B: AddressableBuffer<E>,
E: ExternalMemory,
T: HasCompact,
Compact<T>: Decode,
{
if data.total_len() < position {
return Err(ParserError::Buffer(BufferError::OutOfRange {
position,
total_length: data.total_len(),
}));
}
let mut out = None;
for i in 0..(data.total_len() - position) {
if i > MAX_COMPACT_LEN {
break;
}
let hippo = data.read_slice(ext_memory, position, i + 1)?;
let unhippo = <Compact<T>>::decode(&mut hippo.as_ref());
if let Ok(hurray) = unhippo {
let start_next_unit = {
if data.total_len() - position == i {
data.total_len()
} else {
position + i + 1
}
};
out = Some(FoundCompact {
compact: hurray.0,
start_next_unit,
});
break;
}
}
match out {
Some(c) => Ok(c),
None => Err(ParserError::NoCompact { position }),
}
}
pub fn get_compact<T, B, E>(
data: &B,
ext_memory: &mut E,
position: &mut usize,
) -> Result<T, ParserError<E>>
where
B: AddressableBuffer<E>,
E: ExternalMemory,
T: HasCompact,
Compact<T>: Decode,
{
let found_compact = find_compact::<T, B, E>(data, ext_memory, *position)?;
*position = found_compact.start_next_unit;
Ok(found_compact.compact)
}