#[derive(Debug, Clone)]
pub struct WriteBuffer {
buffer: Vec<u8>,
size: usize,
offset: usize,
}
impl Default for WriteBuffer {
fn default() -> Self {
Self::new()
}
}
impl WriteBuffer {
#[must_use]
pub fn new() -> Self {
Self {
buffer: Vec::new(),
size: 0,
offset: 0,
}
}
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
Self {
buffer: vec![0; capacity],
size: 0,
offset: 0,
}
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.size == 0
}
#[must_use]
pub fn data(&self) -> &[u8] {
&self.buffer[..self.size]
}
#[must_use]
pub fn capacity(&self) -> usize {
self.buffer.len()
}
#[must_use]
pub const fn size(&self) -> usize {
self.size
}
#[must_use]
pub const fn offset(&self) -> usize {
self.offset
}
pub fn set_size(&mut self, size: usize) {
self.size = size;
}
pub fn attach_new(&mut self) {
self.buffer = Vec::new();
self.size = 0;
self.offset = 0;
}
pub fn attach_capacity(&mut self, capacity: usize) {
self.buffer = vec![0; capacity];
self.size = 0;
self.offset = 0;
}
pub fn attach_buffer(&mut self, buffer: &[u8], offset: usize, size: usize) {
assert!(!buffer.is_empty(), "Invalid buffer!");
assert!(size > 0, "Invalid size!");
assert!(offset <= size, "Invalid offset!");
self.buffer = buffer.to_vec();
self.size = size;
self.offset = offset;
}
pub fn allocate(&mut self, size: usize) -> usize {
let offset = self.size;
let total = self.size + size;
if total > self.buffer.len() {
let new_capacity = total.max(self.buffer.len() * 2);
self.buffer.resize(new_capacity, 0);
}
self.size = total;
offset
}
pub fn remove(&mut self, offset: usize, size: usize) {
assert!(offset + size <= self.buffer.len(), "Invalid offset & size!");
self.buffer.drain(offset..offset + size);
self.size -= size;
if self.offset >= offset + size {
self.offset -= size;
} else if self.offset >= offset {
self.offset -= self.offset - offset;
if self.offset > self.size {
self.offset = self.size;
}
}
}
pub fn reserve(&mut self, capacity: usize) {
if capacity > self.buffer.len() {
let new_capacity = capacity.max(self.buffer.len() * 2);
self.buffer.resize(new_capacity, 0);
}
}
pub fn resize(&mut self, size: usize) {
self.reserve(size);
self.size = size;
if self.offset > self.size {
self.offset = self.size;
}
}
pub fn reset(&mut self) {
self.size = 0;
self.offset = 0;
}
pub fn shift(&mut self, offset: usize) {
self.offset += offset;
}
pub fn unshift(&mut self, offset: usize) {
self.offset -= offset;
}
#[inline]
pub fn write_byte(&mut self, offset: usize, value: u8) {
self.write_u8(offset, value);
}
#[inline]
pub fn write_char(&mut self, offset: usize, value: u8) {
self.buffer[self.offset + offset] = value;
}
#[inline]
pub fn write_wchar(&mut self, offset: usize, value: u32) {
self.write_u32(offset, value);
}
#[inline]
pub fn write_bool(&mut self, offset: usize, value: bool) {
self.buffer[self.offset + offset] = value as u8;
}
#[inline]
pub fn write_i8(&mut self, offset: usize, value: i8) {
self.buffer[self.offset + offset] = value as u8;
}
#[inline]
pub fn write_u8(&mut self, offset: usize, value: u8) {
self.buffer[self.offset + offset] = value;
}
#[inline]
pub fn write_i16(&mut self, offset: usize, value: i16) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 2].copy_from_slice(&bytes);
}
#[inline]
pub fn write_u16(&mut self, offset: usize, value: u16) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 2].copy_from_slice(&bytes);
}
#[inline]
pub fn write_i32(&mut self, offset: usize, value: i32) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 4].copy_from_slice(&bytes);
}
#[inline]
pub fn write_u32(&mut self, offset: usize, value: u32) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 4].copy_from_slice(&bytes);
}
#[inline]
pub fn write_i64(&mut self, offset: usize, value: i64) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 8].copy_from_slice(&bytes);
}
#[inline]
pub fn write_u64(&mut self, offset: usize, value: u64) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 8].copy_from_slice(&bytes);
}
#[inline]
pub fn write_i128(&mut self, offset: usize, value: i128) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 16].copy_from_slice(&bytes);
}
#[inline]
pub fn write_u128(&mut self, offset: usize, value: u128) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 16].copy_from_slice(&bytes);
}
#[inline]
pub fn write_f32(&mut self, offset: usize, value: f32) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 4].copy_from_slice(&bytes);
}
#[inline]
pub fn write_f64(&mut self, offset: usize, value: f64) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 8].copy_from_slice(&bytes);
}
#[inline]
pub fn write_string(&mut self, offset: usize, value: &str) {
let len = value.len() as i32;
self.write_i32(offset, len);
let bytes = value.as_bytes();
self.buffer[self.offset + offset + 4..self.offset + offset + 4 + bytes.len()]
.copy_from_slice(bytes);
}
#[inline]
pub fn write_timestamp(&mut self, offset: usize, value: u64) {
self.write_u64(offset, value);
}
#[inline]
pub fn write_uuid(&mut self, offset: usize, value: &[u8; 16]) {
self.buffer[self.offset + offset..self.offset + offset + 16].copy_from_slice(value);
}
#[inline]
pub fn write_bytes(&mut self, offset: usize, value: &[u8]) {
let len = value.len() as i32;
self.write_i32(offset, len);
self.buffer[self.offset + offset + 4..self.offset + offset + 4 + value.len()]
.copy_from_slice(value);
}
#[inline]
pub fn write_decimal(&mut self, offset: usize, value: i128, scale: u8, negative: bool) {
let bytes = value.to_le_bytes();
self.buffer[self.offset + offset..self.offset + offset + 12].copy_from_slice(&bytes[..12]);
self.buffer[self.offset + offset + 12] = 0;
self.buffer[self.offset + offset + 13] = 0;
self.buffer[self.offset + offset + 14] = scale;
self.buffer[self.offset + offset + 15] = if negative { 0x80 } else { 0x00 };
}
pub fn write_list_i32(&mut self, offset: usize, values: &[i32]) -> usize {
self.write_vector_i32(offset, values)
}
pub fn write_vector_i32(&mut self, offset: usize, values: &[i32]) -> usize {
let size = values.len();
let data_size = 4 + (size * 4); let data_offset = self.allocate(data_size);
self.write_u32(offset, (data_offset - self.offset) as u32);
self.write_u32(data_offset - self.offset, size as u32);
for (i, &value) in values.iter().enumerate() {
self.write_i32(data_offset - self.offset + 4 + (i * 4), value);
}
data_size
}
#[inline]
pub fn write_array_i32(&mut self, offset: usize, values: &[i32]) {
for (i, &value) in values.iter().enumerate() {
self.write_i32(offset + (i * 4), value);
}
}
pub fn write_map_i32(&mut self, offset: usize, entries: &[(i32, i32)]) -> usize {
let size = entries.len();
let data_size = 4 + (size * 8); let data_offset = self.allocate(data_size);
self.write_u32(offset, (data_offset - self.offset) as u32);
self.write_u32(data_offset - self.offset, size as u32);
for (i, &(key, value)) in entries.iter().enumerate() {
self.write_i32(data_offset - self.offset + 4 + (i * 8), key);
self.write_i32(data_offset - self.offset + 4 + (i * 8) + 4, value);
}
data_size
}
#[inline]
pub fn write_set_i32(&mut self, offset: usize, values: &[i32]) -> usize {
self.write_vector_i32(offset, values)
}
pub fn write_vector_string(&mut self, offset: usize, values: &[String]) -> usize {
let size = values.len();
let mut data_size = 4; for s in values {
data_size += 4 + s.len();
}
let data_offset = self.allocate(data_size);
self.write_u32(offset, (data_offset - self.offset) as u32);
self.write_u32(data_offset - self.offset, size as u32);
let mut current_offset = data_offset - self.offset + 4;
for s in values {
self.write_string(current_offset, s);
current_offset += 4 + s.len();
}
data_size
}
pub fn write_array_string(&mut self, offset: usize, values: &[String]) -> usize {
let mut current_offset = offset;
for s in values {
self.write_string(current_offset, s);
current_offset += 4 + s.len();
}
current_offset - offset
}
pub fn write_vector_f32(&mut self, offset: usize, values: &[f32]) -> usize {
let size = values.len();
let data_size = 4 + (size * 4);
let data_offset = self.allocate(data_size);
self.write_u32(offset, (data_offset - self.offset) as u32);
self.write_u32(data_offset - self.offset, size as u32);
for (i, &value) in values.iter().enumerate() {
self.write_f32(data_offset - self.offset + 4 + (i * 4), value);
}
data_size
}
pub fn write_array_f32(&mut self, offset: usize, values: &[f32]) -> usize {
for (i, &value) in values.iter().enumerate() {
self.write_f32(offset + (i * 4), value);
}
values.len() * 4
}
pub fn write_vector_f64(&mut self, offset: usize, values: &[f64]) -> usize {
let size = values.len();
let data_size = 4 + (size * 8);
let data_offset = self.allocate(data_size);
self.write_u32(offset, (data_offset - self.offset) as u32);
self.write_u32(data_offset - self.offset, size as u32);
for (i, &value) in values.iter().enumerate() {
self.write_f64(data_offset - self.offset + 4 + (i * 8), value);
}
data_size
}
pub fn write_array_f64(&mut self, offset: usize, values: &[f64]) -> usize {
for (i, &value) in values.iter().enumerate() {
self.write_f64(offset + (i * 8), value);
}
values.len() * 8
}
pub fn write_optional_i32(&mut self, offset: usize, value: Option<i32>) {
match value {
None => self.write_u8(offset, 0),
Some(v) => {
self.write_u8(offset, 1);
let data_offset = self.allocate(4); self.write_u32(offset + 1, (data_offset - self.offset) as u32);
self.write_i32(data_offset - self.offset, v);
}
}
}
pub fn write_optional_string(&mut self, offset: usize, value: Option<&str>) {
match value {
None => self.write_u8(offset, 0),
Some(v) => {
self.write_u8(offset, 1);
let len = v.len();
let data_offset = self.allocate(4 + len); self.write_u32(offset + 1, (data_offset - self.offset) as u32);
self.write_string(data_offset - self.offset, v);
}
}
}
pub fn write_optional_f64(&mut self, offset: usize, value: Option<f64>) {
match value {
None => self.write_u8(offset, 0),
Some(v) => {
self.write_u8(offset, 1);
let data_offset = self.allocate(8); self.write_u32(offset + 1, (data_offset - self.offset) as u32);
self.write_f64(data_offset - self.offset, v);
}
}
}
}
#[derive(Debug, Clone)]
pub struct ReadBuffer {
buffer: Vec<u8>,
size: usize,
offset: usize,
}
impl Default for ReadBuffer {
fn default() -> Self {
Self::new()
}
}
impl From<Vec<u8>> for ReadBuffer {
fn from(data: Vec<u8>) -> Self {
let size = data.len();
Self {
buffer: data,
size,
offset: 0,
}
}
}
impl ReadBuffer {
#[must_use]
pub fn new() -> Self {
Self {
buffer: Vec::new(),
size: 0,
offset: 0,
}
}
#[must_use]
pub fn data(&self) -> &[u8] {
&self.buffer
}
#[must_use]
pub fn capacity(&self) -> usize {
self.size
}
#[must_use]
pub const fn size(&self) -> usize {
self.size
}
#[must_use]
pub const fn offset(&self) -> usize {
self.offset
}
pub fn attach_buffer(&mut self, buffer: &[u8], offset: usize, size: usize) {
assert!(!buffer.is_empty(), "Invalid buffer!");
assert!(size > 0, "Invalid size!");
assert!(offset <= size, "Invalid offset!");
self.buffer = buffer.to_vec();
self.size = size;
self.offset = offset;
}
pub fn reset(&mut self) {
self.buffer.clear();
self.size = 0;
self.offset = 0;
}
pub fn shift(&mut self, offset: usize) {
self.offset += offset;
}
pub fn unshift(&mut self, offset: usize) {
self.offset -= offset;
}
#[must_use]
#[inline]
pub fn read_byte(&self, offset: usize) -> u8 {
self.read_u8(offset)
}
#[must_use]
#[inline]
pub fn read_char(&self, offset: usize) -> u8 {
self.buffer[self.offset + offset]
}
#[must_use]
#[inline]
pub fn read_wchar(&self, offset: usize) -> u32 {
self.read_u32(offset)
}
#[must_use]
#[inline]
pub fn read_bool(&self, offset: usize) -> bool {
self.buffer[self.offset + offset] != 0
}
#[must_use]
#[inline]
pub fn read_i8(&self, offset: usize) -> i8 {
self.buffer[self.offset + offset] as i8
}
#[must_use]
#[inline]
pub fn read_u8(&self, offset: usize) -> u8 {
self.buffer[self.offset + offset]
}
#[must_use]
#[inline]
pub fn read_i16(&self, offset: usize) -> i16 {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 2];
i16::from_le_bytes(bytes.try_into().unwrap())
}
#[must_use]
#[inline]
pub fn read_u16(&self, offset: usize) -> u16 {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 2];
u16::from_le_bytes(bytes.try_into().unwrap())
}
#[must_use]
#[inline]
pub fn read_i32(&self, offset: usize) -> i32 {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 4];
i32::from_le_bytes(bytes.try_into().unwrap())
}
#[must_use]
#[inline]
pub fn read_u32(&self, offset: usize) -> u32 {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 4];
u32::from_le_bytes(bytes.try_into().unwrap())
}
#[must_use]
#[inline]
pub fn read_i64(&self, offset: usize) -> i64 {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 8];
i64::from_le_bytes(bytes.try_into().unwrap())
}
#[must_use]
#[inline]
pub fn read_u64(&self, offset: usize) -> u64 {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 8];
u64::from_le_bytes(bytes.try_into().unwrap())
}
#[must_use]
#[inline]
pub fn read_i128(&self, offset: usize) -> i128 {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 16];
i128::from_le_bytes(bytes.try_into().unwrap())
}
#[must_use]
#[inline]
pub fn read_u128(&self, offset: usize) -> u128 {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 16];
u128::from_le_bytes(bytes.try_into().unwrap())
}
#[must_use]
#[inline]
pub fn read_f32(&self, offset: usize) -> f32 {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 4];
f32::from_le_bytes(bytes.try_into().unwrap())
}
#[must_use]
#[inline]
pub fn read_f64(&self, offset: usize) -> f64 {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 8];
f64::from_le_bytes(bytes.try_into().unwrap())
}
#[must_use]
#[inline]
pub fn read_string(&self, offset: usize) -> String {
let len = self.read_i32(offset) as usize;
let bytes = &self.buffer[self.offset + offset + 4..self.offset + offset + 4 + len];
String::from_utf8_lossy(bytes).to_string()
}
#[must_use]
#[inline]
pub fn read_timestamp(&self, offset: usize) -> u64 {
self.read_u64(offset)
}
#[must_use]
#[inline]
pub fn read_uuid(&self, offset: usize) -> [u8; 16] {
let bytes = &self.buffer[self.offset + offset..self.offset + offset + 16];
bytes.try_into().unwrap()
}
#[must_use]
#[inline]
pub fn read_bytes(&self, offset: usize) -> Vec<u8> {
let len = self.read_i32(offset) as usize;
self.buffer[self.offset + offset + 4..self.offset + offset + 4 + len].to_vec()
}
#[must_use]
#[inline]
pub fn read_decimal(&self, offset: usize) -> (i128, u8, bool) {
let mut value_bytes = [0u8; 16];
value_bytes[..12]
.copy_from_slice(&self.buffer[self.offset + offset..self.offset + offset + 12]);
let value = i128::from_le_bytes(value_bytes);
let scale = self.buffer[self.offset + offset + 14];
let negative = (self.buffer[self.offset + offset + 15] & 0x80) != 0;
(value, scale, negative)
}
#[must_use]
pub fn read_list_i32(&self, offset: usize) -> Vec<i32> {
self.read_vector_i32(offset)
}
#[must_use]
pub fn read_vector_i32(&self, offset: usize) -> Vec<i32> {
let data_offset = self.read_u32(offset) as usize;
if data_offset == 0 {
return Vec::new();
}
let size = self.read_u32(data_offset) as usize;
let mut result = Vec::with_capacity(size);
for i in 0..size {
result.push(self.read_i32(data_offset + 4 + (i * 4)));
}
result
}
#[must_use]
#[inline]
pub fn read_array_i32(&self, offset: usize, size: usize) -> Vec<i32> {
let mut result = Vec::with_capacity(size);
for i in 0..size {
result.push(self.read_i32(offset + (i * 4)));
}
result
}
#[must_use]
pub fn read_map_i32(&self, offset: usize) -> Vec<(i32, i32)> {
let data_offset = self.read_u32(offset) as usize;
if data_offset == 0 {
return Vec::new();
}
let size = self.read_u32(data_offset) as usize;
let mut result = Vec::with_capacity(size);
for i in 0..size {
let key = self.read_i32(data_offset + 4 + (i * 8));
let value = self.read_i32(data_offset + 4 + (i * 8) + 4);
result.push((key, value));
}
result
}
#[must_use]
#[inline]
pub fn read_set_i32(&self, offset: usize) -> Vec<i32> {
self.read_vector_i32(offset)
}
pub fn read_vector_string(&self, offset: usize) -> Vec<String> {
let pointer = self.read_u32(offset) as usize;
if pointer == 0 {
return Vec::new();
}
let size = self.read_u32(pointer) as usize;
let mut values = Vec::with_capacity(size);
let mut current_offset = pointer + 4;
for _ in 0..size {
let s = self.read_string(current_offset);
current_offset += 4 + s.len();
values.push(s);
}
values
}
pub fn read_array_string(&self, offset: usize, count: usize) -> Vec<String> {
let mut values = Vec::with_capacity(count);
let mut current_offset = offset;
for _ in 0..count {
let s = self.read_string(current_offset);
current_offset += 4 + s.len();
values.push(s);
}
values
}
pub fn read_vector_f32(&self, offset: usize) -> Vec<f32> {
let pointer = self.read_u32(offset) as usize;
if pointer == 0 {
return Vec::new();
}
let size = self.read_u32(pointer) as usize;
let mut values = Vec::with_capacity(size);
for i in 0..size {
values.push(self.read_f32(pointer + 4 + (i * 4)));
}
values
}
pub fn read_array_f32(&self, offset: usize, count: usize) -> Vec<f32> {
let mut values = Vec::with_capacity(count);
for i in 0..count {
values.push(self.read_f32(offset + (i * 4)));
}
values
}
pub fn read_vector_f64(&self, offset: usize) -> Vec<f64> {
let pointer = self.read_u32(offset) as usize;
if pointer == 0 {
return Vec::new();
}
let size = self.read_u32(pointer) as usize;
let mut values = Vec::with_capacity(size);
for i in 0..size {
values.push(self.read_f64(pointer + 4 + (i * 8)));
}
values
}
pub fn read_array_f64(&self, offset: usize, count: usize) -> Vec<f64> {
let mut values = Vec::with_capacity(count);
for i in 0..count {
values.push(self.read_f64(offset + (i * 8)));
}
values
}
pub fn has_value(&self, offset: usize) -> bool {
self.read_u8(offset) != 0
}
pub fn read_optional_i32(&self, offset: usize) -> Option<i32> {
if !self.has_value(offset) {
return None;
}
let data_offset = self.read_u32(offset + 1) as usize;
Some(self.read_i32(data_offset))
}
pub fn read_optional_string(&self, offset: usize) -> Option<String> {
if !self.has_value(offset) {
return None;
}
let data_offset = self.read_u32(offset + 1) as usize;
Some(self.read_string(data_offset))
}
pub fn read_optional_f64(&self, offset: usize) -> Option<f64> {
if !self.has_value(offset) {
return None;
}
let data_offset = self.read_u32(offset + 1) as usize;
Some(self.read_f64(data_offset))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_write_buffer_basic() {
let mut buffer = WriteBuffer::new();
assert!(buffer.is_empty());
assert_eq!(buffer.size(), 0);
assert_eq!(buffer.offset(), 0);
}
#[test]
fn test_write_buffer_allocate() {
let mut buffer = WriteBuffer::new();
let offset = buffer.allocate(100);
assert_eq!(offset, 0);
assert_eq!(buffer.size(), 100);
}
#[test]
fn test_write_read_primitives() {
let mut writer = WriteBuffer::with_capacity(100);
writer.allocate(100);
writer.write_i32(0, 42);
writer.write_f64(4, 3.14159);
writer.write_bool(12, true);
let mut reader = ReadBuffer::new();
reader.attach_buffer(writer.data(), 0, writer.size());
assert_eq!(reader.read_i32(0), 42);
assert_eq!(reader.read_f64(4), 3.14159);
assert_eq!(reader.read_bool(12), true);
}
}