flatdata 0.1.4

Rust implementation of heremaps/flatdata
Documentation
#![cfg(test)]

use std::convert;
use std::mem;
use std::slice;

use archive::{Index, IndexMut, Struct, StructMut, VariadicStruct};
use handle::HandleMut;
use memory;

#[derive(Clone, Debug, PartialEq)]
pub struct Idx {
    data: *const u8,
}

impl Struct for Idx {
    const SCHEMA: &'static str = "Index";
    const SIZE_IN_BYTES: usize = 4;
    type Mut = IdxMut;
    fn as_ptr(&self) -> *const u8 {
        self.data
    }
}

impl convert::From<*const u8> for Idx {
    fn from(data: *const u8) -> Self {
        Self { data }
    }
}

impl Index for Idx {
    type IndexMut = IdxMut;
    fn value(&self) -> usize {
        read_bytes!(u64, self.data, 0, 32) as usize
    }
}

#[derive(Debug)]
pub struct IdxMut {
    data: *mut u8,
}

impl convert::From<*mut u8> for IdxMut {
    fn from(data: *mut u8) -> Self {
        Self { data }
    }
}

impl StructMut for IdxMut {
    type Const = Idx;
    fn as_mut_ptr(&mut self) -> *mut u8 {
        self.data
    }
}

impl AsRef<Idx> for IdxMut {
    fn as_ref(&self) -> &Idx {
        unsafe { mem::transmute(self) }
    }
}

impl IndexMut for IdxMut {
    fn set_value(&mut self, value: usize) {
        let buffer = unsafe { slice::from_raw_parts_mut(self.data, Self::Const::SIZE_IN_BYTES) };
        write_bytes!(u32; value as u32, buffer, 0, 32);
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct A {
    data: *const u8,
}

impl A {
    pub fn x(&self) -> u32 {
        read_bytes!(u32, self.data, 0, 16)
    }

    pub fn y(&self) -> u32 {
        read_bytes!(u32, self.data, 16, 16)
    }
}

impl convert::From<*const u8> for A {
    fn from(data: *const u8) -> Self {
        Self { data }
    }
}

impl Struct for A {
    const SCHEMA: &'static str = "struct A { }";
    const SIZE_IN_BYTES: usize = 4;
    type Mut = AMut;
    fn as_ptr(&self) -> *const u8 {
        self.data
    }
}

#[derive(Debug)]
pub struct AMut {
    data: *mut u8,
}

impl AMut {
    pub fn x(&self) -> u32 {
        read_bytes!(u32, self.data, 0, 16)
    }

    pub fn y(&self) -> u32 {
        read_bytes!(u32, self.data, 16, 16)
    }

    pub fn set_x(&mut self, value: u32) {
        let buffer = unsafe {
            slice::from_raw_parts_mut(self.data, <Self as StructMut>::Const::SIZE_IN_BYTES)
        };
        write_bytes!(u32; value, buffer, 0, 16);
    }

    pub fn set_y(&mut self, value: u32) {
        let buffer = unsafe {
            slice::from_raw_parts_mut(self.data, <Self as StructMut>::Const::SIZE_IN_BYTES)
        };
        write_bytes!(u32; value, buffer, 16, 16);
    }
}

impl convert::From<*mut u8> for AMut {
    fn from(data: *mut u8) -> Self {
        Self { data }
    }
}

impl AsRef<A> for AMut {
    fn as_ref(&self) -> &A {
        unsafe { mem::transmute(self) }
    }
}

impl StructMut for AMut {
    type Const = A;
    fn as_mut_ptr(&mut self) -> *mut u8 {
        self.data
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Variant {
    A(A),
}

impl convert::From<(u8, *const u8)> for Variant {
    fn from((type_index, data): (u8, *const u8)) -> Variant {
        match type_index {
            0 => Variant::A(A::from(data)),
            _ => panic!("invalid index"),
        }
    }
}

impl VariadicStruct for Variant {
    type ItemBuilder = VariantBuilder;
    fn size_in_bytes(&self) -> usize {
        match *self {
            Variant::A(_) => A::SIZE_IN_BYTES,
        }
    }
}

pub struct VariantBuilder {
    data: *mut Vec<u8>,
}

impl VariantBuilder {
    pub fn add_a(&mut self) -> HandleMut<<A as Struct>::Mut> {
        let data = unsafe { &mut *self.data };
        let old_len = data.len();
        let increment = 1 + A::SIZE_IN_BYTES;
        data.resize(old_len + increment, 0);
        data[old_len - memory::PADDING_SIZE] = 0;
        HandleMut::new(<A as Struct>::Mut::from(
            &mut data[1 + old_len - memory::PADDING_SIZE] as *mut _,
        ))
    }
}

impl convert::From<*mut Vec<u8>> for VariantBuilder {
    fn from(data: *mut Vec<u8>) -> Self {
        Self { data }
    }
}