use std::collections::HashMap;
#[derive(Debug, Default, PartialEq, Eq)]
pub(crate) struct BytesPool {
buffer: Vec<u8>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct BytesSymbol {
from: usize,
to: usize,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct StringSymbol {
from: usize,
to: usize,
}
impl BytesPool {
fn insert(&mut self, v: &[u8]) -> BytesSymbol {
let from = self.buffer.len();
self.buffer.extend(v);
BytesSymbol {
from,
to: self.buffer.len(),
}
}
fn insert_str(&mut self, v: &str) -> StringSymbol {
let from = self.buffer.len();
self.buffer.extend(v.as_bytes());
StringSymbol {
from,
to: self.buffer.len(),
}
}
pub(crate) fn get(&self, symbol: BytesSymbol) -> &[u8] {
&self.buffer[symbol.from..symbol.to]
}
pub(crate) fn get_str(&self, symbol: StringSymbol) -> &str {
unsafe { std::str::from_utf8_unchecked(&self.buffer[symbol.from..symbol.to]) }
}
}
#[derive(Default, Debug)]
pub(crate) struct BytesPoolBuilder {
pool: BytesPool,
bytes_map: HashMap<Vec<u8>, BytesSymbol>,
str_map: HashMap<String, StringSymbol>,
}
impl BytesPoolBuilder {
pub(crate) fn insert(&mut self, v: &[u8]) -> BytesSymbol {
match self.bytes_map.get(v) {
Some(v) => *v,
None => {
let symbol = self.pool.insert(v);
let _r = self.bytes_map.insert(v.to_vec(), symbol);
symbol
}
}
}
pub(crate) fn insert_str(&mut self, v: &str) -> StringSymbol {
match self.str_map.get(v) {
Some(v) => *v,
None => {
let symbol = self.pool.insert_str(v);
let _r = self.str_map.insert(v.to_owned(), symbol);
symbol
}
}
}
pub(crate) fn into_pool(mut self) -> BytesPool {
self.pool.buffer.shrink_to_fit();
self.pool
}
}
#[cfg(feature = "serialize")]
mod wire {
use std::io;
use crate::wire::{Deserialize, Serialize};
use super::{BytesPool, BytesSymbol, StringSymbol};
impl Serialize for BytesPool {
fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
self.buffer.serialize(writer)
}
}
impl Deserialize for BytesPool {
fn deserialize_reader<R: io::Read>(reader: &mut R) -> io::Result<Self> {
Ok(Self {
buffer: <Vec<u8>>::deserialize_reader(reader)?,
})
}
}
impl Serialize for StringSymbol {
fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
self.from.serialize(writer)?;
self.to.serialize(writer)?;
Ok(())
}
}
impl Deserialize for StringSymbol {
fn deserialize_reader<R: io::Read>(reader: &mut R) -> io::Result<Self> {
let from = usize::deserialize_reader(reader)?;
let to = usize::deserialize_reader(reader)?;
Ok(Self { from, to })
}
}
impl Serialize for BytesSymbol {
fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
self.from.serialize(writer)?;
self.to.serialize(writer)?;
Ok(())
}
}
impl Deserialize for BytesSymbol {
fn deserialize_reader<R: io::Read>(reader: &mut R) -> io::Result<Self> {
let from = usize::deserialize_reader(reader)?;
let to = usize::deserialize_reader(reader)?;
Ok(Self { from, to })
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::wire::tests::test_round_trip;
#[test]
fn test_wire_bytes_pool() {
test_round_trip(
&BytesPool {
buffer: b"abcedf".to_vec(),
},
&[2, 6],
);
test_round_trip(&BytesPool { buffer: Vec::new() }, &[2]);
test_round_trip(&StringSymbol { from: 23, to: 2 }, &[0, 8]);
test_round_trip(&BytesSymbol { from: 3, to: 8 }, &[0, 8]);
}
}
}
#[cfg(test)]
mod tests {
use crate::test_helpers::{test_type_traits, test_type_traits_non_clonable};
use super::*;
#[test]
fn test_types_traits() {
test_type_traits_non_clonable(BytesPoolBuilder::default());
test_type_traits_non_clonable(BytesPoolBuilder::default().into_pool());
test_type_traits(BytesSymbol { from: 0, to: 0 });
test_type_traits(StringSymbol { from: 0, to: 0 });
}
}