tsfile-writer 0.2.1

A simple TsFile writer in rust with a sync sender to import tsfiles to Apache IoTDB instances
Documentation
//! This is a not yet feature complete Writer for TsFiles Version 3 (as defined from the Apache IoTDB Project).
//! Currently not all features of TsFiles are supported.
//! Most notably:
//!
//! * No Aligned Chunks can be written
//! * Not all Encodings are available
//! * Not all DataTypes are supported
//! * Not all Compression Types are supported
//!
//! But generally, the TsFiles written with this client are 100% compatible with TsFiles written in Java.
//!
//! ## Quickstart
//!
//! To write a TsFile just do something like
//!
//! ```
//! use tsfile_writer::writer::tsfile_writer::TsFileWriter;
//! use tsfile_writer::writer::IoTDBValue;
//! use tsfile_writer::writer::tsfile_writer::DataPoint;
//! use tsfile_writer::writer::schema::TsFileSchemaBuilder;
//! use tsfile_writer::writer::schema::DeviceBuilder;
//! use tsfile_writer::writer::TSDataType;
//! use tsfile_writer::writer::encoding::TSEncoding;
//! use tsfile_writer::writer::compression::CompressionType;
//!
//! // Create the Schema
//! // Two devices with two sensors each
//! let schema = TsFileSchemaBuilder::new()
//!         .add(
//!             "d1",
//!             DeviceBuilder::new()
//!                 .add(
//!                     "s1",
//!                     TSDataType::INT64,
//!                     TSEncoding::PLAIN,
//!                     CompressionType::UNCOMPRESSED,
//!                 )
//!                 .add(
//!                     "s2",
//!                     TSDataType::FLOAT,
//!                     TSEncoding::PLAIN,
//!                     CompressionType::UNCOMPRESSED,
//!                 )
//!                 .build(),
//!         )
//!         .add(
//!             "d2",
//!             DeviceBuilder::new()
//!                 .add(
//!                     "s1",
//!                     TSDataType::INT64,
//!                     TSEncoding::PLAIN,
//!                     CompressionType::UNCOMPRESSED,
//!                 )
//!                 .add(
//!                     "s2",
//!                     TSDataType::FLOAT,
//!                     TSEncoding::PLAIN,
//!                     CompressionType::UNCOMPRESSED,
//!                 )
//!                 .build(),
//!         )
//!         .build();
//!
//! // Create the writer
//! let mut writer = TsFileWriter::new(
//!     "target/benchmark2.tsfile",
//!     schema,
//!     Default::default(),
//! )
//! .unwrap();
//!
//! // Write multiple timeseries at once
//! writer.write_many("d1",1, vec![
//!         DataPoint::new("s1", IoTDBValue::LONG(13)),
//!         DataPoint::new("s2", IoTDBValue::FLOAT(13.0 as f32)),
//! ]);
//!
//! // Write single series
//! writer.write("d2", "s1", 1, IoTDBValue::LONG(14));
//! writer.write("d2", "s2", 1, IoTDBValue::FLOAT(14.0 as f32));
//! ```
#![allow(unused_must_use)]
extern crate core;

use std::cmp::Ordering;
use std::collections::hash_map::IntoIter;
use std::collections::{BTreeMap, HashMap};
use std::fmt::{Display, Formatter};
use std::hash::Hash;
use std::io::Write;
use std::{io, vec};

mod chunk_writer;
pub mod compression;
pub mod encoding;
pub mod errors;
mod group_writer;
mod murmur128;
pub mod schema;
mod statistics;
mod test;
pub mod test_utils;
pub mod ts_file_config;
mod tsfile_io_writer;
pub mod tsfile_writer;
mod utils;

use crate::writer::chunk_writer::ChunkMetadata;
use crate::writer::compression::CompressionType;
use crate::writer::encoding::TSEncoding;
use crate::writer::errors::TsFileError;

use crate::writer::murmur128::Murmur128;
use crate::writer::schema::{DeviceBuilder, TsFileSchemaBuilder};
use crate::writer::statistics::Statistics;
use crate::writer::ts_file_config::TsFileConfig;
use crate::writer::utils::{write_var_i32, write_var_u32};
use crate::writer::MetadataIndexNodeType::LeafDevice;

/// Central enum to pass Values to the writer
#[allow(dead_code)]
#[derive(Clone)]
pub enum IoTDBValue {
    DOUBLE(f64),
    FLOAT(f32),
    INT(i32),
    LONG(i64),
}

impl From<i64> for IoTDBValue {
    fn from(x: i64) -> Self {
        IoTDBValue::LONG(x)
    }
}

/// Extension of the Write trait
/// that allows to get the position of the "buffer"
/// via the `get_position()` method
pub trait PositionedWrite: Write {
    fn get_position(&self) -> u64;
}

pub struct WriteWrapper<T: Write> {
    position: u64,
    writer: T,
}

impl<T: Write> Write for WriteWrapper<T> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match self.writer.write(buf) {
            Ok(size) => {
                self.position += size as u64;
                Ok(size)
            }
            Err(e) => Err(e),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        self.writer.flush()
    }
}

impl<T: Write> PositionedWrite for WriteWrapper<T> {
    fn get_position(&self) -> u64 {
        self.position
    }
}

impl<T: Write> WriteWrapper<T> {
    fn new(writer: T) -> WriteWrapper<T> {
        WriteWrapper {
            position: 0,
            writer,
        }
    }
}

impl PositionedWrite for Vec<u8> {
    fn get_position(&self) -> u64 {
        self.len() as u64
    }
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum TSDataType {
    INT32,
    INT64,
    FLOAT,
}

impl TSDataType {
    pub fn serialize(&self) -> u8 {
        match self {
            TSDataType::INT32 => 1,
            TSDataType::INT64 => 2,
            TSDataType::FLOAT => 3,
        }
    }
}

impl TryFrom<u8> for TSDataType {
    type Error = ();

    fn try_from(value: u8) -> Result<Self, Self::Error> {
        match value {
            1 => Ok(TSDataType::INT32),
            2 => Ok(TSDataType::INT64),
            3 => Ok(TSDataType::FLOAT),
            _ => Err(()),
        }
    }
}

#[derive(Clone)]
pub struct MeasurementSchema {
    pub data_type: TSDataType,
    pub encoding: TSEncoding,
    pub compression: CompressionType,
}

#[derive(Clone, PartialEq, Eq, Hash)]
struct Path {
    path: String,
}

impl Display for Path {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.path)
    }
}

impl Ord for Path {
    fn cmp(&self, other: &Self) -> Ordering {
        self.path.cmp(&other.path)
    }
}

impl PartialOrd<Self> for Path {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.path.partial_cmp(&other.path)
    }
}

impl MeasurementSchema {
    #[allow(dead_code)]
    fn new(
        data_type: TSDataType,
        encoding: TSEncoding,
        compression: CompressionType,
    ) -> MeasurementSchema {
        MeasurementSchema {
            data_type,
            encoding,
            compression,
        }
    }
}

#[derive(Clone)]
pub struct MeasurementGroup<'a> {
    measurement_schemas: HashMap<&'a str, MeasurementSchema>,
}

impl<'a> MeasurementGroup<'a> {
    pub fn get_timeseries(&self) -> IntoIter<&'a str, MeasurementSchema> {
        self.measurement_schemas.clone().into_iter()
    }
}

#[derive(Clone)]
pub struct Schema<'a> {
    measurement_groups: HashMap<&'a str, MeasurementGroup<'a>>,
}

impl<'a> Schema<'a> {
    pub fn get_devices(&self) -> IntoIter<&'a str, MeasurementGroup<'a>> {
        self.measurement_groups.clone().into_iter()
    }
}

impl<'a> Display for Schema<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let mut devices = vec![];
        for device_id in self.measurement_groups.keys() {
            devices.push(device_id);
        }
        write!(f, "{:?}", devices)
    }
}

impl<'a> Schema<'a> {
    pub fn simple(
        device_id: &'a str,
        measurement_id: &'a str,
        data_type: TSDataType,
        encoding: TSEncoding,
        compression: CompressionType,
    ) -> Schema<'a> {
        TsFileSchemaBuilder::new()
            .add(
                device_id,
                DeviceBuilder::new()
                    .add(measurement_id, data_type, encoding, compression)
                    .build(),
            )
            .build()
    }
}

struct ChunkGroupMetadata {
    device_id: String,
    chunk_metadata: Vec<ChunkMetadata>,
}

impl ChunkGroupMetadata {
    fn new(device_id: String, chunk_metadata: Vec<ChunkMetadata>) -> ChunkGroupMetadata {
        ChunkGroupMetadata {
            device_id,
            chunk_metadata,
        }
    }
}

#[derive(Clone)]
enum MetadataIndexNodeType {
    LeafMeasurement,
    InternalMeasurement,
    LeafDevice,
}

impl Serializable for MetadataIndexNodeType {
    //   /** INTERNAL_DEVICE */
    //   INTERNAL_DEVICE((byte) 0),
    //
    //   /** LEAF_DEVICE */
    //   LEAF_DEVICE((byte) 1),
    //
    //   /** INTERNAL_MEASUREMENT */
    //   INTERNAL_MEASUREMENT((byte) 2),
    //
    //   /** INTERNAL_MEASUREMENT */
    //   LEAF_MEASUREMENT((byte) 3);
    fn serialize(&self, file: &mut dyn PositionedWrite) -> Result<(), TsFileError> {
        let byte: u8 = match self {
            MetadataIndexNodeType::LeafMeasurement => 0x03,
            MetadataIndexNodeType::InternalMeasurement => 0x02,
            LeafDevice => 0x01,
        };
        file.write(&[byte]);

        Ok(())
    }
}

struct TimeseriesMetadata {}

#[derive(Clone)]
struct MetadataIndexEntry {
    name: String,
    offset: usize,
}

impl Serializable for MetadataIndexEntry {
    fn serialize(&self, file: &mut dyn PositionedWrite) -> Result<(), TsFileError> {
        // int byteLen = 0;
        // byteLen += ReadWriteIOUtils.writeVar(name, outputStream);
        // byteLen += ReadWriteIOUtils.write(offset, outputStream);
        // return byteLen;
        write_str(file, self.name.as_str());
        file.write(&self.offset.to_be_bytes());
        // file.write(&(self.offset as i64).to_be_bytes());

        Ok(())
    }
}

#[derive(Clone)]
struct MetadataIndexNode {
    children: Vec<MetadataIndexEntry>,
    end_offset: usize,
    node_type: MetadataIndexNodeType,
}

impl Serializable for MetadataIndexNode {
    fn serialize(&self, file: &mut dyn PositionedWrite) -> Result<(), TsFileError> {
        // int byteLen = 0;
        // byteLen += ReadWriteForEncodingUtils.writeUnsignedVarInt(children.size(), outputStream);
        // for (MetadataIndexEntry metadataIndexEntry : children) {
        //   byteLen += metadataIndexEntry.serializeTo(outputStream);
        // }
        // byteLen += ReadWriteIOUtils.write(endOffset, outputStream);
        // byteLen += ReadWriteIOUtils.write(nodeType.serialize(), outputStream);
        // return byteLen;
        write_var_u32(self.children.len() as u32, file);

        for metadata_index_entry in self.children.iter() {
            metadata_index_entry.serialize(file);
        }

        file.write(&self.end_offset.to_be_bytes());
        self.node_type.serialize(file);

        Ok(())
    }
}

impl MetadataIndexNode {
    fn new(node_type: MetadataIndexNodeType) -> MetadataIndexNode {
        MetadataIndexNode {
            children: vec![],
            end_offset: 0,
            node_type,
        }
    }

    fn add_current_index_node_to_queue(
        current_index_node: &mut MetadataIndexNode,
        measurement_metadata_index_queue: &mut Vec<MetadataIndexNode>,
        file: &mut dyn PositionedWrite,
    ) {
        // TODO file.getPosition
        // currentIndexNode.setEndOffset(out.getPosition());
        current_index_node.end_offset = file.get_position() as usize;
        // metadataIndexNodeQueue.add(currentIndexNode);
        measurement_metadata_index_queue.push(current_index_node.clone());
    }

    #[allow(unused_variables)]
    fn generate_root_node(
        mut measurement_metadata_index_queue: Vec<MetadataIndexNode>,
        file: &mut dyn PositionedWrite,
        node_type: MetadataIndexNodeType,
        config: &TsFileConfig,
    ) -> MetadataIndexNode {
        // int queueSize = metadataIndexNodeQueue.size();
        // MetadataIndexNode metadataIndexNode;
        // MetadataIndexNode currentIndexNode = new MetadataIndexNode(type);
        // while (queueSize != 1) {
        //   for (int i = 0; i < queueSize; i++) {
        //     metadataIndexNode = metadataIndexNodeQueue.poll();
        //     // when constructing from internal node, each node is related to an entry
        //     if (currentIndexNode.isFull()) {
        //       addCurrentIndexNodeToQueue(currentIndexNode, metadataIndexNodeQueue, out);
        //       currentIndexNode = new MetadataIndexNode(type);
        //     }
        //     currentIndexNode.addEntry(
        //         new MetadataIndexEntry(metadataIndexNode.peek().getName(), out.getPosition()));
        //     metadataIndexNode.serializeTo(out.wrapAsStream());
        //   }
        //   addCurrentIndexNodeToQueue(currentIndexNode, metadataIndexNodeQueue, out);
        //   currentIndexNode = new MetadataIndexNode(type);
        //   queueSize = metadataIndexNodeQueue.size();
        // }
        // return metadataIndexNodeQueue.poll();
        // TODO
        let mut queue_size = measurement_metadata_index_queue.len();
        let mut metadata_index_node;
        let mut current_index_metadata = MetadataIndexNode::new(node_type.clone());

        while queue_size != 1 {
            for i in 0..queue_size {
                metadata_index_node = measurement_metadata_index_queue.last().unwrap().clone();
                let device = match metadata_index_node.children.get(0) {
                    None => {
                        panic!("...")
                    }
                    Some(inner) => inner.name.clone(),
                };
                measurement_metadata_index_queue.remove(measurement_metadata_index_queue.len() - 1);
                if current_index_metadata.is_full(config) {
                    current_index_metadata.end_offset = file.get_position() as usize;
                    measurement_metadata_index_queue.push(current_index_metadata.clone());
                }
                // ...
                let name = match metadata_index_node.children.get(0) {
                    None => {
                        panic!("This should not happen!")
                    }
                    Some(node) => node.name.clone(),
                };
                current_index_metadata.children.push(MetadataIndexEntry {
                    name,
                    offset: file.get_position() as usize,
                });
            }
            // ...
            Self::add_current_index_node_to_queue(
                &mut current_index_metadata,
                &mut measurement_metadata_index_queue,
                file,
            );
            current_index_metadata = MetadataIndexNode {
                children: vec![],
                end_offset: 0,
                node_type: node_type.clone(),
            };
            queue_size = measurement_metadata_index_queue.len();
        }
        return measurement_metadata_index_queue.get(0).unwrap().clone();
    }

    #[allow(unused_variables)]
    fn construct_metadata_index(
        device_timeseries_metadata_map: &BTreeMap<String, Vec<Box<dyn TimeSeriesMetadatable>>>,
        file: &mut dyn PositionedWrite,
        config: &TsFileConfig,
    ) -> MetadataIndexNode {
        let mut device_metadata_index_map: HashMap<String, MetadataIndexNode> = HashMap::new();

        for (device, list_metadata) in device_timeseries_metadata_map.iter() {
            if list_metadata.is_empty() {
                continue;
            }

            let mut measurement_metadata_index_queue: Vec<MetadataIndexNode> = vec![];

            let timeseries_metadata: TimeseriesMetadata;
            let mut current_index_node: MetadataIndexNode =
                MetadataIndexNode::new(MetadataIndexNodeType::LeafMeasurement);

            // for (int i = 0; i < entry.getValue().size(); i++) {
            for i in 0..list_metadata.len() {
                let timeseries_metadata = list_metadata.get(i).unwrap();

                if i % config.max_degree_of_index_node == 0 {
                    if current_index_node.is_full(config) {
                        Self::add_current_index_node_to_queue(
                            &mut current_index_node,
                            &mut measurement_metadata_index_queue,
                            file,
                        );
                        current_index_node =
                            MetadataIndexNode::new(MetadataIndexNodeType::LeafMeasurement);
                    }
                    current_index_node.children.push(MetadataIndexEntry {
                        name: timeseries_metadata.get_measurement_id(),
                        offset: file.get_position() as usize,
                    });
                }
                timeseries_metadata.serialize(file);
            }
            // addCurrentIndexNodeToQueue(currentIndexNode, measurementMetadataIndexQueue, out);
            // deviceMetadataIndexMap.put(
            //       entry.getKey(),
            //       generateRootNode(
            //           measurementMetadataIndexQueue, out, MetadataIndexNodeType.INTERNAL_MEASUREMENT));
            current_index_node.end_offset = file.get_position() as usize;
            measurement_metadata_index_queue.push(current_index_node.clone());

            let root_node = Self::generate_root_node(
                measurement_metadata_index_queue,
                file,
                MetadataIndexNodeType::InternalMeasurement,
                config,
            );
            device_metadata_index_map.insert(device.clone(), root_node);
        }

        if device_metadata_index_map.len() <= config.max_degree_of_index_node {
            let mut metadata_index_node = MetadataIndexNode::new(LeafDevice);

            for (s, value) in device_metadata_index_map {
                metadata_index_node.children.push(MetadataIndexEntry {
                    name: s.to_owned(),
                    offset: file.get_position() as usize,
                });
                value.serialize(file);
            }
            metadata_index_node.end_offset = file.get_position() as usize;
            return metadata_index_node;
        }

        panic!("This is not yet implemented!");

        // // if not exceed the max child nodes num, ignore the device index and directly point to the
        // // measurement
        // if (deviceMetadataIndexMap.size() <= config.getMaxDegreeOfIndexNode()) {
        //   MetadataIndexNode metadataIndexNode =
        //       new MetadataIndexNode(MetadataIndexNodeType.LEAF_DEVICE);
        //   for (Map.Entry<String, MetadataIndexNode> entry : deviceMetadataIndexMap.entrySet()) {
        //     metadataIndexNode.addEntry(new MetadataIndexEntry(entry.getKey(), out.getPosition()));
        //     entry.getValue().serializeTo(out.wrapAsStream());
        //   }
        //   metadataIndexNode.setEndOffset(out.getPosition());
        //   return metadataIndexNode;
        // }
        //
        // // else, build level index for devices
        // Queue<MetadataIndexNode> deviceMetadataIndexQueue = new ArrayDeque<>();
        // MetadataIndexNode currentIndexNode = new MetadataIndexNode(MetadataIndexNodeType.LEAF_DEVICE);
        //
        // for (Map.Entry<String, MetadataIndexNode> entry : deviceMetadataIndexMap.entrySet()) {
        //   // when constructing from internal node, each node is related to an entry
        //   if (currentIndexNode.isFull()) {
        //     addCurrentIndexNodeToQueue(currentIndexNode, deviceMetadataIndexQueue, out);
        //     currentIndexNode = new MetadataIndexNode(MetadataIndexNodeType.LEAF_DEVICE);
        //   }
        //   currentIndexNode.addEntry(new MetadataIndexEntry(entry.getKey(), out.getPosition()));
        //   entry.getValue().serializeTo(out.wrapAsStream());
        // }
        // addCurrentIndexNodeToQueue(currentIndexNode, deviceMetadataIndexQueue, out);
        // MetadataIndexNode deviceMetadataIndexNode =
        //     generateRootNode(deviceMetadataIndexQueue, out, MetadataIndexNodeType.INTERNAL_DEVICE);
        // deviceMetadataIndexNode.setEndOffset(out.getPosition());
        // return deviceMetadataIndexNode;
    }
    fn is_full(&self, config: &TsFileConfig) -> bool {
        self.children.len() >= config.max_degree_of_index_node
    }
}

trait TimeSeriesMetadatable {
    fn get_measurement_id(&self) -> String;
    fn serialize(&self, file: &mut dyn PositionedWrite) -> io::Result<()>;
}

impl TimeSeriesMetadatable for TimeSeriesMetadata {
    fn get_measurement_id(&self) -> String {
        self.measurement_id.clone()
    }

    fn serialize(&self, file: &mut dyn PositionedWrite) -> io::Result<()> {
        file.write_all(&[self.time_series_metadata_type]);
        write_str(file, self.measurement_id.as_str());
        file.write_all(&[self.data_type.serialize()]);
        write_var_u32(self.chunk_meta_data_list_data_size as u32, file);
        self.statistics.serialize(file);
        file.write_all(&self.buffer);
        Ok(())
    }
}

struct TimeSeriesMetadata {
    time_series_metadata_type: u8,
    chunk_meta_data_list_data_size: usize,
    measurement_id: String,
    data_type: TSDataType,
    statistics: Statistics,
    buffer: Vec<u8>,
}
//
// impl<T> Serializable for TimeSeriesMetadata<T> {
//     fn serialize(&self, file: &mut dyn PositionedWrite) -> io::Result<()> {
//         file.write_all(&[self.time_series_metadata_type]);
//         write_str(file, self.measurement_id.as_str());
//         file.write_all(&[self.data_type.serialize()]);
//         write_var_u32(self.chunk_meta_data_list_data_size as u32, file);
//         self.statistics.serialize(file);
//         file.write_all(&self.buffer);
//         Ok(())
//     }
// }

struct HashFunction {
    cap: i32,
    seed: i32,
}

impl HashFunction {
    fn new(cap: i32, seed: i32) -> HashFunction {
        HashFunction { cap, seed }
    }

    fn _murmur_hash(&self, s: &str, seed: i32) -> i32 {
        Murmur128::hash(s, seed)
    }

    fn hash(&self, value: &str) -> usize {
        // return Math.abs(Murmur128Hash.hash(value, seed)) % cap;
        (self._murmur_hash(value, self.seed).abs() % self.cap) as usize
    }
}

struct BloomFilter {
    size: i32,
    hash_function_size: i32,
    func: Vec<HashFunction>,
    bit_set: Vec<bool>,
}

impl BloomFilter {
    fn add(&mut self, path: String) {
        for f in self.func.iter() {
            let bit_id = f.hash(&path);
            // println!("{path} - {} -> {}", f.seed, bit_id);
            self.bit_set[bit_id] = true;
        }
    }

    fn new(size: i32, hash_function_size: i32, config: &TsFileConfig) -> BloomFilter {
        let mut func = vec![];

        for i in 0..hash_function_size {
            func.push(HashFunction::new(size, config.seeds[i as usize] as i32));
        }

        let bit_set = vec![false; size as usize];

        BloomFilter {
            size,
            hash_function_size,
            func,
            bit_set,
        }
    }

    fn build(paths: Vec<Path>, config: &TsFileConfig) -> BloomFilter {
        let mut filter =
            BloomFilter::empty_filter(config.bloom_filter_error_rate, paths.len() as i32, config);

        for path in paths {
            filter.add(path.path);
        }

        filter
    }

    fn empty_filter(error_percent: f64, num_of_string: i32, config: &TsFileConfig) -> BloomFilter {
        let mut error = error_percent;
        error = error.max(config.min_bloom_filter_error_rate);
        error = error.min(config.max_bloom_filter_error_rate);

        let ln2 = 2.0_f64.ln();

        let size = (-num_of_string as f64 * error.ln() / ln2 / ln2) as i32 + 1;
        let hash_function_size = ((-1.0 * error.ln() / ln2) + 1.0) as i32;

        BloomFilter::new(
            size.max(config.minimal_size),
            hash_function_size.min(config.maximal_hash_function_size),
            config,
        )
    }

    fn serialize_bits(&self) -> Vec<u8> {
        let number_of_bytes = if self.bit_set.len() % 8 == 0 {
            self.bit_set.len() / 8
        } else {
            (self.bit_set.len() + (self.bit_set.len() % 8)) / 8
        };

        let mut result = vec![0_u8; number_of_bytes];

        for i in 0..self.bit_set.len() {
            let byte_index = (i - (i % 8)) / 8;
            let bit_index = i % 8;

            // println!("{} - {} / {} -> {}", i, byte_index, bit_index, self.bit_set[i]);

            // TODO why is this necessary?
            // if byte_index >= result.len() {
            //     println!("Skipped!!!!");
            //     continue;
            // }

            let value = *result.get(byte_index).unwrap();

            // See https://stackoverflow.com/questions/57449264/how-to-get-replace-a-value-in-rust-vec
            let bit: u8 = if self.bit_set[i] { 0x01 } else { 0x00 };
            std::mem::replace(&mut result[byte_index], value | (bit << bit_index));
        }

        // Remove all trailing zero-bytes
        while result.last().is_some() && *result.last().unwrap() == 0x00 {
            result.remove(result.len() - 1);
        }

        result
    }
}

impl Serializable for BloomFilter {
    fn serialize(&self, file: &mut dyn PositionedWrite) -> Result<(), TsFileError> {
        // Real
        let bytes = self.serialize_bits();

        write_var_u32(bytes.len() as u32, file);
        file.write_all(bytes.as_slice());
        write_var_u32(self.size as u32, file);
        write_var_u32(self.hash_function_size as u32, file);

        Ok(())
    }
}

struct TsFileMetadata {
    metadata_index: Option<MetadataIndexNode>,
    meta_offset: u64,
}

impl TsFileMetadata {
    pub fn new(metadata_index: Option<MetadataIndexNode>, meta_offset: u64) -> TsFileMetadata {
        TsFileMetadata {
            metadata_index,
            meta_offset,
        }
    }
}

impl Serializable for TsFileMetadata {
    fn serialize(&self, file: &mut dyn PositionedWrite) -> Result<(), TsFileError> {
        match self.metadata_index.clone() {
            Some(index) => {
                index.serialize(file);
            }
            None => {
                // Write 0 as 4 bytes (u32)
                file.write_all(&0x00_u32.to_be_bytes());
            }
        }
        // Meta Offset
        file.write_all(&self.meta_offset.to_be_bytes());

        Ok(())
    }
}

pub struct ChunkGroupHeader<'a> {
    device_id: &'a str,
}

impl<'a> ChunkGroupHeader<'a> {
    fn new(device_id: &'a str) -> ChunkGroupHeader<'a> {
        ChunkGroupHeader { device_id }
    }
}

impl Serializable for ChunkGroupHeader<'_> {
    fn serialize(&self, file: &mut dyn PositionedWrite) -> Result<(), TsFileError> {
        file.write_all(&[0])?;
        write_str(file, self.device_id)?;
        Ok(())
    }
}

struct ChunkGroup<'a> {
    header: ChunkGroupHeader<'a>,
}

impl Serializable for ChunkGroup<'_> {
    fn serialize(&self, file: &mut dyn PositionedWrite) -> Result<(), TsFileError> {
        self.header.serialize(file)
    }
}

pub trait Serializable {
    fn serialize(&self, file: &mut dyn PositionedWrite) -> Result<(), TsFileError>;
}

fn write_str(file: &mut dyn PositionedWrite, s: &str) -> Result<(), TsFileError> {
    let len = s.len() as i32;
    write_var_i32(len, file)?;
    let bytes = s.as_bytes();
    file.write_all(bytes)?; // measurement id
    Ok(())
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use std::time::{SystemTime, UNIX_EPOCH};

    use crate::writer::compression::CompressionType;
    use crate::writer::encoding::TSEncoding;
    use crate::writer::schema::{DeviceBuilder, TsFileSchemaBuilder};
    use crate::writer::tsfile_writer::TsFileWriter;
    use crate::writer::utils::{read_var_u32, write_var_u32};
    use crate::writer::{
        IoTDBValue, MeasurementGroup, MeasurementSchema, Schema, TSDataType, TsFileError,
        WriteWrapper,
    };

    #[test]
    fn it_works() {
        let result = 2 + 2;
        assert_eq!(result, 4);
    }

    #[test]
    fn write_file_test_4() {
        let expectation = [
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65, 0x03, 0x00, 0x04, 0x64, 0x31, 0x05, 0x04, 0x73,
            0x31, 0x20, 0x01, 0x00, 0x00, 0x1E, 0x1E, 0x1A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
            0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x01, 0x01, 0x44, 0x1A, 0x1C, 0x1E, // TODO make this in HEX
            2, 0, 4, 115, 49, 1, 8, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0,
            13, 0, 0, 0, 15, 0, 0, 0, 13, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0,
            0, 11, 1, 4, 115, 49, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 107, 3, 1, 4, 100,
            49, 0, 0, 0, 0, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 0, 0, 0, 51, 31,
            4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 2, 128, 2, 5, 0, 0, 0, 64, 84, 115, 70, 105, 108, 101,
        ];

        let measurement_schema = MeasurementSchema::new(
            TSDataType::INT32,
            TSEncoding::PLAIN,
            CompressionType::UNCOMPRESSED,
        );

        let mut measurement_schema_map = HashMap::new();
        measurement_schema_map.insert("s1", measurement_schema);
        let measurement_group = MeasurementGroup {
            measurement_schemas: measurement_schema_map,
        };
        let mut measurement_groups_map = HashMap::new();
        let d1 = "d1";
        measurement_groups_map.insert(d1, measurement_group);
        let schema = Schema {
            measurement_groups: measurement_groups_map,
        };
        let buffer: Vec<u8> = vec![];
        let buffer_writer = WriteWrapper::new(buffer);

        let mut writer =
            TsFileWriter::new_from_writer(schema, buffer_writer, Default::default()).unwrap();

        TsFileWriter::write(&mut writer, "d1", "s1", 1, IoTDBValue::INT(13));
        TsFileWriter::write(&mut writer, "d1", "s1", 10, IoTDBValue::INT(14));
        TsFileWriter::write(&mut writer, "d1", "s1", 100, IoTDBValue::INT(15));

        writer.close();

        let buffer_writer = writer.file_io_writer.out;

        assert_eq!(buffer_writer.writer, expectation);
        assert_eq!(buffer_writer.position, expectation.len() as u64);
    }

    #[test]
    fn write_file_5() {
        let device = "root.sg.d1";
        let schema = TsFileSchemaBuilder::new()
            .add(
                device,
                DeviceBuilder::new()
                    .add(
                        "s1",
                        TSDataType::INT32,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .add(
                        "s2",
                        TSDataType::INT32,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let epoch_time_ms = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_millis();

        let filename = format!("target/{}-1-0-0.tsfile", epoch_time_ms);
        let mut writer = TsFileWriter::new(filename.as_str(), schema, Default::default()).unwrap();

        for i in 0..100 {
            writer.write(device, "s1", i, IoTDBValue::INT(i as i32));
            writer.write(device, "s2", i, IoTDBValue::INT(i as i32));
        }

        writer.close();
    }

    #[test]
    fn write_i64() {
        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s1",
                        TSDataType::INT64,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let mut writer =
            TsFileWriter::new("target/write_long.tsfile", schema, Default::default()).unwrap();

        let result = writer.write("d1", "s1", 0, IoTDBValue::LONG(0));

        match result {
            Ok(_) => {}
            Err(_) => {
                assert!(false);
            }
        }

        writer.close();
    }

    #[test]
    fn write_float() {
        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s1",
                        TSDataType::FLOAT,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let mut writer =
            TsFileWriter::new("target/write_float.tsfile", schema, Default::default()).unwrap();

        let result = writer.write("d1", "s1", 0, IoTDBValue::FLOAT(3.141));

        match result {
            Ok(_) => {}
            Err(_) => {
                assert!(false);
            }
        }

        writer.close();
    }

    #[test]
    fn read_var_int() {
        for number in [
            1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 123456789,
        ] {
            let mut result: Vec<u8> = vec![];

            // Write it
            write_var_u32(number, &mut result);
            // Read it back
            let result: u32 = read_var_u32(&mut result.as_slice()).unwrap();

            assert_eq!(number, result);
        }
    }

    #[test]
    fn write_var_int() {
        let number: u32 = 123456789;
        let mut result: Vec<u8> = vec![];
        let position = write_var_u32(number, &mut result).unwrap();

        assert_eq!(position, 4);
        assert_eq!(
            result.as_slice(),
            [0b10010101, 0b10011010, 0b11101111, 0b00111010]
        );
    }

    #[test]
    fn write_var_int_2() {
        let number: u32 = 128;
        let mut result: Vec<u8> = vec![];
        let position = write_var_u32(number, &mut result).unwrap();

        assert_eq!(position, 2);
        assert_eq!(result.as_slice(), [128, 1]);
    }

    #[test]
    fn write_var_int_3() {
        let number: u32 = 13;
        let mut result: Vec<u8> = vec![];
        let position = write_var_u32(number, &mut result).unwrap();

        assert_eq!(position, 1);
        assert_eq!(result.as_slice(), [13]);
    }

    #[test]
    fn pre_write_var_int() {
        let mut number: u32 = 123456789;
        let bytes: [u8; 4] = number.to_be_bytes();
        assert_eq!(bytes, [0b00000111, 0b01011011, 0b11001101, 0b00010101]);

        let mut buffer: Vec<u8> = vec![];

        // Now compress them
        let mut position: u8 = 1;

        while (number & 0xFFFFFF80) != 0 {
            buffer.push(((number & 0x7F) | 0x80) as u8);
            number >>= 7;
            position += 1;
        }

        buffer.push((number & 0x7F) as u8);

        assert_eq!(buffer, [0b10010101, 0b10011010, 0b11101111, 0b00111010]);
        assert_eq!(position, 4);
    }

    #[test]
    fn write_multiple_types() {
        let expected = [
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65, 0x03, 0x00, 0x04, 0x64, 0x31, 0x05, 0x04, 0x73,
            0x31, 0x1C, 0x01, 0x00, 0x00, 0x1A, 0x1A, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x01, 0x1A, 0x05, 0x04, 0x73, 0x32, 0x23, 0x02, 0x00, 0x00, 0x21,
            0x21, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x05, 0x04, 0x73, 0x33, 0x1F, 0x03, 0x00, 0x00,
            0x1D, 0x1D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF,
            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41,
            0x70, 0x00, 0x00, 0x02, 0x00, 0x04, 0x73, 0x31, 0x01, 0x08, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
            0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x0B, 0x00, 0x04, 0x73, 0x32, 0x02, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x0E, 0x40, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x2F, 0x00, 0x04, 0x73, 0x33, 0x03, 0x08, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41,
            0x70, 0x00, 0x00, 0x41, 0x70, 0x00, 0x00, 0x41, 0x70, 0x00, 0x00, 0x41, 0x70, 0x00,
            0x00, 0x40, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x5A, 0x01, 0x04, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37, 0x03, 0x01, 0x04, 0x64, 0x31,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x01, 0x4C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x20, 0x04, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x24, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x21, 0x00, 0x00, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
            0x02, 0x20, 0x80, 0x02, 0x05, 0x00, 0x00, 0x00, 0x41, 0x54, 0x73, 0x46, 0x69, 0x6C,
            0x65,
        ];

        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s1",
                        TSDataType::INT32,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .add(
                        "s2",
                        TSDataType::INT64,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .add(
                        "s3",
                        TSDataType::FLOAT,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let buffer: Vec<u8> = vec![];
        let buffer_writer = WriteWrapper::new(buffer);

        let mut writer =
            TsFileWriter::new_from_writer(schema, buffer_writer, Default::default()).unwrap();

        writer.write("d1", "s1", 1, IoTDBValue::INT(13));
        writer.write("d1", "s2", 1, IoTDBValue::LONG(14));
        writer.write("d1", "s3", 1, IoTDBValue::FLOAT(15.0));

        writer.close();

        // assert_eq!(buffer_writer.writer, expected);
        assert_eq!(writer.file_io_writer.out.position, expected.len() as u64);
    }

    #[test]
    fn write_datapoint_int32() {
        let expected = [
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65, 0x03, 0x00, 0x04, 0x64, 0x31, 0x05, 0x02, 0x73,
            0x1C, 0x01, 0x00, 0x00, 0x1A, 0x1A, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x1A, 0x02, 0x00, 0x02, 0x73, 0x01, 0x08, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
            0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x0B, 0x01, 0x02, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x03, 0x01, 0x04, 0x64, 0x31, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x79, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x20, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
            0x08, 0x80, 0x02, 0x05, 0x00, 0x00, 0x00, 0x41, 0x54, 0x73, 0x46, 0x69, 0x6C, 0x65,
        ];

        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s",
                        TSDataType::INT32,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let buffer: Vec<u8> = vec![];
        let buffer_writer = WriteWrapper::new(buffer);

        let mut writer =
            TsFileWriter::new_from_writer(schema, buffer_writer, Default::default()).unwrap();

        writer.write("d1", "s", 1, IoTDBValue::INT(13));

        writer.close();

        assert_eq!(writer.file_io_writer.out.writer, expected);
    }

    #[test]
    fn write_datapoint_int64() {
        let expected = [
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65, 0x03, 0x00, 0x04, 0x64, 0x31, 0x05, 0x02, 0x73,
            0x23, 0x02, 0x00, 0x00, 0x21, 0x21, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x02, 0x00, 0x02,
            0x73, 0x02, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x2A, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x02,
            0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x7C, 0x03, 0x01, 0x04, 0x64, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x35, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
            0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x02, 0x05, 0x00,
            0x00, 0x00, 0x41, 0x54, 0x73, 0x46, 0x69, 0x6C, 0x65,
        ];

        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s",
                        TSDataType::INT64,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let buffer: Vec<u8> = vec![];
        let buffer_writer = WriteWrapper::new(buffer);

        let mut writer =
            TsFileWriter::new_from_writer(schema, buffer_writer, Default::default()).unwrap();

        writer.write("d1", "s", 1, IoTDBValue::LONG(13));

        writer.close();

        assert_eq!(writer.file_io_writer.out.writer, expected);
    }

    #[test]
    fn write_datapoint_float() {
        let expected = [
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65, 0x03, 0x00, 0x04, 0x64, 0x31, 0x05, 0x02, 0x73,
            0x1F, 0x03, 0x00, 0x00, 0x1D, 0x1D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x41, 0x50, 0x00, 0x00, 0x02, 0x00, 0x02, 0x73, 0x03, 0x08, 0x01,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x01, 0x41, 0x50, 0x00, 0x00, 0x41, 0x50, 0x00, 0x00, 0x41, 0x50, 0x00, 0x00,
            0x41, 0x50, 0x00, 0x00, 0x40, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x02, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0x01, 0x04,
            0x64, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x20,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
            0x00, 0x00, 0x00, 0x08, 0x80, 0x02, 0x05, 0x00, 0x00, 0x00, 0x41, 0x54, 0x73, 0x46,
            0x69, 0x6C, 0x65,
        ];

        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s",
                        TSDataType::FLOAT,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let buffer: Vec<u8> = vec![];
        let buffer_writer = WriteWrapper::new(buffer);

        let mut writer =
            TsFileWriter::new_from_writer(schema, buffer_writer, Default::default()).unwrap();

        writer.write("d1", "s", 1, IoTDBValue::FLOAT(13.0));

        writer.close();

        assert_eq!(writer.file_io_writer.out.writer, expected);
    }

    #[test]
    fn write_datapoint_int32_1000() {
        let expected = [
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65, 0x03, 0x00, 0x04, 0x64, 0x31, 0x05, 0x02, 0x73,
            0xD8, 0x10, 0x01, 0x00, 0x00, 0xD4, 0x10, 0xD4, 0x10, 0xC0, 0x01, 0x00, 0x00, 0x00,
            0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
            0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x83, 0x00, 0x00, 0x00, 0x80, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
            0x85, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x00,
            0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x87, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C,
            0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x28,
            0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E, 0x40, 0x42, 0x44,
            0x46, 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5A, 0x5C, 0x5E, 0x60,
            0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C, 0x6E, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7A, 0x7C,
            0x7E, 0x80, 0x01, 0x82, 0x01, 0x84, 0x01, 0x86, 0x01, 0x88, 0x01, 0x8A, 0x01, 0x8C,
            0x01, 0x8E, 0x01, 0x90, 0x01, 0x92, 0x01, 0x94, 0x01, 0x96, 0x01, 0x98, 0x01, 0x9A,
            0x01, 0x9C, 0x01, 0x9E, 0x01, 0xA0, 0x01, 0xA2, 0x01, 0xA4, 0x01, 0xA6, 0x01, 0xA8,
            0x01, 0xAA, 0x01, 0xAC, 0x01, 0xAE, 0x01, 0xB0, 0x01, 0xB2, 0x01, 0xB4, 0x01, 0xB6,
            0x01, 0xB8, 0x01, 0xBA, 0x01, 0xBC, 0x01, 0xBE, 0x01, 0xC0, 0x01, 0xC2, 0x01, 0xC4,
            0x01, 0xC6, 0x01, 0xC8, 0x01, 0xCA, 0x01, 0xCC, 0x01, 0xCE, 0x01, 0xD0, 0x01, 0xD2,
            0x01, 0xD4, 0x01, 0xD6, 0x01, 0xD8, 0x01, 0xDA, 0x01, 0xDC, 0x01, 0xDE, 0x01, 0xE0,
            0x01, 0xE2, 0x01, 0xE4, 0x01, 0xE6, 0x01, 0xE8, 0x01, 0xEA, 0x01, 0xEC, 0x01, 0xEE,
            0x01, 0xF0, 0x01, 0xF2, 0x01, 0xF4, 0x01, 0xF6, 0x01, 0xF8, 0x01, 0xFA, 0x01, 0xFC,
            0x01, 0xFE, 0x01, 0x80, 0x02, 0x82, 0x02, 0x84, 0x02, 0x86, 0x02, 0x88, 0x02, 0x8A,
            0x02, 0x8C, 0x02, 0x8E, 0x02, 0x90, 0x02, 0x92, 0x02, 0x94, 0x02, 0x96, 0x02, 0x98,
            0x02, 0x9A, 0x02, 0x9C, 0x02, 0x9E, 0x02, 0xA0, 0x02, 0xA2, 0x02, 0xA4, 0x02, 0xA6,
            0x02, 0xA8, 0x02, 0xAA, 0x02, 0xAC, 0x02, 0xAE, 0x02, 0xB0, 0x02, 0xB2, 0x02, 0xB4,
            0x02, 0xB6, 0x02, 0xB8, 0x02, 0xBA, 0x02, 0xBC, 0x02, 0xBE, 0x02, 0xC0, 0x02, 0xC2,
            0x02, 0xC4, 0x02, 0xC6, 0x02, 0xC8, 0x02, 0xCA, 0x02, 0xCC, 0x02, 0xCE, 0x02, 0xD0,
            0x02, 0xD2, 0x02, 0xD4, 0x02, 0xD6, 0x02, 0xD8, 0x02, 0xDA, 0x02, 0xDC, 0x02, 0xDE,
            0x02, 0xE0, 0x02, 0xE2, 0x02, 0xE4, 0x02, 0xE6, 0x02, 0xE8, 0x02, 0xEA, 0x02, 0xEC,
            0x02, 0xEE, 0x02, 0xF0, 0x02, 0xF2, 0x02, 0xF4, 0x02, 0xF6, 0x02, 0xF8, 0x02, 0xFA,
            0x02, 0xFC, 0x02, 0xFE, 0x02, 0x80, 0x03, 0x82, 0x03, 0x84, 0x03, 0x86, 0x03, 0x88,
            0x03, 0x8A, 0x03, 0x8C, 0x03, 0x8E, 0x03, 0x90, 0x03, 0x92, 0x03, 0x94, 0x03, 0x96,
            0x03, 0x98, 0x03, 0x9A, 0x03, 0x9C, 0x03, 0x9E, 0x03, 0xA0, 0x03, 0xA2, 0x03, 0xA4,
            0x03, 0xA6, 0x03, 0xA8, 0x03, 0xAA, 0x03, 0xAC, 0x03, 0xAE, 0x03, 0xB0, 0x03, 0xB2,
            0x03, 0xB4, 0x03, 0xB6, 0x03, 0xB8, 0x03, 0xBA, 0x03, 0xBC, 0x03, 0xBE, 0x03, 0xC0,
            0x03, 0xC2, 0x03, 0xC4, 0x03, 0xC6, 0x03, 0xC8, 0x03, 0xCA, 0x03, 0xCC, 0x03, 0xCE,
            0x03, 0xD0, 0x03, 0xD2, 0x03, 0xD4, 0x03, 0xD6, 0x03, 0xD8, 0x03, 0xDA, 0x03, 0xDC,
            0x03, 0xDE, 0x03, 0xE0, 0x03, 0xE2, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xEA,
            0x03, 0xEC, 0x03, 0xEE, 0x03, 0xF0, 0x03, 0xF2, 0x03, 0xF4, 0x03, 0xF6, 0x03, 0xF8,
            0x03, 0xFA, 0x03, 0xFC, 0x03, 0xFE, 0x03, 0x80, 0x04, 0x82, 0x04, 0x84, 0x04, 0x86,
            0x04, 0x88, 0x04, 0x8A, 0x04, 0x8C, 0x04, 0x8E, 0x04, 0x90, 0x04, 0x92, 0x04, 0x94,
            0x04, 0x96, 0x04, 0x98, 0x04, 0x9A, 0x04, 0x9C, 0x04, 0x9E, 0x04, 0xA0, 0x04, 0xA2,
            0x04, 0xA4, 0x04, 0xA6, 0x04, 0xA8, 0x04, 0xAA, 0x04, 0xAC, 0x04, 0xAE, 0x04, 0xB0,
            0x04, 0xB2, 0x04, 0xB4, 0x04, 0xB6, 0x04, 0xB8, 0x04, 0xBA, 0x04, 0xBC, 0x04, 0xBE,
            0x04, 0xC0, 0x04, 0xC2, 0x04, 0xC4, 0x04, 0xC6, 0x04, 0xC8, 0x04, 0xCA, 0x04, 0xCC,
            0x04, 0xCE, 0x04, 0xD0, 0x04, 0xD2, 0x04, 0xD4, 0x04, 0xD6, 0x04, 0xD8, 0x04, 0xDA,
            0x04, 0xDC, 0x04, 0xDE, 0x04, 0xE0, 0x04, 0xE2, 0x04, 0xE4, 0x04, 0xE6, 0x04, 0xE8,
            0x04, 0xEA, 0x04, 0xEC, 0x04, 0xEE, 0x04, 0xF0, 0x04, 0xF2, 0x04, 0xF4, 0x04, 0xF6,
            0x04, 0xF8, 0x04, 0xFA, 0x04, 0xFC, 0x04, 0xFE, 0x04, 0x80, 0x05, 0x82, 0x05, 0x84,
            0x05, 0x86, 0x05, 0x88, 0x05, 0x8A, 0x05, 0x8C, 0x05, 0x8E, 0x05, 0x90, 0x05, 0x92,
            0x05, 0x94, 0x05, 0x96, 0x05, 0x98, 0x05, 0x9A, 0x05, 0x9C, 0x05, 0x9E, 0x05, 0xA0,
            0x05, 0xA2, 0x05, 0xA4, 0x05, 0xA6, 0x05, 0xA8, 0x05, 0xAA, 0x05, 0xAC, 0x05, 0xAE,
            0x05, 0xB0, 0x05, 0xB2, 0x05, 0xB4, 0x05, 0xB6, 0x05, 0xB8, 0x05, 0xBA, 0x05, 0xBC,
            0x05, 0xBE, 0x05, 0xC0, 0x05, 0xC2, 0x05, 0xC4, 0x05, 0xC6, 0x05, 0xC8, 0x05, 0xCA,
            0x05, 0xCC, 0x05, 0xCE, 0x05, 0xD0, 0x05, 0xD2, 0x05, 0xD4, 0x05, 0xD6, 0x05, 0xD8,
            0x05, 0xDA, 0x05, 0xDC, 0x05, 0xDE, 0x05, 0xE0, 0x05, 0xE2, 0x05, 0xE4, 0x05, 0xE6,
            0x05, 0xE8, 0x05, 0xEA, 0x05, 0xEC, 0x05, 0xEE, 0x05, 0xF0, 0x05, 0xF2, 0x05, 0xF4,
            0x05, 0xF6, 0x05, 0xF8, 0x05, 0xFA, 0x05, 0xFC, 0x05, 0xFE, 0x05, 0x80, 0x06, 0x82,
            0x06, 0x84, 0x06, 0x86, 0x06, 0x88, 0x06, 0x8A, 0x06, 0x8C, 0x06, 0x8E, 0x06, 0x90,
            0x06, 0x92, 0x06, 0x94, 0x06, 0x96, 0x06, 0x98, 0x06, 0x9A, 0x06, 0x9C, 0x06, 0x9E,
            0x06, 0xA0, 0x06, 0xA2, 0x06, 0xA4, 0x06, 0xA6, 0x06, 0xA8, 0x06, 0xAA, 0x06, 0xAC,
            0x06, 0xAE, 0x06, 0xB0, 0x06, 0xB2, 0x06, 0xB4, 0x06, 0xB6, 0x06, 0xB8, 0x06, 0xBA,
            0x06, 0xBC, 0x06, 0xBE, 0x06, 0xC0, 0x06, 0xC2, 0x06, 0xC4, 0x06, 0xC6, 0x06, 0xC8,
            0x06, 0xCA, 0x06, 0xCC, 0x06, 0xCE, 0x06, 0xD0, 0x06, 0xD2, 0x06, 0xD4, 0x06, 0xD6,
            0x06, 0xD8, 0x06, 0xDA, 0x06, 0xDC, 0x06, 0xDE, 0x06, 0xE0, 0x06, 0xE2, 0x06, 0xE4,
            0x06, 0xE6, 0x06, 0xE8, 0x06, 0xEA, 0x06, 0xEC, 0x06, 0xEE, 0x06, 0xF0, 0x06, 0xF2,
            0x06, 0xF4, 0x06, 0xF6, 0x06, 0xF8, 0x06, 0xFA, 0x06, 0xFC, 0x06, 0xFE, 0x06, 0x80,
            0x07, 0x82, 0x07, 0x84, 0x07, 0x86, 0x07, 0x88, 0x07, 0x8A, 0x07, 0x8C, 0x07, 0x8E,
            0x07, 0x90, 0x07, 0x92, 0x07, 0x94, 0x07, 0x96, 0x07, 0x98, 0x07, 0x9A, 0x07, 0x9C,
            0x07, 0x9E, 0x07, 0xA0, 0x07, 0xA2, 0x07, 0xA4, 0x07, 0xA6, 0x07, 0xA8, 0x07, 0xAA,
            0x07, 0xAC, 0x07, 0xAE, 0x07, 0xB0, 0x07, 0xB2, 0x07, 0xB4, 0x07, 0xB6, 0x07, 0xB8,
            0x07, 0xBA, 0x07, 0xBC, 0x07, 0xBE, 0x07, 0xC0, 0x07, 0xC2, 0x07, 0xC4, 0x07, 0xC6,
            0x07, 0xC8, 0x07, 0xCA, 0x07, 0xCC, 0x07, 0xCE, 0x07, 0xD0, 0x07, 0xD2, 0x07, 0xD4,
            0x07, 0xD6, 0x07, 0xD8, 0x07, 0xDA, 0x07, 0xDC, 0x07, 0xDE, 0x07, 0xE0, 0x07, 0xE2,
            0x07, 0xE4, 0x07, 0xE6, 0x07, 0xE8, 0x07, 0xEA, 0x07, 0xEC, 0x07, 0xEE, 0x07, 0xF0,
            0x07, 0xF2, 0x07, 0xF4, 0x07, 0xF6, 0x07, 0xF8, 0x07, 0xFA, 0x07, 0xFC, 0x07, 0xFE,
            0x07, 0x80, 0x08, 0x82, 0x08, 0x84, 0x08, 0x86, 0x08, 0x88, 0x08, 0x8A, 0x08, 0x8C,
            0x08, 0x8E, 0x08, 0x90, 0x08, 0x92, 0x08, 0x94, 0x08, 0x96, 0x08, 0x98, 0x08, 0x9A,
            0x08, 0x9C, 0x08, 0x9E, 0x08, 0xA0, 0x08, 0xA2, 0x08, 0xA4, 0x08, 0xA6, 0x08, 0xA8,
            0x08, 0xAA, 0x08, 0xAC, 0x08, 0xAE, 0x08, 0xB0, 0x08, 0xB2, 0x08, 0xB4, 0x08, 0xB6,
            0x08, 0xB8, 0x08, 0xBA, 0x08, 0xBC, 0x08, 0xBE, 0x08, 0xC0, 0x08, 0xC2, 0x08, 0xC4,
            0x08, 0xC6, 0x08, 0xC8, 0x08, 0xCA, 0x08, 0xCC, 0x08, 0xCE, 0x08, 0xD0, 0x08, 0xD2,
            0x08, 0xD4, 0x08, 0xD6, 0x08, 0xD8, 0x08, 0xDA, 0x08, 0xDC, 0x08, 0xDE, 0x08, 0xE0,
            0x08, 0xE2, 0x08, 0xE4, 0x08, 0xE6, 0x08, 0xE8, 0x08, 0xEA, 0x08, 0xEC, 0x08, 0xEE,
            0x08, 0xF0, 0x08, 0xF2, 0x08, 0xF4, 0x08, 0xF6, 0x08, 0xF8, 0x08, 0xFA, 0x08, 0xFC,
            0x08, 0xFE, 0x08, 0x80, 0x09, 0x82, 0x09, 0x84, 0x09, 0x86, 0x09, 0x88, 0x09, 0x8A,
            0x09, 0x8C, 0x09, 0x8E, 0x09, 0x90, 0x09, 0x92, 0x09, 0x94, 0x09, 0x96, 0x09, 0x98,
            0x09, 0x9A, 0x09, 0x9C, 0x09, 0x9E, 0x09, 0xA0, 0x09, 0xA2, 0x09, 0xA4, 0x09, 0xA6,
            0x09, 0xA8, 0x09, 0xAA, 0x09, 0xAC, 0x09, 0xAE, 0x09, 0xB0, 0x09, 0xB2, 0x09, 0xB4,
            0x09, 0xB6, 0x09, 0xB8, 0x09, 0xBA, 0x09, 0xBC, 0x09, 0xBE, 0x09, 0xC0, 0x09, 0xC2,
            0x09, 0xC4, 0x09, 0xC6, 0x09, 0xC8, 0x09, 0xCA, 0x09, 0xCC, 0x09, 0xCE, 0x09, 0xD0,
            0x09, 0xD2, 0x09, 0xD4, 0x09, 0xD6, 0x09, 0xD8, 0x09, 0xDA, 0x09, 0xDC, 0x09, 0xDE,
            0x09, 0xE0, 0x09, 0xE2, 0x09, 0xE4, 0x09, 0xE6, 0x09, 0xE8, 0x09, 0xEA, 0x09, 0xEC,
            0x09, 0xEE, 0x09, 0xF0, 0x09, 0xF2, 0x09, 0xF4, 0x09, 0xF6, 0x09, 0xF8, 0x09, 0xFA,
            0x09, 0xFC, 0x09, 0xFE, 0x09, 0x80, 0x0A, 0x82, 0x0A, 0x84, 0x0A, 0x86, 0x0A, 0x88,
            0x0A, 0x8A, 0x0A, 0x8C, 0x0A, 0x8E, 0x0A, 0x90, 0x0A, 0x92, 0x0A, 0x94, 0x0A, 0x96,
            0x0A, 0x98, 0x0A, 0x9A, 0x0A, 0x9C, 0x0A, 0x9E, 0x0A, 0xA0, 0x0A, 0xA2, 0x0A, 0xA4,
            0x0A, 0xA6, 0x0A, 0xA8, 0x0A, 0xAA, 0x0A, 0xAC, 0x0A, 0xAE, 0x0A, 0xB0, 0x0A, 0xB2,
            0x0A, 0xB4, 0x0A, 0xB6, 0x0A, 0xB8, 0x0A, 0xBA, 0x0A, 0xBC, 0x0A, 0xBE, 0x0A, 0xC0,
            0x0A, 0xC2, 0x0A, 0xC4, 0x0A, 0xC6, 0x0A, 0xC8, 0x0A, 0xCA, 0x0A, 0xCC, 0x0A, 0xCE,
            0x0A, 0xD0, 0x0A, 0xD2, 0x0A, 0xD4, 0x0A, 0xD6, 0x0A, 0xD8, 0x0A, 0xDA, 0x0A, 0xDC,
            0x0A, 0xDE, 0x0A, 0xE0, 0x0A, 0xE2, 0x0A, 0xE4, 0x0A, 0xE6, 0x0A, 0xE8, 0x0A, 0xEA,
            0x0A, 0xEC, 0x0A, 0xEE, 0x0A, 0xF0, 0x0A, 0xF2, 0x0A, 0xF4, 0x0A, 0xF6, 0x0A, 0xF8,
            0x0A, 0xFA, 0x0A, 0xFC, 0x0A, 0xFE, 0x0A, 0x80, 0x0B, 0x82, 0x0B, 0x84, 0x0B, 0x86,
            0x0B, 0x88, 0x0B, 0x8A, 0x0B, 0x8C, 0x0B, 0x8E, 0x0B, 0x90, 0x0B, 0x92, 0x0B, 0x94,
            0x0B, 0x96, 0x0B, 0x98, 0x0B, 0x9A, 0x0B, 0x9C, 0x0B, 0x9E, 0x0B, 0xA0, 0x0B, 0xA2,
            0x0B, 0xA4, 0x0B, 0xA6, 0x0B, 0xA8, 0x0B, 0xAA, 0x0B, 0xAC, 0x0B, 0xAE, 0x0B, 0xB0,
            0x0B, 0xB2, 0x0B, 0xB4, 0x0B, 0xB6, 0x0B, 0xB8, 0x0B, 0xBA, 0x0B, 0xBC, 0x0B, 0xBE,
            0x0B, 0xC0, 0x0B, 0xC2, 0x0B, 0xC4, 0x0B, 0xC6, 0x0B, 0xC8, 0x0B, 0xCA, 0x0B, 0xCC,
            0x0B, 0xCE, 0x0B, 0xD0, 0x0B, 0xD2, 0x0B, 0xD4, 0x0B, 0xD6, 0x0B, 0xD8, 0x0B, 0xDA,
            0x0B, 0xDC, 0x0B, 0xDE, 0x0B, 0xE0, 0x0B, 0xE2, 0x0B, 0xE4, 0x0B, 0xE6, 0x0B, 0xE8,
            0x0B, 0xEA, 0x0B, 0xEC, 0x0B, 0xEE, 0x0B, 0xF0, 0x0B, 0xF2, 0x0B, 0xF4, 0x0B, 0xF6,
            0x0B, 0xF8, 0x0B, 0xFA, 0x0B, 0xFC, 0x0B, 0xFE, 0x0B, 0x80, 0x0C, 0x82, 0x0C, 0x84,
            0x0C, 0x86, 0x0C, 0x88, 0x0C, 0x8A, 0x0C, 0x8C, 0x0C, 0x8E, 0x0C, 0x90, 0x0C, 0x92,
            0x0C, 0x94, 0x0C, 0x96, 0x0C, 0x98, 0x0C, 0x9A, 0x0C, 0x9C, 0x0C, 0x9E, 0x0C, 0xA0,
            0x0C, 0xA2, 0x0C, 0xA4, 0x0C, 0xA6, 0x0C, 0xA8, 0x0C, 0xAA, 0x0C, 0xAC, 0x0C, 0xAE,
            0x0C, 0xB0, 0x0C, 0xB2, 0x0C, 0xB4, 0x0C, 0xB6, 0x0C, 0xB8, 0x0C, 0xBA, 0x0C, 0xBC,
            0x0C, 0xBE, 0x0C, 0xC0, 0x0C, 0xC2, 0x0C, 0xC4, 0x0C, 0xC6, 0x0C, 0xC8, 0x0C, 0xCA,
            0x0C, 0xCC, 0x0C, 0xCE, 0x0C, 0xD0, 0x0C, 0xD2, 0x0C, 0xD4, 0x0C, 0xD6, 0x0C, 0xD8,
            0x0C, 0xDA, 0x0C, 0xDC, 0x0C, 0xDE, 0x0C, 0xE0, 0x0C, 0xE2, 0x0C, 0xE4, 0x0C, 0xE6,
            0x0C, 0xE8, 0x0C, 0xEA, 0x0C, 0xEC, 0x0C, 0xEE, 0x0C, 0xF0, 0x0C, 0xF2, 0x0C, 0xF4,
            0x0C, 0xF6, 0x0C, 0xF8, 0x0C, 0xFA, 0x0C, 0xFC, 0x0C, 0xFE, 0x0C, 0x80, 0x0D, 0x82,
            0x0D, 0x84, 0x0D, 0x86, 0x0D, 0x88, 0x0D, 0x8A, 0x0D, 0x8C, 0x0D, 0x8E, 0x0D, 0x90,
            0x0D, 0x92, 0x0D, 0x94, 0x0D, 0x96, 0x0D, 0x98, 0x0D, 0x9A, 0x0D, 0x9C, 0x0D, 0x9E,
            0x0D, 0xA0, 0x0D, 0xA2, 0x0D, 0xA4, 0x0D, 0xA6, 0x0D, 0xA8, 0x0D, 0xAA, 0x0D, 0xAC,
            0x0D, 0xAE, 0x0D, 0xB0, 0x0D, 0xB2, 0x0D, 0xB4, 0x0D, 0xB6, 0x0D, 0xB8, 0x0D, 0xBA,
            0x0D, 0xBC, 0x0D, 0xBE, 0x0D, 0xC0, 0x0D, 0xC2, 0x0D, 0xC4, 0x0D, 0xC6, 0x0D, 0xC8,
            0x0D, 0xCA, 0x0D, 0xCC, 0x0D, 0xCE, 0x0D, 0xD0, 0x0D, 0xD2, 0x0D, 0xD4, 0x0D, 0xD6,
            0x0D, 0xD8, 0x0D, 0xDA, 0x0D, 0xDC, 0x0D, 0xDE, 0x0D, 0xE0, 0x0D, 0xE2, 0x0D, 0xE4,
            0x0D, 0xE6, 0x0D, 0xE8, 0x0D, 0xEA, 0x0D, 0xEC, 0x0D, 0xEE, 0x0D, 0xF0, 0x0D, 0xF2,
            0x0D, 0xF4, 0x0D, 0xF6, 0x0D, 0xF8, 0x0D, 0xFA, 0x0D, 0xFC, 0x0D, 0xFE, 0x0D, 0x80,
            0x0E, 0x82, 0x0E, 0x84, 0x0E, 0x86, 0x0E, 0x88, 0x0E, 0x8A, 0x0E, 0x8C, 0x0E, 0x8E,
            0x0E, 0x90, 0x0E, 0x92, 0x0E, 0x94, 0x0E, 0x96, 0x0E, 0x98, 0x0E, 0x9A, 0x0E, 0x9C,
            0x0E, 0x9E, 0x0E, 0xA0, 0x0E, 0xA2, 0x0E, 0xA4, 0x0E, 0xA6, 0x0E, 0xA8, 0x0E, 0xAA,
            0x0E, 0xAC, 0x0E, 0xAE, 0x0E, 0xB0, 0x0E, 0xB2, 0x0E, 0xB4, 0x0E, 0xB6, 0x0E, 0xB8,
            0x0E, 0xBA, 0x0E, 0xBC, 0x0E, 0xBE, 0x0E, 0xC0, 0x0E, 0xC2, 0x0E, 0xC4, 0x0E, 0xC6,
            0x0E, 0xC8, 0x0E, 0xCA, 0x0E, 0xCC, 0x0E, 0xCE, 0x0E, 0xD0, 0x0E, 0xD2, 0x0E, 0xD4,
            0x0E, 0xD6, 0x0E, 0xD8, 0x0E, 0xDA, 0x0E, 0xDC, 0x0E, 0xDE, 0x0E, 0xE0, 0x0E, 0xE2,
            0x0E, 0xE4, 0x0E, 0xE6, 0x0E, 0xE8, 0x0E, 0xEA, 0x0E, 0xEC, 0x0E, 0xEE, 0x0E, 0xF0,
            0x0E, 0xF2, 0x0E, 0xF4, 0x0E, 0xF6, 0x0E, 0xF8, 0x0E, 0xFA, 0x0E, 0xFC, 0x0E, 0xFE,
            0x0E, 0x80, 0x0F, 0x82, 0x0F, 0x84, 0x0F, 0x86, 0x0F, 0x88, 0x0F, 0x8A, 0x0F, 0x8C,
            0x0F, 0x8E, 0x0F, 0x90, 0x0F, 0x92, 0x0F, 0x94, 0x0F, 0x96, 0x0F, 0x98, 0x0F, 0x9A,
            0x0F, 0x9C, 0x0F, 0x9E, 0x0F, 0xA0, 0x0F, 0xA2, 0x0F, 0xA4, 0x0F, 0xA6, 0x0F, 0xA8,
            0x0F, 0xAA, 0x0F, 0xAC, 0x0F, 0xAE, 0x0F, 0xB0, 0x0F, 0xB2, 0x0F, 0xB4, 0x0F, 0xB6,
            0x0F, 0xB8, 0x0F, 0xBA, 0x0F, 0xBC, 0x0F, 0xBE, 0x0F, 0xC0, 0x0F, 0xC2, 0x0F, 0xC4,
            0x0F, 0xC6, 0x0F, 0xC8, 0x0F, 0xCA, 0x0F, 0xCC, 0x0F, 0xCE, 0x0F, 0xD0, 0x0F, 0x02,
            0x00, 0x02, 0x73, 0x01, 0x08, 0xE9, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x07, 0xA3, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x01,
            0x02, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x6C, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x08, 0xA3, 0x03, 0x01, 0x04, 0x64, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x08, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xB7, 0x01, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x08, 0x6B, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x02, 0x05,
            0x00, 0x00, 0x00, 0x41, 0x54, 0x73, 0x46, 0x69, 0x6C, 0x65,
        ];

        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s",
                        TSDataType::INT32,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let buffer: Vec<u8> = vec![];
        let buffer_writer = WriteWrapper::new(buffer);

        let mut writer =
            TsFileWriter::new_from_writer(schema, buffer_writer, Default::default()).unwrap();

        for i in 0..1001 {
            writer.write("d1", "s", i, IoTDBValue::INT(i as i32));
        }

        writer.close();

        assert_eq!(writer.file_io_writer.out.writer, expected);
    }

    #[test]
    fn write_datapoint_int64_10000() {
        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s",
                        TSDataType::INT64,
                        TSEncoding::PLAIN,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let mut writer =
            TsFileWriter::new("target/10000_int64.tsfile", schema, Default::default()).unwrap();

        for i in 0..10001 {
            writer.write("d1", "s", i, IoTDBValue::LONG(2 * i));
        }

        writer.close();
    }

    #[test]
    fn write_out_of_order_data() -> Result<(), TsFileError> {
        let schema = Schema::simple(
            "d1",
            "s1",
            TSDataType::INT64,
            TSEncoding::PLAIN,
            CompressionType::UNCOMPRESSED,
        );

        let mut writer = TsFileWriter::new("target/test.tsfile", schema, Default::default())?;

        writer.write("d1", "s1", 1, IoTDBValue::LONG(1))?;
        let result = writer.write("d1", "s1", 1, IoTDBValue::LONG(1));

        assert_eq!(Some(TsFileError::OutOfOrderData), result.err());

        Ok(())
    }

    #[test]
    fn write_i64_snappy() {
        let expected = [
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65, 0x03, 0x00, 0x04, 0x64, 0x31, 0x05, 0x04, 0x73,
            0x31, 0x19, 0x02, 0x01, 0x00, 0x21, 0x17, 0x21, 0x04, 0x18, 0x00, 0x0D, 0x01, 0x04,
            0x7F, 0xFF, 0x09, 0x01, 0x0D, 0x0F, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x0D, 0x02, 0x00, 0x04, 0x73, 0x31, 0x02, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x0D, 0x40, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x0B, 0x01, 0x04, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x03, 0x01, 0x04, 0x64,
            0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x1F, 0x04,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
            0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x02, 0x80, 0x02, 0x05, 0x00, 0x00, 0x00, 0x40, 0x54, 0x73, 0x46, 0x69, 0x6C,
            0x65,
        ];
        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s1",
                        TSDataType::INT64,
                        TSEncoding::PLAIN,
                        CompressionType::SNAPPY,
                    )
                    .build(),
            )
            .build();

        let buffer: Vec<u8> = Vec::new();

        let mut writer = TsFileWriter::new_from_writer(schema, buffer, Default::default()).unwrap();

        writer.write("d1", "s1", 1, IoTDBValue::LONG(13));
        writer.close();

        assert_eq!(expected, writer.file_io_writer.out.as_slice());
    }

    #[test]
    fn write_i64_ts2diff() -> Result<(), TsFileError> {
        let expected = [
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65, 0x03, 0x00, 0x04, 0x64, 0x31, 0x05, 0x04, 0x73,
            0x31, 0x33, 0x02, 0x00, 0x04, 0x31, 0x31, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x02, 0x00, 0x04, 0x73, 0x31, 0x02, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
            0x40, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x0B, 0x01, 0x04, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x03, 0x01, 0x04, 0x64, 0x31, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0xA3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1F, 0x04, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
            0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
            0x80, 0x02, 0x05, 0x00, 0x00, 0x00, 0x40, 0x54, 0x73, 0x46, 0x69, 0x6C, 0x65,
        ];
        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s1",
                        TSDataType::INT64,
                        TSEncoding::TS2DIFF,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let buffer: Vec<u8> = Vec::new();

        let mut writer = TsFileWriter::new_from_writer(schema, buffer, Default::default()).unwrap();

        for i in 0..10 {
            writer.write("d1", "s1", i, IoTDBValue::LONG(i))?;
        }
        writer.close();

        assert_eq!(expected, writer.file_io_writer.out.as_slice());

        Ok(())
    }

    #[test]
    fn write_i32_ts2diff() -> Result<(), TsFileError> {
        let expected = [
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65, 0x03, 0x00, 0x04, 0x64, 0x31, 0x05, 0x04, 0x73,
            0x31, 0x2B, 0x01, 0x00, 0x04, 0x29, 0x29, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x73, 0x31, 0x01, 0x08, 0x0A,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x04, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x03, 0x01,
            0x04, 0x64, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x8B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E,
            0x1F, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x05, 0x00, 0x00, 0x00, 0x40, 0x54, 0x73, 0x46,
            0x69, 0x6C, 0x65,
        ];
        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s1",
                        TSDataType::INT32,
                        TSEncoding::TS2DIFF,
                        CompressionType::UNCOMPRESSED,
                    )
                    .build(),
            )
            .build();

        let buffer: Vec<u8> = Vec::new();

        let mut writer = TsFileWriter::new_from_writer(schema, buffer, Default::default()).unwrap();

        for i in 0..10 {
            writer.write("d1", "s1", i, IoTDBValue::INT(i as i32))?;
        }
        writer.close();

        assert_eq!(expected, writer.file_io_writer.out.as_slice());

        Ok(())
    }

    #[test]
    #[ignore = "Is luck dependent due to HashMap"]
    fn write_snappy_complex() {
        let expected = [
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65, 0x03, 0x00, 0x04, 0x64, 0x31, 0x05, 0x04, 0x73,
            0x31, 0x19, 0x02, 0x01, 0x00, 0x21, 0x17, 0x21, 0x04, 0x18, 0x00, 0x0D, 0x01, 0x04,
            0x7F, 0xFF, 0x09, 0x01, 0x0D, 0x0F, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x0D, 0x05, 0x04, 0x73, 0x32, 0x1A, 0x03, 0x01, 0x00, 0x1D, 0x18, 0x1D, 0x04,
            0x18, 0x00, 0x0D, 0x01, 0x04, 0x7F, 0xFF, 0x09, 0x01, 0x2C, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x01, 0x41, 0x60, 0x00, 0x00, 0x00, 0x04, 0x64, 0x32, 0x05, 0x04,
            0x73, 0x31, 0x1A, 0x01, 0x01, 0x00, 0x1A, 0x18, 0x1A, 0x04, 0x18, 0x00, 0x0D, 0x01,
            0x40, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x01, 0x1E, 0x02, 0x00, 0x04, 0x73, 0x31, 0x02, 0x08, 0x01, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x0D, 0x40, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x04, 0x73, 0x32, 0x03, 0x08, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x01, 0x41, 0x60, 0x00, 0x00, 0x41, 0x60, 0x00, 0x00, 0x41, 0x60, 0x00, 0x00, 0x41,
            0x60, 0x00, 0x00, 0x40, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x04, 0x73, 0x31, 0x01, 0x08, 0x01, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
            0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00,
            0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x52, 0x01, 0x04, 0x73, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x03, 0x01, 0x04, 0x73,
            0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x01, 0x2A, 0x03, 0x02, 0x04, 0x64, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x01, 0x2A, 0x04, 0x64, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3F, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x74, 0x20, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x80,
            0x00, 0x00, 0x08, 0x01, 0x00, 0x21, 0x40, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x02, 0x04, 0x00, 0x00, 0x02, 0x20, 0x80, 0x02, 0x05, 0x00, 0x00, 0x00, 0x4C,
            0x54, 0x73, 0x46, 0x69, 0x6C, 0x65,
        ];
        let schema = TsFileSchemaBuilder::new()
            .add(
                "d1",
                DeviceBuilder::new()
                    .add(
                        "s1",
                        TSDataType::INT64,
                        TSEncoding::PLAIN,
                        CompressionType::SNAPPY,
                    )
                    .add(
                        "s2",
                        TSDataType::FLOAT,
                        TSEncoding::PLAIN,
                        CompressionType::SNAPPY,
                    )
                    .build(),
            )
            .add(
                "d2",
                DeviceBuilder::new()
                    .add(
                        "s1",
                        TSDataType::INT32,
                        TSEncoding::PLAIN,
                        CompressionType::SNAPPY,
                    )
                    .build(),
            )
            .build();

        let buffer: Vec<u8> = Vec::new();

        let mut writer = TsFileWriter::new_from_writer(schema, buffer, Default::default()).unwrap();

        writer.write("d1", "s1", 1, IoTDBValue::LONG(13));
        writer.write("d1", "s2", 1, IoTDBValue::FLOAT(14.0));
        writer.write("d2", "s1", 1, IoTDBValue::INT(15));
        writer.close();

        assert_eq!(expected, writer.file_io_writer.out.as_slice());
    }

    #[test]
    fn use_ts2diff() -> Result<(), TsFileError> {
        let schema = Schema::simple(
            "d1",
            "s1",
            TSDataType::INT64,
            TSEncoding::TS2DIFF,
            CompressionType::UNCOMPRESSED,
        );

        let mut writer = TsFileWriter::new("target/test.tsfile", schema, Default::default())?;

        writer.write("d1", "s1", 1, IoTDBValue::LONG(1))?;

        writer.close();

        Ok(())
    }
}

pub const ONLY_ONE_PAGE_CHUNK_HEADER: u8 = 5;
pub const CHUNK_HEADER: u8 = 1;