rusty-chunkenc 0.1.2

A Rust implementation of Prometheus' chunkenc library
Documentation
use std::num::NonZeroUsize;

use nom::{number::complete::be_u64, IResult, Parser};

use crate::crc32c::{assert_crc32c_on_data, read_crc32c};

#[derive(Debug)]
pub struct IndexTableOfContent {
    pub symbols: Option<usize>,
    pub series: Option<usize>,
    pub label_indices_start: Option<usize>,
    pub label_offset_table: Option<usize>,
    pub postings_start: Option<usize>,
    pub postings_offset_table: Option<usize>,
}

static TOC_SIZE: usize = 8 * 6 + 4;
static TOC_SIZE_WITHOUT_CRC32C: usize = 8 * 6;

pub fn read_toc(input: &[u8]) -> IResult<&[u8], IndexTableOfContent> {
    let (
        remaining_input,
        (
            symbols,
            series,
            label_indices_start,
            label_offset_table,
            postings_start,
            postings_offset_table,
            expected_crc32c,
        ),
    ) = (be_u64, be_u64, be_u64, be_u64, be_u64, be_u64, read_crc32c).parse(input)?;

    assert_crc32c_on_data(input, 0, TOC_SIZE_WITHOUT_CRC32C, expected_crc32c)?;

    Ok((
        remaining_input,
        IndexTableOfContent {
            symbols: if symbols == 0 {
                None
            } else {
                Some(symbols as usize)
            },
            series: if series == 0 {
                None
            } else {
                Some(series as usize)
            },
            label_indices_start: if label_indices_start == 0 {
                None
            } else {
                Some(label_indices_start as usize)
            },
            label_offset_table: if label_offset_table == 0 {
                None
            } else {
                Some(label_offset_table as usize)
            },
            postings_start: if postings_start == 0 {
                None
            } else {
                Some(postings_start as usize)
            },
            postings_offset_table: if postings_offset_table == 0 {
                None
            } else {
                Some(postings_offset_table as usize)
            },
        },
    ))
}

pub fn read_toc_at_end(input: &[u8]) -> IResult<&[u8], IndexTableOfContent> {
    if input.len() < TOC_SIZE {
        return Err(nom::Err::Incomplete(nom::Needed::Size(
            NonZeroUsize::new(TOC_SIZE).unwrap(),
        )));
    }
    let toc_index_start = input.len() - TOC_SIZE;
    let toc_input_start = &input[toc_index_start..];
    let (remaining_input, toc) = read_toc(toc_input_start)?;
    Ok((remaining_input, toc))
}