use core::num::NonZeroUsize;
use std::convert::TryInto;
pub(crate) mod leb128;
use crate::{ActorId, ChangeHash};
const HASH_SIZE: usize = 32;
#[allow(unused_imports)]
pub(crate) use self::leb128::{leb128_i64, leb128_u32, leb128_u64, nonzero_leb128_u64};
pub(crate) type ParseResult<'a, O, E> = Result<(Input<'a>, O), ParseError<E>>;
#[derive(PartialEq, Clone, Copy)]
pub(crate) struct Input<'a> {
bytes: &'a [u8],
position: usize,
original: &'a [u8],
}
impl std::fmt::Debug for Input<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Input(len: {}, position: {}, original_len: {})",
self.bytes.len(),
self.position,
self.original.len()
)
}
}
impl<'a> Input<'a> {
pub(crate) fn new(bytes: &'a [u8]) -> Self {
Self {
bytes,
position: 0,
original: bytes,
}
}
#[cfg(test)]
pub(in crate::storage::parse) fn with_position(bytes: &'a [u8], position: usize) -> Input<'a> {
let remaining = &bytes[position..];
Self {
bytes: remaining,
position,
original: bytes,
}
}
pub(crate) fn empty() -> Self {
Self {
bytes: &[],
position: 0,
original: &[],
}
}
fn take_1<E>(&self) -> ParseResult<'a, u8, E> {
if let Some(need) = NonZeroUsize::new(1_usize.saturating_sub(self.bytes.len())) {
Err(ParseError::Incomplete(Needed::Size(need)))
} else {
let (result, remaining) = self.bytes.split_at(1);
let new_input = Input {
bytes: remaining,
original: self.original,
position: self.position + 1,
};
Ok((new_input, result[0]))
}
}
fn take_n<E>(&self, n: usize) -> ParseResult<'a, &'a [u8], E> {
if let Some(need) = NonZeroUsize::new(n.saturating_sub(self.bytes.len())) {
Err(ParseError::Incomplete(Needed::Size(need)))
} else {
let (result, remaining) = self.bytes.split_at(n);
let new_input = Input {
bytes: remaining,
original: self.original,
position: self.position + n,
};
Ok((new_input, result))
}
}
fn take_4<E>(&self) -> ParseResult<'a, [u8; 4], E> {
if let Some(need) = NonZeroUsize::new(4_usize.saturating_sub(self.bytes.len())) {
Err(ParseError::Incomplete(Needed::Size(need)))
} else {
let (result, remaining) = self.bytes.split_at(4);
let new_input = Input {
bytes: remaining,
original: self.original,
position: self.position + 4,
};
Ok((new_input, result.try_into().expect("we checked the length")))
}
}
fn range_of<P, R, E>(&self, mut parser: P) -> ParseResult<'a, RangeOf<R>, E>
where
P: Parser<'a, R, E>,
{
let (new_input, value) = parser.parse(*self)?;
let range = self.position..new_input.position;
Ok((new_input, RangeOf { range, value }))
}
fn rest<E>(&self) -> ParseResult<'a, &'a [u8], E> {
let position = self.position + self.bytes.len();
let new_input = Self {
position,
original: self.original,
bytes: &[],
};
Ok((new_input, self.bytes))
}
fn truncate(&self, length: usize) -> Input<'a> {
let length = if length > self.bytes.len() {
self.bytes.len()
} else {
length
};
Input {
bytes: &self.bytes[..length],
position: self.position,
original: &self.original[..(self.position + length)],
}
}
fn skip(&self, length: usize) -> Input<'a> {
if length > self.bytes.len() {
Input {
bytes: &[],
position: self.bytes.len(),
original: self.original,
}
} else {
Input {
bytes: &self.bytes[length..],
position: self.position + length,
original: &self.original[(self.position + length)..],
}
}
}
pub(crate) fn split(&self, length: usize) -> Split<'a> {
Split {
first: self.truncate(length),
remaining: self.skip(length),
}
}
pub(crate) fn reset(&self) -> Input<'a> {
Input::new(self.bytes)
}
pub(crate) fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
pub(crate) fn unconsumed_bytes(&self) -> &'a [u8] {
self.bytes
}
#[allow(clippy::misnamed_getters)]
pub(crate) fn bytes(&self) -> &'a [u8] {
self.original
}
}
pub(crate) struct Split<'a> {
pub(crate) first: Input<'a>,
pub(crate) remaining: Input<'a>,
}
pub(crate) trait Parser<'a, O, E> {
fn parse(&mut self, input: Input<'a>) -> ParseResult<'a, O, E>;
}
impl<'a, O, F, E> Parser<'a, O, E> for F
where
F: FnMut(Input<'a>) -> ParseResult<'a, O, E>,
{
fn parse(&mut self, input: Input<'a>) -> ParseResult<'a, O, E> {
(self)(input)
}
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum ParseError<E> {
Error(E),
Incomplete(Needed),
}
impl<E> ParseError<E> {
pub(crate) fn lift<F>(self) -> ParseError<F>
where
F: From<E>,
{
match self {
Self::Error(e) => ParseError::Error(F::from(e)),
Self::Incomplete(n) => ParseError::Incomplete(n),
}
}
}
impl<E: std::fmt::Display> std::fmt::Display for ParseError<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Error(e) => write!(f, "{}", e),
Self::Incomplete(_) => write!(f, "not enough data"),
}
}
}
impl<E: std::fmt::Display + std::fmt::Debug> std::error::Error for ParseError<E> {}
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum Needed {
#[allow(dead_code)]
Unknown,
Size(NonZeroUsize),
}
pub(crate) fn map<'a, O1, O2, F, G, Er>(
mut parser: F,
mut f: G,
) -> impl FnMut(Input<'a>) -> ParseResult<'a, O2, Er>
where
F: Parser<'a, O1, Er>,
G: FnMut(O1) -> O2,
{
move |input: Input<'a>| {
let (input, o1) = parser.parse(input)?;
Ok((input, f(o1)))
}
}
pub(crate) fn take1<E>(input: Input<'_>) -> ParseResult<'_, u8, E> {
input.take_1()
}
pub(crate) fn take4<E>(input: Input<'_>) -> ParseResult<'_, [u8; 4], E> {
input.take_4()
}
pub(crate) fn take_n<E>(n: usize, input: Input<'_>) -> ParseResult<'_, &[u8], E> {
input.take_n(n)
}
pub(crate) fn length_prefixed<'a, G, O, Er>(
mut g: G,
) -> impl FnMut(Input<'a>) -> ParseResult<'a, Vec<O>, Er>
where
G: Parser<'a, O, Er>,
Er: From<leb128::Error>,
{
move |input: Input<'a>| {
let (i, count) = leb128_u64(input).map_err(|e| e.lift())?;
let mut res = Vec::new();
let mut input = i;
for _ in 0..count {
match g.parse(input) {
Ok((i, e)) => {
input = i;
res.push(e);
}
Err(e) => {
return Err(e);
}
}
}
Ok((input, res))
}
}
pub(crate) fn length_prefixed_bytes<E>(input: Input<'_>) -> ParseResult<'_, &[u8], E>
where
E: From<leb128::Error>,
{
let (i, len) = leb128_u64(input).map_err(|e| e.lift())?;
take_n(len as usize, i)
}
pub(super) fn tuple2<'a, F, E, G, H, Er>(
mut f: F,
mut g: G,
) -> impl FnMut(Input<'a>) -> ParseResult<'a, (E, H), Er>
where
F: Parser<'a, E, Er>,
G: Parser<'a, H, Er>,
{
move |input: Input<'a>| {
let (i, one) = f.parse(input)?;
let (i, two) = g.parse(i)?;
Ok((i, (one, two)))
}
}
pub(super) fn apply_n<'a, F, E, Er>(
n: usize,
mut f: F,
) -> impl FnMut(Input<'a>) -> ParseResult<'a, Vec<E>, Er>
where
F: Parser<'a, E, Er>,
{
move |input: Input<'a>| {
let mut i = input;
let mut result = Vec::new();
for _ in 0..n {
let (new_i, e) = f.parse(i)?;
result.push(e);
i = new_i;
}
Ok((i, result))
}
}
pub(crate) fn actor_id<E>(input: Input<'_>) -> ParseResult<'_, ActorId, E>
where
E: From<leb128::Error>,
{
let (i, length) = leb128_u64(input).map_err(|e| e.lift())?;
let (i, bytes) = take_n(length as usize, i)?;
Ok((i, bytes.into()))
}
pub(crate) fn change_hash<E>(input: Input<'_>) -> ParseResult<'_, ChangeHash, E> {
let (i, bytes) = take_n(HASH_SIZE, input)?;
let byte_arr: ChangeHash = bytes.try_into().expect("we checked the length above");
Ok((i, byte_arr))
}
#[derive(thiserror::Error, Debug)]
#[error("invalid UTF-8")]
pub(crate) struct InvalidUtf8;
pub(crate) fn utf_8<E>(len: usize, input: Input<'_>) -> ParseResult<'_, String, E>
where
E: From<InvalidUtf8>,
{
let (i, bytes) = take_n(len, input)?;
let result = String::from_utf8(bytes.to_vec())
.map_err(|_| ParseError::Error(InvalidUtf8))
.map_err(|e| e.lift())?;
Ok((i, result))
}
pub(crate) struct RangeOf<T> {
pub(crate) range: std::ops::Range<usize>,
pub(crate) value: T,
}
pub(crate) fn range_of<'a, P, R, E>(parser: P, input: Input<'a>) -> ParseResult<'a, RangeOf<R>, E>
where
P: Parser<'a, R, E>,
{
input.range_of(parser)
}
pub(crate) fn range_only_unless_empty<'a, P, R, E>(
parser: P,
input: Input<'a>,
) -> ParseResult<'a, std::ops::Range<usize>, E>
where
P: Parser<'a, R, E>,
{
if input.is_empty() {
Ok((input, 0..0))
} else {
range_only(parser, input)
}
}
pub(crate) fn range_only<'a, P, R, E>(
parser: P,
input: Input<'a>,
) -> ParseResult<'a, std::ops::Range<usize>, E>
where
P: Parser<'a, R, E>,
{
input.range_of(parser).map(|(i, r)| (i, r.range))
}
pub(crate) fn take_rest<E>(input: Input<'_>) -> ParseResult<'_, &'_ [u8], E> {
input.rest()
}