use crate::grimoire::io::{Mapper, Reader, Writer};
pub struct Vector<T: Copy> {
data: Vec<T>,
fixed: bool,
}
impl<T: Copy> Vector<T> {
#[inline]
pub fn new() -> Self {
Vector {
data: Vec::new(),
fixed: false,
}
}
#[inline]
pub fn push_back(&mut self, value: T) {
assert!(!self.fixed, "Cannot modify fixed vector");
self.data.push(value);
}
#[inline]
pub fn pop_back(&mut self) {
assert!(!self.fixed, "Cannot modify fixed vector");
assert!(!self.data.is_empty(), "Cannot pop from empty vector");
self.data.pop();
}
#[inline]
pub fn resize(&mut self, size: usize, value: T) {
assert!(!self.fixed, "Cannot modify fixed vector");
self.data.resize(size, value);
}
#[inline]
pub fn reserve(&mut self, capacity: usize) {
assert!(!self.fixed, "Cannot modify fixed vector");
self.data.reserve(capacity);
}
#[inline]
pub fn shrink(&mut self) {
assert!(!self.fixed, "Cannot modify fixed vector");
self.data.shrink_to_fit();
}
#[inline]
pub fn fix(&mut self) {
self.fixed = true;
}
#[inline]
pub fn size(&self) -> usize {
self.data.len()
}
#[inline]
pub fn capacity(&self) -> usize {
self.data.capacity()
}
#[inline]
pub fn empty(&self) -> bool {
self.data.is_empty()
}
#[inline]
pub fn fixed(&self) -> bool {
self.fixed
}
#[inline]
pub fn total_size(&self) -> usize {
std::mem::size_of::<T>() * self.data.len()
}
#[inline]
pub fn io_size(&self) -> usize {
std::mem::size_of::<u64>() + ((self.total_size() + 7) & !0x07)
}
#[inline]
pub fn get(&self, index: usize) -> Option<&T> {
self.data.get(index)
}
#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
assert!(!self.fixed, "Cannot modify fixed vector");
self.data.get_mut(index)
}
#[inline]
pub fn back(&self) -> Option<&T> {
self.data.last()
}
#[inline]
pub fn back_mut(&mut self) -> Option<&mut T> {
assert!(!self.fixed, "Cannot modify fixed vector");
self.data.last_mut()
}
#[inline]
pub fn as_slice(&self) -> &[T] {
&self.data
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
assert!(!self.fixed, "Cannot modify fixed vector");
&mut self.data
}
#[inline]
pub fn clear(&mut self) {
*self = Vector::new();
}
#[inline]
pub fn swap(&mut self, other: &mut Vector<T>) {
std::mem::swap(&mut self.data, &mut other.data);
std::mem::swap(&mut self.fixed, &mut other.fixed);
}
pub fn map(&mut self, mapper: &mut Mapper) -> std::io::Result<()> {
let total_size: u64 = mapper.map_value()?;
let elem_size = std::mem::size_of::<T>();
if elem_size == 0 {
self.fixed = true;
return Ok(()); }
let num_elements = (total_size as usize) / elem_size;
self.data.clear();
self.data.reserve(num_elements);
#[allow(clippy::uninit_vec)]
unsafe {
self.data.set_len(num_elements);
}
if num_elements > 0 {
mapper.map_slice(&mut self.data[..])?;
}
let padding = ((8 - (total_size % 8)) % 8) as usize;
if padding > 0 {
mapper.seek(padding)?;
}
self.fixed = true;
Ok(())
}
pub fn read(&mut self, reader: &mut Reader) -> std::io::Result<()> {
let total_size: u64 = reader.read()?;
let elem_size = std::mem::size_of::<T>();
if elem_size == 0 {
return Ok(()); }
let size = (total_size as usize) / elem_size;
self.data.clear();
self.data.reserve(size);
#[allow(clippy::uninit_vec)]
unsafe {
self.data.set_len(size);
}
if size > 0 {
reader.read_slice(&mut self.data[..])?;
}
let padding = ((8 - (total_size % 8)) % 8) as usize;
if padding > 0 {
reader.seek(padding)?;
}
Ok(())
}
pub fn write(&self, writer: &mut Writer) -> std::io::Result<()> {
let total = self.total_size() as u64;
writer.write(&total)?;
if !self.data.is_empty() {
writer.write_slice(&self.data[..])?;
}
let padding = ((8 - (total % 8)) % 8) as usize;
if padding > 0 {
writer.seek(padding)?;
}
Ok(())
}
}
impl<T: Copy> Default for Vector<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Copy> std::ops::Index<usize> for Vector<T> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.data[index]
}
}
impl<T: Copy> std::ops::IndexMut<usize> for Vector<T> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
assert!(!self.fixed, "Cannot modify fixed vector");
&mut self.data[index]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vector_new() {
let vec: Vector<i32> = Vector::new();
assert_eq!(vec.size(), 0);
assert!(vec.empty());
}
#[test]
fn test_vector_push_pop() {
let mut vec = Vector::new();
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
assert_eq!(vec.size(), 3);
assert_eq!(vec[0], 1);
assert_eq!(vec[1], 2);
assert_eq!(vec[2], 3);
vec.pop_back();
assert_eq!(vec.size(), 2);
}
#[test]
fn test_vector_resize() {
let mut vec = Vector::new();
vec.resize(5, 42);
assert_eq!(vec.size(), 5);
for i in 0..5 {
assert_eq!(vec[i], 42);
}
}
#[test]
fn test_vector_fix() {
let mut vec = Vector::new();
vec.push_back(1);
vec.fix();
assert!(vec.fixed());
}
#[test]
#[should_panic(expected = "Cannot modify fixed vector")]
fn test_vector_fixed_push() {
let mut vec = Vector::new();
vec.fix();
vec.push_back(1);
}
#[test]
fn test_vector_write_read() {
use crate::grimoire::io::{Reader, Writer};
let mut vec = Vector::new();
vec.push_back(1u32);
vec.push_back(2u32);
vec.push_back(3u32);
let mut writer = Writer::from_vec(Vec::new());
vec.write(&mut writer).unwrap();
let data = writer.into_inner().unwrap();
let mut reader = Reader::from_bytes(&data);
let mut vec2: Vector<u32> = Vector::new();
vec2.read(&mut reader).unwrap();
assert_eq!(vec2.size(), 3);
assert_eq!(vec2[0], 1);
assert_eq!(vec2[1], 2);
assert_eq!(vec2[2], 3);
}
#[test]
fn test_vector_write_read_empty() {
use crate::grimoire::io::{Reader, Writer};
let vec: Vector<u64> = Vector::new();
let mut writer = Writer::from_vec(Vec::new());
vec.write(&mut writer).unwrap();
let data = writer.into_inner().unwrap();
let mut reader = Reader::from_bytes(&data);
let mut vec2: Vector<u64> = Vector::new();
vec2.read(&mut reader).unwrap();
assert_eq!(vec2.size(), 0);
assert!(vec2.empty());
}
#[test]
fn test_vector_write_alignment() {
use crate::grimoire::io::Writer;
let mut vec = Vector::new();
vec.push_back(1u8);
vec.push_back(2u8);
vec.push_back(3u8);
let mut writer = Writer::from_vec(Vec::new());
vec.write(&mut writer).unwrap();
let data = writer.into_inner().unwrap();
assert_eq!(data.len(), 16);
let total_size = u64::from_le_bytes([
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
]);
assert_eq!(total_size, 3);
assert_eq!(data[8], 1);
assert_eq!(data[9], 2);
assert_eq!(data[10], 3);
assert_eq!(data[11], 0);
assert_eq!(data[12], 0);
assert_eq!(data[13], 0);
assert_eq!(data[14], 0);
assert_eq!(data[15], 0);
}
}