extern crate alloc;
use alloc::{string::String, vec, vec::Vec};
use serde::Serialize;
use serde_json::{Result, Value};
#[derive(Debug)]
pub struct RpcParams(ParamsBuilder);
pub type ExampleHash = [u8; 32];
impl RpcParams {
pub fn new() -> Self {
Self::default()
}
pub fn insert<P: Serialize>(&mut self, value: P) -> Result<()> {
self.0.insert(value)
}
pub fn insert_with_allocation<P: Serialize>(&mut self, value: P) -> Result<()> {
self.0.insert_with_allocation(value)
}
pub fn build(self) -> Option<String> {
self.0.build()
}
pub fn to_json_value(self) -> Result<Value> {
let params = match self.build() {
Some(string) => serde_json::from_str(&string)?,
None => serde_json::json!(vec![Value::Null]),
};
Ok(params)
}
}
impl Default for RpcParams {
fn default() -> Self {
Self(ParamsBuilder::positional())
}
}
const PARAM_BYTES_CAPACITY: usize = 128;
#[derive(Debug)]
pub struct ParamsBuilder {
bytes: Vec<u8>,
start: char,
end: char,
}
impl ParamsBuilder {
fn new(start: char, end: char) -> Self {
ParamsBuilder {
bytes: Vec::new(),
start,
end,
}
}
pub(crate) fn positional() -> Self {
Self::new('[', ']')
}
fn maybe_initialize(&mut self) {
if self.bytes.is_empty() {
self.bytes.reserve(PARAM_BYTES_CAPACITY);
self.bytes.push(self.start as u8);
}
}
pub(crate) fn build(mut self) -> Option<String> {
if self.bytes.is_empty() {
return None;
}
let idx = self.bytes.len() - 1;
if self.bytes[idx] == b',' {
self.bytes[idx] = self.end as u8;
} else {
self.bytes.push(self.end as u8);
}
Some(unsafe { String::from_utf8_unchecked(self.bytes) })
}
#[cfg(feature = "std")]
pub(crate) fn insert<P: Serialize>(&mut self, value: P) -> Result<()> {
self.maybe_initialize();
serde_json::to_writer(&mut self.bytes, &value)?;
self.bytes.push(b',');
Ok(())
}
#[cfg(not(feature = "std"))]
pub(crate) fn insert<P: Serialize>(&mut self, value: P) -> Result<()> {
self.insert_with_allocation(value)
}
pub(crate) fn insert_with_allocation<P: Serialize>(&mut self, value: P) -> Result<()> {
self.maybe_initialize();
let mut serialized_vec = serde_json::to_vec(&value)?;
self.bytes.append(&mut serialized_vec);
self.bytes.push(b',');
Ok(())
}
}
#[macro_export]
macro_rules! rpc_params {
($($param:expr),*) => {
{
let mut params = RpcParams::new();
$(
if let Err(err) = params.insert($param) {
panic!("Parameter `{}` cannot be serialized: {:?}", stringify!($param), err);
}
)*
params
}
};
}