tsfile 0.0.2

Apache IoTDB TsFile written in Rust
Documentation
use std::io::{Cursor, Read};

use byteorder::{BigEndian, ByteOrder};
use snafu::{ensure, ResultExt};

use crate::file::metadata::TsFileMetadata;
use crate::file::reader::SectionReader;
use crate::FOOTER_SIZE;

use crate::file::metadata;
use snafu::Snafu;

#[derive(Debug, Snafu)]
pub enum Error {
    #[snafu(display("Unable to parser metadata: {}", source))]
    ParserMetadata { source: metadata::Error },
    #[snafu(display("Invalid TsFile. {}", detail))]
    InvalidTsFile { detail: String },
    #[snafu(display("Unable to read cursor: {}", source))]
    ReadCursorData { source: std::io::Error },
}

type Result<T, E = Error> = std::result::Result<T, E>;

pub fn parser_metadata<R: SectionReader>(reader: &R) -> Result<TsFileMetadata> {
    let file_size = reader.len();
    ensure!(
        file_size >= (FOOTER_SIZE as u64),
        InvalidTsFile {
            detail: "Size is smaller than footer".to_string()
        }
    );

    let mut result = reader.get_read(file_size - FOOTER_SIZE as u64, FOOTER_SIZE);

    let mut end_buf = vec![0; FOOTER_SIZE];
    result.read_exact(&mut end_buf).context(ReadCursorData)?;

    ensure!(
        end_buf[4..] == [b'T', b's', b'F', b'i', b'l', b'e'],
        InvalidTsFile {
            detail: "Corrupt footer".to_string()
        }
    );

    let metadata_len = BigEndian::read_i32(&end_buf[0..4]);
    ensure!(
        metadata_len >= 0,
        InvalidTsFile {
            detail: " Metadata length is less than zero".to_string()
        }
    );

    let footer_metadata_pos = file_size - FOOTER_SIZE as u64 - metadata_len as u64;

    let metadata_reader = reader.get_read(footer_metadata_pos, metadata_len as usize);
    let mut metadata_reader = Box::new(metadata_reader);

    let mut data = vec![0; metadata_len as usize];
    let result = metadata_reader.read(&mut data).context(ReadCursorData)?;
    ensure!(
        result == metadata_len as usize,
        InvalidTsFile {
            detail: "TsFileMetadata error".to_string()
        }
    );
    TsFileMetadata::parser(Cursor::new(data)).context(ParserMetadata)
}