use std::io;
pub use super::EncoderError;
use crate::{Typ, Encoder};
pub fn encode_varint<W>(
mut val: u64,
buf: &mut W,
) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
let mut size = 0;
loop {
size += 1;
if val < 0x80 {
buf.write_all(&[val as u8 & 0x7F])?;
return Ok(size);
} else {
let byte = ((val & 0x7F) | 0x80) as u8;
buf.write_all(&[byte])?;
val >>= 7;
}
}
}
pub fn encode_key<W>(
tag: u32,
typ: Typ,
buf: &mut W,
) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
if tag < Encoder::TAG_MIN || tag > Encoder::TAG_MAX {
return Err(EncoderError::InvalidTag);
}
let key = (tag << 3) | typ as u32;
encode_varint(u64::from(key), buf)
}
pub fn encode_bool<W>(val: bool, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
let res = if val { 1u64 } else { 0u64 };
encode_varint(res, buf)
}
pub fn encode_int32<W>(val: i32, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
encode_varint(val as u64, buf)
}
pub fn encode_int64<W>(val: i64, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
encode_varint(val as u64, buf)
}
pub fn encode_uint32<W>(val: u32, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
encode_varint(val as u64, buf)
}
pub fn encode_uint64<W>(val: u64, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
encode_varint(val, buf)
}
pub fn encode_sint32<W>(val: i32, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
let res = ((val << 1) ^ (val >> 31)) as u32 as u64;
encode_varint(res, buf)
}
pub fn encode_sint64<W>(val: i64, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
let res = ((val << 1) ^ (val >> 63)) as u64;
encode_varint(res, buf)
}
pub fn encode_fixed32<W>(val: u32, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
buf.write_all(&val.to_le_bytes())?;
Ok(4)
}
pub fn encode_fixed64<W>(val: u64, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
buf.write_all(&val.to_le_bytes())?;
Ok(8)
}
pub fn encode_sfixed32<W>(val: i32, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
buf.write_all(&val.to_le_bytes())?;
Ok(4)
}
pub fn encode_sfixed64<W>(val: i64, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
buf.write_all(&val.to_le_bytes())?;
Ok(8)
}
pub fn encode_float<W>(val: f32, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
buf.write_all(&val.to_le_bytes())?;
Ok(4)
}
pub fn encode_double<W>(val: f64, buf: &mut W) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
buf.write_all(&val.to_le_bytes())?;
Ok(8)
}
pub fn encode_bytes<W>(
mut bytes: Vec<u8>,
buf: &mut W,
) -> Result<usize, EncoderError>
where
W: ?Sized + io::Write,
{
let mut size = bytes.len();
if size > u64::MAX as usize {
return Err(EncoderError::DataOverflow);
}
size += encode_varint(size as u64, buf)?; buf.write_all(&mut bytes)?;
Ok(size)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn encodes_varints() {
let mut dst = vec![];
let size = encode_varint(u64::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![0]);
assert_eq!(size, 1);
dst.clear();
let size = encode_varint(u64::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 255, 255, 255, 255, 255, 1]);
assert_eq!(size, 10);
}
#[test]
fn encodes_key() {
let mut dst = vec![];
let size = encode_key(123456789, Typ::Varint, &mut dst).unwrap();
assert_eq!(dst, vec![168, 209, 249, 214, 3]);
assert_eq!(size, 5);
dst.clear();
let size = encode_key(1234, Typ::Bit32, &mut dst).unwrap();
assert_eq!(dst, vec![149, 77]);
assert_eq!(size, 2);
}
#[test]
fn encodes_int32() {
let mut dst = vec![];
let size = encode_int32(i32::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![128, 128, 128, 128, 248, 255, 255, 255, 255, 1]);
assert_eq!(size, 10);
dst.clear();
let size = encode_int32(i32::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 7]);
assert_eq!(size, 5);
}
#[test]
fn encodes_uint32() {
let mut dst = vec![];
let size = encode_uint32(u32::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![0]);
assert_eq!(size, 1);
dst.clear();
let size = encode_uint32(u32::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 15]);
assert_eq!(size, 5);
}
#[test]
fn encodes_sint32() {
let mut dst = vec![];
let size = encode_sint32(i32::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 15]);
assert_eq!(size, 5);
dst.clear();
let size = encode_sint32(i32::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![254, 255, 255, 255, 15]);
assert_eq!(size, 5);
}
#[test]
fn encodes_int64() {
let mut dst = vec![];
let size = encode_int64(i64::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![128, 128, 128, 128, 128, 128, 128, 128, 128, 1]);
assert_eq!(size, 10);
dst.clear();
let size = encode_int64(i64::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 255, 255, 255, 255, 127]);
assert_eq!(size, 9);
}
#[test]
fn encodes_uint64() {
let mut dst = vec![];
let size = encode_uint64(u64::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![0]);
assert_eq!(size, 1);
dst.clear();
let size = encode_uint64(u64::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 255, 255, 255, 255, 255, 1]);
assert_eq!(size, 10);
}
#[test]
fn encodes_sint64() {
let mut dst = vec![];
let size = encode_sint64(i64::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 255, 255, 255, 255, 255, 1]);
assert_eq!(size, 10);
dst.clear();
let size = encode_sint64(i64::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![254, 255, 255, 255, 255, 255, 255, 255, 255, 1]);
assert_eq!(size, 10);
}
#[test]
fn encodes_bool() {
let mut dst = vec![];
let size = encode_bool(true, &mut dst).unwrap();
assert_eq!(dst, vec![1]);
assert_eq!(size, 1);
dst.clear();
let size = encode_bool(false, &mut dst).unwrap();
assert_eq!(dst, vec![0]);
assert_eq!(size, 1);
}
#[test]
fn encodes_fixed64() {
let mut dst = vec![];
let size = encode_fixed64(u64::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![0, 0, 0, 0, 0, 0, 0, 0]);
assert_eq!(size, 8);
dst.clear();
let size = encode_fixed64(u64::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 255, 255, 255, 255]);
assert_eq!(size, 8);
}
#[test]
fn encodes_sfixed64() {
let mut dst = vec![];
let size = encode_sfixed64(i64::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![0, 0, 0, 0, 0, 0, 0, 128]);
assert_eq!(size, 8);
dst.clear();
let size = encode_sfixed64(i64::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 255, 255, 255, 127]);
assert_eq!(size, 8);
}
#[test]
fn encodes_double() {
let mut dst = vec![];
let size = encode_double(f64::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 255, 255, 239, 255]);
assert_eq!(size, 8);
dst.clear();
let size = encode_double(f64::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255, 255, 255, 239, 127]);
assert_eq!(size, 8);
}
#[test]
fn encodes_fixed32() {
let mut dst = vec![];
let size = encode_fixed32(u32::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![0, 0, 0, 0]);
assert_eq!(size, 4);
dst.clear();
let size = encode_fixed32(u32::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 255]);
assert_eq!(size, 4);
}
#[test]
fn encodes_sfixed32() {
let mut dst = vec![];
let size = encode_sfixed32(i32::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![0, 0, 0, 128]);
assert_eq!(size, 4);
dst.clear();
let size = encode_sfixed32(i32::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 255, 127]);
assert_eq!(size, 4);
}
#[test]
fn encodes_float() {
let mut dst = vec![];
let size = encode_float(f32::MIN, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 127, 255]);
assert_eq!(size, 4);
dst.clear();
let size = encode_float(f32::MAX, &mut dst).unwrap();
assert_eq!(dst, vec![255, 255, 127, 127]);
assert_eq!(size, 4);
}
#[test]
fn encodes_bytes() {
let mut dst = vec![];
let size = encode_bytes(vec![1, 2, 3, 4, 5], &mut dst).unwrap();
assert_eq!(dst, vec![5, 1, 2, 3, 4, 5]);
assert_eq!(size, 6);
}
}