use crate::params;
use crate::signature;
use crate::wire::errors::MarshalError;
use crate::wire::marshal::base::*;
use crate::wire::marshal::MarshalContext;
use crate::wire::util::*;
pub fn marshal_param(p: ¶ms::Param, ctx: &mut MarshalContext) -> Result<(), MarshalError> {
match p {
params::Param::Base(b) => marshal_base_param(b, ctx),
params::Param::Container(c) => marshal_container_param(c, ctx),
}
}
fn marshal_array(
array: &[params::Param],
sig: &signature::Type,
ctx: &mut MarshalContext,
) -> Result<(), MarshalError> {
ctx.align_to(4);
let len_pos = ctx.buf.len();
ctx.buf.extend_from_slice(&[0, 0, 0, 0]);
ctx.align_to(sig.get_alignment());
let content_pos = ctx.buf.len();
for p in array {
marshal_param(p, ctx)?;
}
let len = ctx.buf.len() - content_pos;
insert_u32(
ctx.byteorder,
len as u32,
&mut ctx.buf[len_pos..len_pos + 4],
);
Ok(())
}
fn marshal_struct(params: &[params::Param], ctx: &mut MarshalContext) -> Result<(), MarshalError> {
ctx.align_to(8);
for p in params {
marshal_param(p, ctx)?;
}
Ok(())
}
fn marshal_variant(var: ¶ms::Variant, ctx: &mut MarshalContext) -> Result<(), MarshalError> {
let mut sig_str = String::new();
var.sig.to_str(&mut sig_str);
marshal_signature(&sig_str, ctx.buf)?;
marshal_param(&var.value, ctx)?;
Ok(())
}
fn marshal_dict(dict: ¶ms::DictMap, ctx: &mut MarshalContext) -> Result<(), MarshalError> {
ctx.align_to(4);
let len_pos = ctx.buf.len();
ctx.buf.extend_from_slice(&[0, 0, 0, 0]);
ctx.align_to(8);
let content_pos = ctx.buf.len();
for (key, value) in dict {
ctx.align_to(8);
marshal_base_param(key, ctx)?;
marshal_param(value, ctx)?;
}
let len = ctx.buf.len() - content_pos;
insert_u32(
ctx.byteorder,
len as u32,
&mut ctx.buf[len_pos..len_pos + 4],
);
Ok(())
}
pub fn marshal_container_param(
p: ¶ms::Container,
ctx: &mut MarshalContext,
) -> Result<(), MarshalError> {
match p {
params::Container::Array(params) => {
params::validate_array(¶ms.values, ¶ms.element_sig)?;
marshal_array(¶ms.values, ¶ms.element_sig, ctx)?;
}
params::Container::ArrayRef(params) => {
params::validate_array(params.values, ¶ms.element_sig)?;
marshal_array(params.values, ¶ms.element_sig, ctx)?;
}
params::Container::Struct(params) => {
marshal_struct(params, ctx)?;
}
params::Container::StructRef(params) => {
marshal_struct(params, ctx)?;
}
params::Container::Dict(params) => {
params::validate_dict(¶ms.map, params.key_sig, ¶ms.value_sig)?;
marshal_dict(¶ms.map, ctx)?;
}
params::Container::DictRef(params) => {
params::validate_dict(params.map, params.key_sig, ¶ms.value_sig)?;
marshal_dict(params.map, ctx)?;
}
params::Container::Variant(variant) => {
marshal_variant(variant, ctx)?;
}
}
Ok(())
}