use bumpalo::Bump;
use super::decoder::{F32_BYTES, F64_BYTES, MAP_ENTRY_MIN};
use super::decoder_value::inline_int;
use super::shape::Walk;
use crate::binary::{Decoder, tag, unzigzag};
use crate::model::number::int_to_f64;
impl<'b> Decoder<'b> {
fn next_is(&mut self, t: u8) -> Option<()> {
(self.b.get(self.i) == Some(&t)).then(|| self.i += 1)
}
pub fn null(&mut self) -> bool {
self.next_is(tag::NULL).is_some()
}
pub fn bool(&mut self) -> Option<bool> {
match *self.b.get(self.i)? {
tag::FALSE | tag::TRUE => {
self.i += 1;
Some(self.b[self.i - 1] == tag::TRUE)
}
_ => None,
}
}
pub fn int(&mut self) -> Option<i64> {
let t = *self.b.get(self.i)?;
if self.is_inline_int(t) {
self.i += 1;
return Some(inline_int(t));
}
self.next_is(tag::INT)?;
self.varint().ok().map(unzigzag)
}
pub fn float(&mut self) -> Option<f64> {
match *self.b.get(self.i)? {
tag::FLOAT => {
self.i += 1;
self.fixed().ok().map(f64::from_le_bytes)
}
tag::FLOAT32 => {
self.i += 1;
self.fixed().ok().map(|b| f64::from(f32::from_le_bytes(b)))
}
t if t == tag::INT || self.is_inline_int(t) => self.int().map(int_to_f64),
_ => None,
}
}
pub fn str(&mut self) -> Option<&'b str> {
let t = *self.b.get(self.i)?;
if self.is_indexed(t) {
self.i += 1;
return self.indexed(t).ok();
}
self.next_is(tag::STR)?;
self.string().ok()
}
pub fn bytes(&mut self) -> Option<&'b [u8]> {
self.next_is(tag::BYTES)?;
self.length_bytes().ok()
}
pub fn list(&mut self) -> Option<usize> {
self.next_is(tag::LIST)?;
let n = self.count(1).ok()?;
self.deeper().ok()?;
Some(n)
}
pub fn ints(&mut self) -> Option<usize> {
self.next_is(tag::INTS)?;
self.count(1).ok()
}
pub fn stream(&mut self) -> Option<&'b [u8]> {
self.next_is(tag::STREAM)?;
self.stream_body().ok()
}
pub(crate) fn rest(&self) -> &'b [u8] {
&self.b[self.i..]
}
pub(crate) fn stream_count(&mut self) -> Option<usize> {
self.count(1).ok()
}
pub fn floats(&mut self) -> Option<Vec<f64>> {
if self.next_is(tag::FLOATS32).is_some() {
return Some(crate::frame::floats::widen(
self.packed_floats::<F32_BYTES>()
.ok()?
.as_slice()
.as_flattened(),
));
}
self.next_is(tag::FLOATS)?;
Some(
self.packed_floats::<F64_BYTES>()
.ok()?
.map(|f| f64::from_le_bytes(*f))
.collect(),
)
}
pub fn floats32(&mut self) -> Option<Vec<f32>> {
self.next_is(tag::FLOATS32)?;
Some(
self.packed_floats::<F32_BYTES>()
.ok()?
.map(|f| f32::from_le_bytes(*f))
.collect(),
)
}
pub fn packed_int(&mut self) -> Option<i64> {
self.varint().ok().map(unzigzag)
}
pub fn map(&mut self) -> Option<usize> {
match *self.b.get(self.i)? {
tag::MAP => {
self.i += 1;
let n = self.count(MAP_ENTRY_MIN).ok()?;
self.deeper().ok()?;
Some(n)
}
tag::MAP_SHAPE if self.v2 => {
self.i += 1;
let shape = self.shape_spec().ok()?;
let n = self.shape_width(shape).ok()?;
self.deeper().ok()?;
self.frames.push(Walk {
depth: self.depth,
shape,
next: 0,
});
Some(n)
}
_ => None,
}
}
pub fn leave(&mut self) {
self.depth = self.depth.saturating_sub(1);
if self.frames.last().is_some_and(|f| f.depth > self.depth) {
self.frames.pop();
}
}
pub fn key(&mut self) -> Option<&'b str> {
if let Some(frame) = self.frames.last_mut()
&& frame.depth == self.depth
{
let string = self.shapes.keys_of(frame.shape).get(frame.next).copied()?;
frame.next += 1;
return Some(self.strings[string]);
}
self.string().ok()
}
pub fn skip(&mut self) -> Option<()> {
let arena = Bump::new();
self.value_ref(&arena).ok().map(drop)
}
}