mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-11-16 15:58:17 +00:00
epee: make {read,write}_varint
public, create write_{bytes,container}
(#185)
* make `{read,write}_varint` public, create `write_{container,bytes}` * add doc tests to varint functions * `write_container` -> `write_iterator` * add `write_{iterator,bytes}` doc test * fix `write_iterator()` doc
This commit is contained in:
parent
f6c4e4e9a8
commit
ff1172f2ab
3 changed files with 130 additions and 85 deletions
|
@ -77,7 +77,7 @@ pub use error::*;
|
|||
use io::*;
|
||||
pub use marker::{InnerMarker, Marker};
|
||||
pub use value::EpeeValue;
|
||||
use varint::*;
|
||||
pub use varint::{read_varint, write_varint};
|
||||
|
||||
/// Header that needs to be at the beginning of every binary blob that follows
|
||||
/// this binary serialization format.
|
||||
|
@ -212,6 +212,87 @@ fn write_epee_value<T: EpeeValue, B: BufMut>(val: T, w: &mut B) -> Result<()> {
|
|||
val.write(w)
|
||||
}
|
||||
|
||||
/// Write a byte array to `w` with [`write_varint`].
|
||||
///
|
||||
/// This function:
|
||||
/// - Writes the length of `t`'s bytes into `w` using [`write_varint`]
|
||||
/// - Writes `t`'s bytes into `w`
|
||||
///
|
||||
/// It is used as the internal [`EpeeValue::write`]
|
||||
/// implementation of byte-like containers such as:
|
||||
/// - [`EpeeValue::<Vec<u8>>::write`]
|
||||
/// - [`EpeeValue::<String>::write`]
|
||||
///
|
||||
/// # Errors
|
||||
/// This will error if:
|
||||
/// - [`write_varint`] fails
|
||||
/// - `w` does not have enough capacity
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// let t: [u8; 8] = [3, 0, 0, 0, 1, 0, 0, 0];
|
||||
/// let mut w = vec![];
|
||||
///
|
||||
/// epee_encoding::write_bytes(t, &mut w).unwrap();
|
||||
///
|
||||
/// assert_eq!(w.len(), 9); // length of bytes + bytes
|
||||
/// assert_eq!(w[1..], t);
|
||||
/// ```
|
||||
pub fn write_bytes<T: AsRef<[u8]>, B: BufMut>(t: T, w: &mut B) -> Result<()> {
|
||||
let bytes = t.as_ref();
|
||||
let len = bytes.len();
|
||||
|
||||
write_varint(len.try_into()?, w)?;
|
||||
|
||||
if w.remaining_mut() < len {
|
||||
return Err(Error::IO("Not enough capacity to write bytes"));
|
||||
}
|
||||
|
||||
w.put_slice(bytes);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write an [`Iterator`] of [`EpeeValue`]s to `w` with [`write_varint`].
|
||||
///
|
||||
/// This function:
|
||||
/// - Writes the length of the `iterator`, into `w` using [`write_varint`]
|
||||
/// - [`EpeeValue::write`]s each `T` of the iterator into `w`
|
||||
///
|
||||
/// It is used as the internal [`EpeeValue::write`]
|
||||
/// implementation of containers such as [`EpeeValue::<Vec<T>>::write`].
|
||||
///
|
||||
/// # Errors
|
||||
/// This will error if:
|
||||
/// - [`write_varint`] fails
|
||||
/// - [`EpeeValue::<T>::write`] fails
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// let t: u64 = 3;
|
||||
/// let vec: Vec<u64> = vec![t, t];
|
||||
/// let mut w = vec![];
|
||||
///
|
||||
/// let iter: std::vec::IntoIter<u64> = vec.into_iter();
|
||||
/// epee_encoding::write_iterator(iter, &mut w).unwrap();
|
||||
///
|
||||
/// assert_eq!(w.len(), 17);
|
||||
/// assert_eq!(w[1..9], [3, 0, 0, 0, 0, 0, 0, 0]);
|
||||
/// assert_eq!(w[9..], [3, 0, 0, 0, 0, 0, 0, 0]);
|
||||
/// ```
|
||||
pub fn write_iterator<T, I, B>(iterator: I, w: &mut B) -> Result<()>
|
||||
where
|
||||
T: EpeeValue,
|
||||
I: Iterator<Item = T> + ExactSizeIterator,
|
||||
B: BufMut,
|
||||
{
|
||||
write_varint(iterator.len().try_into()?, w)?;
|
||||
for item in iterator.into_iter() {
|
||||
item.write(w)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A helper object builder that just skips every field.
|
||||
#[derive(Default)]
|
||||
struct SkipObjectBuilder;
|
||||
|
|
|
@ -9,7 +9,10 @@ use bytes::{Buf, BufMut, Bytes, BytesMut};
|
|||
use fixed_bytes::{ByteArray, ByteArrayVec};
|
||||
|
||||
use crate::{
|
||||
io::*, varint::*, EpeeObject, Error, InnerMarker, Marker, Result, MAX_STRING_LEN_POSSIBLE,
|
||||
io::{checked_read_primitive, checked_write_primitive},
|
||||
varint::{read_varint, write_varint},
|
||||
write_bytes, write_iterator, EpeeObject, Error, InnerMarker, Marker, Result,
|
||||
MAX_STRING_LEN_POSSIBLE,
|
||||
};
|
||||
|
||||
/// A trait for epee values.
|
||||
|
@ -83,11 +86,7 @@ impl<T: EpeeObject> EpeeValue for Vec<T> {
|
|||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
write_varint(self.len().try_into()?, w)?;
|
||||
for item in self.into_iter() {
|
||||
item.write(w)?;
|
||||
}
|
||||
Ok(())
|
||||
write_iterator(self.into_iter(), w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,11 +104,7 @@ impl<T: EpeeObject + Debug, const N: usize> EpeeValue for [T; N] {
|
|||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
write_varint(self.len().try_into()?, w)?;
|
||||
for item in self.into_iter() {
|
||||
item.write(w)?;
|
||||
}
|
||||
Ok(())
|
||||
write_iterator(self.into_iter(), w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,14 +186,7 @@ impl EpeeValue for Vec<u8> {
|
|||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
write_varint(self.len().try_into()?, w)?;
|
||||
|
||||
if w.remaining_mut() < self.len() {
|
||||
return Err(Error::IO("Not enough capacity to write bytes"));
|
||||
}
|
||||
|
||||
w.put_slice(&self);
|
||||
Ok(())
|
||||
write_bytes(self, w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,14 +219,7 @@ impl EpeeValue for Bytes {
|
|||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
write_varint(self.len().try_into()?, w)?;
|
||||
|
||||
if w.remaining_mut() < self.len() {
|
||||
return Err(Error::IO("Not enough capacity to write bytes"));
|
||||
}
|
||||
|
||||
w.put(self);
|
||||
Ok(())
|
||||
write_bytes(self, w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,14 +255,7 @@ impl EpeeValue for BytesMut {
|
|||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
write_varint(self.len().try_into()?, w)?;
|
||||
|
||||
if w.remaining_mut() < self.len() {
|
||||
return Err(Error::IO("Not enough capacity to write bytes"));
|
||||
}
|
||||
|
||||
w.put(self);
|
||||
Ok(())
|
||||
write_bytes(self, w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,15 +290,7 @@ impl<const N: usize> EpeeValue for ByteArrayVec<N> {
|
|||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
let bytes = self.take_bytes();
|
||||
|
||||
write_varint(bytes.len().try_into()?, w)?;
|
||||
|
||||
if w.remaining_mut() < bytes.len() {
|
||||
return Err(Error::IO("Not enough capacity to write bytes"));
|
||||
}
|
||||
|
||||
w.put(bytes);
|
||||
Ok(())
|
||||
write_bytes(bytes, w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,15 +317,7 @@ impl<const N: usize> EpeeValue for ByteArray<N> {
|
|||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
let bytes = self.take_bytes();
|
||||
|
||||
write_varint(N.try_into().unwrap(), w)?;
|
||||
|
||||
if w.remaining_mut() < N {
|
||||
return Err(Error::IO("Not enough capacity to write bytes"));
|
||||
}
|
||||
|
||||
w.put(bytes);
|
||||
Ok(())
|
||||
write_bytes(bytes, w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,14 +338,7 @@ impl EpeeValue for String {
|
|||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
write_varint(self.len().try_into()?, w)?;
|
||||
|
||||
if w.remaining_mut() < self.len() {
|
||||
return Err(Error::IO("Not enough capacity to write bytes"));
|
||||
}
|
||||
|
||||
w.put_slice(self.as_bytes());
|
||||
Ok(())
|
||||
write_bytes(self, w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,14 +356,7 @@ impl<const N: usize> EpeeValue for [u8; N] {
|
|||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
write_varint(self.len().try_into()?, w)?;
|
||||
|
||||
if w.remaining_mut() < self.len() {
|
||||
return Err(Error::IO("Not enough capacity to write bytes"));
|
||||
}
|
||||
|
||||
w.put_slice(&self);
|
||||
Ok(())
|
||||
write_bytes(self, w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,11 +390,7 @@ impl<const N: usize> EpeeValue for Vec<[u8; N]> {
|
|||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
write_varint(self.len().try_into()?, w)?;
|
||||
for item in self.into_iter() {
|
||||
item.write(w)?;
|
||||
}
|
||||
Ok(())
|
||||
write_iterator(self.into_iter(), w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -486,11 +426,7 @@ macro_rules! epee_seq {
|
|||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
write_varint(self.len().try_into()?, w)?;
|
||||
for item in self.into_iter() {
|
||||
item.write(w)?;
|
||||
}
|
||||
Ok(())
|
||||
write_iterator(self.into_iter(), w)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,11 +444,7 @@ macro_rules! epee_seq {
|
|||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
|
||||
write_varint(self.len().try_into()?, w)?;
|
||||
for item in self.into_iter() {
|
||||
item.write(w)?;
|
||||
}
|
||||
Ok(())
|
||||
write_iterator(self.into_iter(), w)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7,6 +7,18 @@ const FITS_IN_ONE_BYTE: u64 = 2_u64.pow(8 - SIZE_OF_SIZE_MARKER) - 1;
|
|||
const FITS_IN_TWO_BYTES: u64 = 2_u64.pow(16 - SIZE_OF_SIZE_MARKER) - 1;
|
||||
const FITS_IN_FOUR_BYTES: u64 = 2_u64.pow(32 - SIZE_OF_SIZE_MARKER) - 1;
|
||||
|
||||
/// Read an epee variable sized number from `r`.
|
||||
///
|
||||
/// ```rust
|
||||
/// use epee_encoding::read_varint;
|
||||
///
|
||||
/// assert_eq!(read_varint(&mut [252].as_slice()).unwrap(), 63);
|
||||
/// assert_eq!(read_varint(&mut [1, 1].as_slice()).unwrap(), 64);
|
||||
/// assert_eq!(read_varint(&mut [253, 255].as_slice()).unwrap(), 16_383);
|
||||
/// assert_eq!(read_varint(&mut [2, 0, 1, 0].as_slice()).unwrap(), 16_384);
|
||||
/// assert_eq!(read_varint(&mut [254, 255, 255, 255].as_slice()).unwrap(), 1_073_741_823);
|
||||
/// assert_eq!(read_varint(&mut [3, 0, 0, 0, 1, 0, 0, 0].as_slice()).unwrap(), 1_073_741_824);
|
||||
/// ```
|
||||
pub fn read_varint<B: Buf>(r: &mut B) -> Result<u64> {
|
||||
if !r.has_remaining() {
|
||||
Err(Error::IO("Not enough bytes to build VarInt"))?
|
||||
|
@ -26,6 +38,26 @@ pub fn read_varint<B: Buf>(r: &mut B) -> Result<u64> {
|
|||
Ok(vi)
|
||||
}
|
||||
|
||||
/// Write an epee variable sized number into `w`.
|
||||
///
|
||||
/// ```rust
|
||||
/// use epee_encoding::write_varint;
|
||||
///
|
||||
/// let mut buf = vec![];
|
||||
///
|
||||
/// for (number, expected_bytes) in [
|
||||
/// (63, [252].as_slice()),
|
||||
/// (64, [1, 1].as_slice()),
|
||||
/// (16_383, [253, 255].as_slice()),
|
||||
/// (16_384, [2, 0, 1, 0].as_slice()),
|
||||
/// (1_073_741_823, [254, 255, 255, 255].as_slice()),
|
||||
/// (1_073_741_824, [3, 0, 0, 0, 1, 0, 0, 0].as_slice()),
|
||||
/// ] {
|
||||
/// buf.clear();
|
||||
/// write_varint(number, &mut buf);
|
||||
/// assert_eq!(buf.as_slice(), expected_bytes);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn write_varint<B: BufMut>(number: u64, w: &mut B) -> Result<()> {
|
||||
let size_marker = match number {
|
||||
0..=FITS_IN_ONE_BYTE => 0,
|
||||
|
|
Loading…
Reference in a new issue