rustt 0.1.2

A wire-protocol for efficiently transfering self-describing data implemented in rust.
//! TTv3 contains all the v3 specific things like [`Error`], [`Key`] and [`Value`]

use self::serde::Type;
use std::io::{self, ErrorKind};

mod error;
pub(crate) mod serde;
pub(crate) mod size;
mod untyped;
pub use self::error::Error;
pub use self::serde::{TtF32, TtF64};
pub use untyped::{Key, Value};

#[derive(Debug, Clone)]
pub(crate) struct Node<'d> {
	children_length: usize,
	value_data: &'d [u8],
	value_type: Type,
	key_data: &'d [u8],
	key_type: Type,
}

impl<'v, 'd: 'v> Node<'v> {
	#[inline(always)]
	pub fn from_bytes(&mut self, data: &'d [u8]) -> Result<usize, Error> {
		//decode_var is so expensive and 0 values are common enough for this to be benificial in most cases
		let (vlen, size) = decode_var(&data)?;
		let mut read = size;
		let (klen, size) = decode_var(&data[read..])?;
		read += size;
		//if total data - what is already reaad< what is minimally needed for this Node to be read.
		//first 2 +1 are for the types, the last for the minimal children length
		if data.len() - read < (1 + vlen + 1 + klen + 1) as usize {
			return Err(Error::OutOfSpace());
		}
		self.value_type = Type::from_u8(data[read]);
		read += 1;
		self.value_data = &data[read..read + vlen as usize];
		read += vlen as usize;
		self.key_type = Type::from_u8(data[read]);
		read += 1;
		self.key_data = &data[read..read + klen as usize];
		read += klen as usize;
		let (clen, size) = decode_var(&data[read..])?;
		self.children_length = clen; //.0 is the value not the read data lenght

		Ok(read + size)
	}
}

impl Default for Node<'_> {
	fn default() -> Node<'static> {
		Node {
			children_length: 0,
			value_data: &[],
			value_type: Default::default(),
			key_data: &[],
			key_type: Default::default(),
		}
	}
}

pub(crate) fn write_key_value<K: serde::KeyEncodable, V: serde::ValueEncodable, W>(
	key: &K,
	value: &V,
	out: &mut W,
) -> Result<(), Error>
where
	W: io::Write,
{
	let mut buf = [0 as u8; 10];
	let mut buflen: usize;
	buflen = encode_var(value.len(), &mut buf);
	out.write_all(&buf[0..buflen])?;
	buflen = encode_var(key.len(), &mut buf);
	out.write_all(&buf[0..buflen])?;

	out.write_all(&value.ttype().to_le_bytes())?;
	value.write_bytes(out)?;
	out.write_all(&key.ttype().to_le_bytes())?;
	key.write_bytes(out)?;
	buflen = encode_var(value.len_children(), &mut buf);
	out.write_all(&buf[0..buflen])?;

	value.write_children(out)?;

	Ok(())
}

pub(crate) fn write_key_value_buf<K: serde::KeyEncodable, V: serde::ValueEncodable, W>(
	key: &K,
	value: &V,
	out: &mut W,
	buf: &mut [u8; 10],
) -> Result<(), Error>
where
	W: io::Write,
{
	let mut buflen: usize;
	buflen = encode_var(value.len(), buf);
	out.write_all(&buf[0..buflen])?;
	buflen = encode_var(key.len(), buf);
	out.write_all(&buf[0..buflen])?;

	out.write_all(&value.ttype().to_le_bytes())?;
	value.write_bytes(out)?;
	out.write_all(&key.ttype().to_le_bytes())?;
	key.write_bytes(out)?;
	buflen = encode_var(value.len_children(), buf);
	out.write_all(&buf[0..buflen])?;

	value.write_children(out)?;

	Ok(())
}

#[derive(Debug, Clone)]
pub(crate) struct ReadNode {
	value_length: usize,
	key_length: usize,
}

impl ReadNode {
	#[inline(always)]
	pub fn read_lengths<R: io::Read>(&mut self, r: &mut R) -> Result<(), Error> {
		self.value_length = decode_var_reader(r)?;
		self.key_length = decode_var_reader(r)?;
		Ok(())
	}
}
impl Default for ReadNode {
	fn default() -> ReadNode {
		ReadNode {
			value_length: 0,
			key_length: 0,
		}
	}
}

#[inline(always)]
pub(crate) fn read_byte<R: io::Read>(r: &mut R) -> Option<u8> {
	let mut buf = [0];
	loop {
		match r.read(&mut buf) {
			Ok(0) => return None,
			Ok(_) => return Some(buf[0]),
			Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
			Err(_e) => return None,
		};
	}
}

#[inline(always)]
pub(crate) fn discard_var_reader<R: io::Read>(r: &mut R) {
	loop {
		match read_byte(r) {
			Some(b) if b & 0x80 == 0 => return,
			None => return,
			Some(_) => {}
		};
	}
}

#[inline(always)]
pub(crate) fn decode_var_reader<R: io::Read>(r: &mut R) -> Result<usize, Error> {
	let mut x = 0;
	let mut s = 0;
	loop {
		let b = match read_byte(r) {
			Some(b) => b,
			None => return Err(Error::OutOfSpace()),
		};
		x |= (b << s) as usize;
		s += 7;
		if b & 0x80 == 0 {
			if s > 10 * 7 || s == 10 * 7 && b > 1 {
				return Err(Error::new(
					"The decoded varint is to big, the input data is likely corrupt",
				));
			}
			return Ok(x);
		}
	}
}

#[inline(always)]
pub(crate) fn decode_var(src: &[u8]) -> Result<(usize, usize), Error> {
	let mut x = 0;
	let mut s = 0;
	let mut i = 0;
	let mut iter = src.iter();
	loop {
		let b = match iter.next() {
			Some(b) => b,
			None => return Err(Error::OutOfSpace()),
		};

		i += 1;
		x |= (b << s) as usize;
		s += 7;
		if b & 0x80 == 0 {
			if s > 10 * 7 || s == 10 * 7 && b > &1 {
				return Err(Error::new(
					"The decoded varint is to big, the input data is likely corrupt",
				));
			}
			return Ok((x, i));
		}
		s += 7;
	}
}

#[inline(always)]
pub(crate) fn encode_var(mut u: usize, dst: &mut [u8; 10]) -> usize {
	let mut i = 0;
	while u >= 0x80 {
		dst[i] = u as u8 | 0x80;
		u >>= 7;
		i += 1;
	}
	dst[i] = u as u8;
	i + 1
}

#[inline(always)]
fn size_var(mut v: usize) -> usize {
	let mut i = 0;
	while v >= 0x80 {
		v >>= 7;
		i += 1;
	}
	i + 1
}