Package up Indexer

This commit is contained in:
Tony Garnock-Jones 2022-11-10 22:45:51 +01:00
parent 4a1b021635
commit 384644f5ea
1 changed files with 69 additions and 46 deletions

View File

@ -40,16 +40,6 @@ fn tag_at(packed: &[u8], i: usize) -> io::Result<Tag> {
Ok(Tag::try_from(at(packed, i)?)?)
}
fn skip_annotations(packed: &[u8], mut i: usize) -> io::Result<usize> {
loop {
if tag_at(packed, i)? == Tag::Annotation {
i = skip_value(packed, i + 1)?;
} else {
return Ok(i);
}
}
}
fn varint(packed: &[u8], mut i: usize) -> io::Result<(u64, usize)> {
let mut shift = 0;
let mut acc: u64 = 0;
@ -64,51 +54,84 @@ fn varint(packed: &[u8], mut i: usize) -> io::Result<(u64, usize)> {
}
}
fn skip_value(packed: &[u8], mut i: usize) -> io::Result<usize> {
loop {
let next_i = match tag_at(packed, i)? {
Tag::False => i + 1,
Tag::True => i + 1,
Tag::Float => i + 5,
Tag::Double => i + 9,
Tag::End => Err(io::Error::new(io::ErrorKind::InvalidData, "Unexpected end tag"))?,
Tag::Annotation => {
i = skip_value(packed, i + 1)?;
continue;
struct Indexer<'de> {
packed: &'de [u8],
offset: usize,
}
impl<'de> Indexer<'de> {
fn skip_annotations(&mut self) -> io::Result<()> {
loop {
if tag_at(&self.packed, self.offset)? == Tag::Annotation {
self.offset += 1;
self.skip_value()?;
} else {
return Ok(());
}
Tag::Embedded => {
i = i + 1;
continue;
}
Tag::SmallInteger(_) => i + 1,
Tag::MediumInteger(n) => i + 1 + (n as usize),
Tag::SignedInteger | Tag::ByteString => {
let (n, i) = varint(packed, i + 1)?;
i + (n as usize)
}
Tag::String | Tag::Symbol => {
let (n, i) = varint(packed, i + 1)?;
std::str::from_utf8(&packed[i .. i + (n as usize)]).map_err(
|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8"))?;
i + (n as usize)
}
Tag::Record | Tag::Sequence | Tag::Set | Tag::Dictionary => {
i = i + 1;
while tag_at(packed, i)? != Tag::End {
i = skip_value(packed, i)?;
}
}
fn tag(&mut self) -> io::Result<Tag> {
let tag = tag_at(&self.packed, self.offset)?;
Ok(tag)
}
fn varint(&mut self) -> io::Result<u64> {
let (n, i) = varint(&self.packed, self.offset + 1)?;
self.offset = i;
Ok(n)
}
fn skip_value(&mut self) -> io::Result<()> {
loop {
match self.tag()? {
Tag::False => self.offset += 1,
Tag::True => self.offset += 1,
Tag::Float => self.offset += 5,
Tag::Double => self.offset += 9,
Tag::End => Err(io::Error::new(io::ErrorKind::InvalidData, "Unexpected end tag"))?,
Tag::Annotation => {
self.offset += 1;
self.skip_value()?;
continue;
}
Tag::Embedded => {
self.offset += 1;
continue;
}
Tag::SmallInteger(_) => self.offset += 1,
Tag::MediumInteger(n) => self.offset += 1 + n as usize,
Tag::SignedInteger | Tag::ByteString => {
let n = self.varint()?;
self.offset += n as usize;
}
Tag::String | Tag::Symbol => {
let n = self.varint()?;
std::str::from_utf8(&self.packed[self.offset .. self.offset + (n as usize)])
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8"))?;
self.offset += n as usize;
}
Tag::Record | Tag::Sequence | Tag::Set | Tag::Dictionary => {
self.offset += 1;
while tag_at(&self.packed, self.offset)? != Tag::End {
self.skip_value()?;
}
self.offset += 1;
}
i + 1
}
};
return Ok(next_i);
return Ok(());
}
}
}
impl<'de, Packed: AsRef<[u8]> + 'de> View<'de, Packed> {
pub fn new(packed: Packed) -> io::Result<Self> {
// println!("packed {:?}", &packed.as_ref());
let value_offset = skip_annotations(packed.as_ref(), 0)?;
let value_end = skip_value(packed.as_ref(), value_offset)?;
let mut indexer = Indexer { packed: packed.as_ref(), offset: 0 };
indexer.skip_annotations()?;
let value_offset = indexer.offset;
indexer.skip_value()?;
let value_end = indexer.offset;
if value_end > packed.as_ref().len() { Err(io_eof())? }
Ok(View { packed, value_offset, value_end, phantom: PhantomData })
}