use crate::emitter::errors::EmitError;
use crate::leb128::{encode_signed, encode_unsigned};
use crate::model::Name;
use std::borrow::Borrow;
use std::convert::TryFrom;
use std::io::Write;
use std::iter::IntoIterator;
pub fn emit_f32<T: Borrow<f32>, O: Write + ?Sized>(
value: T,
output: &mut O,
) -> Result<usize, EmitError> {
let bytes = value.borrow().to_le_bytes();
output.write_all(&bytes)?;
Ok(bytes.len())
}
pub fn emit_f64<T: Borrow<f64>, O: Write + ?Sized>(
value: T,
output: &mut O,
) -> Result<usize, EmitError> {
let bytes = value.borrow().to_le_bytes();
output.write_all(&bytes)?;
Ok(bytes.len())
}
pub fn emit_name<O: Write + ?Sized>(value: &Name, output: &mut O) -> Result<usize, EmitError> {
emit_bytes(value.as_bytes(), output, true)
}
pub fn emit_byte<T: Borrow<u8>, O: Write + ?Sized>(
byte: T,
output: &mut O,
) -> Result<usize, EmitError> {
let bytes = [*byte.borrow()];
output.write_all(&bytes)?;
Ok(bytes.len())
}
pub fn emit_bytes<O: Write + ?Sized>(
value: &[u8],
output: &mut O,
include_length: bool,
) -> Result<usize, EmitError> {
let prefix = if include_length {
emit_usize(value.len(), output)?
} else {
0
};
output.write_all(value)?;
Ok(prefix + value.len())
}
pub fn emit_u32<T: Borrow<u32>, O: Write + ?Sized>(
value: T,
output: &mut O,
) -> Result<usize, EmitError> {
Ok(encode_unsigned(*value.borrow(), output)?)
}
pub fn emit_usize<T: Borrow<usize>, O: Write + ?Sized>(
size: T,
output: &mut O,
) -> Result<usize, EmitError> {
Ok(encode_unsigned(u128::try_from(*size.borrow())?, output)?)
}
pub fn emit_i32<T: Borrow<i32>, O: Write + ?Sized>(
value: T,
output: &mut O,
) -> Result<usize, EmitError> {
Ok(encode_signed(*value.borrow(), output)?)
}
pub fn emit_i64<T: Borrow<i64>, O: Write + ?Sized>(
value: T,
output: &mut O,
) -> Result<usize, EmitError> {
Ok(encode_signed(*value.borrow(), output)?)
}
pub fn emit_vector<I, E, O>(items: I, output: &mut O, emit: E) -> Result<usize, EmitError>
where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Clone,
O: Write + ?Sized,
E: Fn(I::Item, &mut O) -> Result<usize, EmitError>,
{
emit_iterator(items, output, true, emit)
}
pub fn emit_repeated<I, E, O>(items: I, output: &mut O, emit: E) -> Result<usize, EmitError>
where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Clone,
O: Write + ?Sized,
E: Fn(I::Item, &mut O) -> Result<usize, EmitError>,
{
emit_iterator(items, output, false, emit)
}
fn emit_iterator<I, E, O>(
items: I,
output: &mut O,
include_length: bool,
emit: E,
) -> Result<usize, EmitError>
where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Clone,
O: Write + ?Sized,
E: Fn(I::Item, &mut O) -> Result<usize, EmitError>,
{
let mut bytes = 0;
let items = items.into_iter();
if include_length {
bytes += emit_usize(items.clone().count(), output)?;
}
for item in items {
bytes += emit(item, output)?;
}
Ok(bytes)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vectored() {
let bytes: [u8; 4] = [1, 2, 3, 4];
let mut buffer: Vec<u8> = Vec::new();
let emitted = emit_vector(&bytes, &mut buffer, emit_byte).unwrap();
assert_eq!(emitted, 1 + bytes.len());
assert_eq!(buffer[0] as usize, bytes.len());
assert_eq!(&bytes[..], &buffer[1..]);
}
}