automerge/rust/automerge/src/columnar/encoding/decodable_impls.rs
Alex Good dd3c6d1303
Move rust workspace into ./rust
After some discussion with PVH I realise that the repo structure in the
last reorg was very rust-centric. In an attempt to put each language on
a level footing move the rust code and project files into ./rust
2022-10-16 19:55:51 +01:00

175 lines
4.1 KiB
Rust

use smol_str::SmolStr;
use std::{borrow::Cow, convert::TryFrom, io::Read, str};
use super::{Decodable, DecodeError};
use crate::ActorId;
// We don't allow decoding items which are larger than this. Almost nothing should be this large
// so this is really guarding against bad encodings which accidentally grab loads of memory
const MAX_ALLOCATION: usize = 1000000000;
impl Decodable for u8 {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
let mut buffer = [0; 1];
bytes.read_exact(&mut buffer)?;
Ok(buffer[0])
}
}
impl Decodable for u32 {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
u64::decode::<R>(bytes).and_then(|val| Self::try_from(val).map_err(DecodeError::from))
}
}
impl Decodable for usize {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
u64::decode::<R>(bytes).and_then(|val| Self::try_from(val).map_err(DecodeError::from))
}
}
impl Decodable for isize {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
i64::decode::<R>(bytes).and_then(|val| Self::try_from(val).map_err(DecodeError::from))
}
}
impl Decodable for i32 {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
i64::decode::<R>(bytes).and_then(|val| Self::try_from(val).map_err(DecodeError::from))
}
}
impl Decodable for i64 {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
leb128::read::signed(bytes).map_err(DecodeError::from)
}
}
impl Decodable for f64 {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
let mut buffer = [0; 8];
bytes.read_exact(&mut buffer)?;
Ok(Self::from_le_bytes(buffer))
}
}
impl Decodable for f32 {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
let mut buffer = [0; 4];
bytes.read_exact(&mut buffer)?;
Ok(Self::from_le_bytes(buffer))
}
}
impl Decodable for u64 {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
leb128::read::unsigned(bytes).map_err(DecodeError::from)
}
}
impl Decodable for Vec<u8> {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
let len = usize::decode::<R>(bytes)?;
if len == 0 {
return Ok(vec![]);
}
if len > MAX_ALLOCATION {
return Err(DecodeError::OverlargeAllocation {
attempted: len,
maximum: MAX_ALLOCATION,
});
}
let mut buffer = vec![0; len];
bytes.read_exact(buffer.as_mut_slice())?;
Ok(buffer)
}
}
impl Decodable for SmolStr {
fn decode<R>(bytes: &mut R) -> Result<SmolStr, DecodeError>
where
R: Read,
{
let buffer = Vec::decode(bytes)?;
str::from_utf8(&buffer)
.map(|t| t.into())
.map_err(|_| DecodeError::BadString)
}
}
impl Decodable for Cow<'static, SmolStr> {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: std::io::Read,
{
SmolStr::decode(bytes).map(Cow::Owned)
}
}
impl Decodable for String {
fn decode<R>(bytes: &mut R) -> Result<String, DecodeError>
where
R: Read,
{
let buffer = Vec::decode(bytes)?;
str::from_utf8(&buffer)
.map(|t| t.into())
.map_err(|_| DecodeError::BadString)
}
}
impl Decodable for Option<String> {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
let buffer = Vec::decode(bytes)?;
if buffer.is_empty() {
return Ok(None);
}
str::from_utf8(&buffer)
.map(|t| Some(t.into()))
.map_err(|_| DecodeError::BadString)
}
}
impl Decodable for ActorId {
fn decode<R>(bytes: &mut R) -> Result<Self, DecodeError>
where
R: Read,
{
let buffer = Vec::decode(bytes)?;
Ok(buffer.into())
}
}