use crate::error::{Error, Result};
use crate::types::{Describer, SentTypes, TypeTable};
use crate::wire::{frame, put_bytes, put_float, put_int, put_uint};
pub trait GobType {
fn describe(d: &mut Describer<'_>) -> Result<i64>;
fn compatible(types: &TypeTable, wire: i64) -> bool;
#[doc(hidden)]
fn describe_slice(d: &mut Describer<'_>) -> Result<i64>
where
Self: Sized,
{
let elem = Self::describe(d)?;
Ok(d.slice(std::any::type_name::<Vec<Self>>(), elem))
}
#[doc(hidden)]
fn compatible_slice(types: &TypeTable, wire: i64) -> bool
where
Self: Sized,
{
match types.get(wire).map(|t| &**t) {
Some(crate::WireType::Slice { elem, .. }) => Self::compatible(types, *elem),
_ => false,
}
}
}
pub trait Encode {
fn describe_value(&self, d: &mut Describer<'_>) -> Result<i64>;
fn is_zero(&self) -> bool;
fn frames_as_struct(&self) -> bool {
false
}
fn encode(&self, e: &mut ValueEncoder<'_>) -> Result<()>;
#[doc(hidden)]
fn encode_slice(items: &[Self], e: &mut ValueEncoder<'_>) -> Result<()>
where
Self: Sized,
{
e.uint(items.len() as u64);
for item in items {
item.encode(e)?;
}
Ok(())
}
}
pub struct ValueEncoder<'a> {
pub(crate) out: &'a mut Vec<u8>,
pub(crate) sent: &'a mut SentTypes,
pub(crate) defs: &'a mut Vec<u8>,
}
impl<'a> ValueEncoder<'a> {
pub fn uint(&mut self, u: u64) {
put_uint(self.out, u);
}
pub fn int(&mut self, i: i64) {
put_int(self.out, i);
}
pub fn bool(&mut self, b: bool) {
put_uint(self.out, u64::from(b));
}
pub fn float(&mut self, f: f64) {
put_float(self.out, f);
}
pub fn complex(&mut self, re: f64, im: f64) {
put_float(self.out, re);
put_float(self.out, im);
}
pub fn bytes(&mut self, b: &[u8]) {
put_bytes(self.out, b);
}
pub fn describer(&mut self) -> Describer<'_> {
Describer {
sent: self.sent,
defs: self.defs,
}
}
pub fn structure(&mut self) -> StructEncoder<'_, 'a> {
StructEncoder { e: self, last: -1 }
}
pub fn interface(&mut self, value: Option<(&str, &dyn Encode)>) -> Result<()> {
let Some((name, value)) = value else {
put_uint(self.out, 0);
return Ok(());
};
if name.is_empty() {
return Err(Error::Encode(
"interface value needs a registered type name".into(),
));
}
put_bytes(self.out, name.as_bytes());
let id = value.describe_value(&mut self.describer())?;
put_int(self.out, id);
let mut inner = Vec::new();
{
let mut e = ValueEncoder {
out: &mut inner,
sent: self.sent,
defs: self.defs,
};
if !value.frames_as_struct() {
e.uint(0);
}
value.encode(&mut e)?;
}
put_bytes(self.out, &inner);
Ok(())
}
}
pub struct StructEncoder<'e, 'a> {
e: &'e mut ValueEncoder<'a>,
last: i64,
}
impl StructEncoder<'_, '_> {
pub fn field<T: Encode + ?Sized>(&mut self, index: u32, value: &T) -> Result<()> {
if value.is_zero() {
return Ok(());
}
let index = i64::from(index);
if index <= self.last {
return Err(Error::Encode(format!(
"struct field {index} written out of order"
)));
}
put_uint(self.e.out, (index - self.last) as u64);
self.last = index;
value.encode(self.e)
}
pub fn end(self) {
put_uint(self.e.out, 0);
}
}
#[derive(Debug, Default)]
pub struct Encoder {
sent: SentTypes,
}
impl Encoder {
pub fn new() -> Self {
Self::default()
}
pub fn encode<T: Encode + ?Sized>(&mut self, value: &T) -> Result<Vec<u8>> {
let mut out = Vec::new();
self.encode_into(value, &mut out)?;
Ok(out)
}
pub fn encode_into<T: Encode + ?Sized>(&mut self, value: &T, out: &mut Vec<u8>) -> Result<()> {
let mark = self.sent.begin();
let mut defs = Vec::new();
let mut body = Vec::new();
let result = (|| {
let id = value.describe_value(&mut Describer {
sent: &mut self.sent,
defs: &mut defs,
})?;
put_int(&mut body, id);
let mut e = ValueEncoder {
out: &mut body,
sent: &mut self.sent,
defs: &mut defs,
};
if !value.frames_as_struct() {
e.uint(0);
}
value.encode(&mut e)
})();
if let Err(e) = result {
self.sent.rollback(mark);
return Err(e);
}
out.extend_from_slice(&defs);
frame(out, &body);
Ok(())
}
}