use std::fmt::Debug;
use std::mem::replace;
use std::panic::AssertUnwindSafe;
use std::panic::catch_unwind;
use std::panic::resume_unwind;
use qubit_budget::ResourceQuantity;
use qubit_budget::json::JsonEncodeLimits;
use qubit_budget::json::JsonEncodeSession;
use qubit_io::Output;
use qubit_json::encode::JsonEncodeError;
use qubit_json::encode::JsonEncoder;
use serde::Serialize;
pub(crate) fn encode<T, R, Q>(
value: &T,
session: &mut JsonEncodeSession<'_, R, Q>,
) -> Result<Vec<u8>, JsonEncodeError<R, Q>>
where
T: Serialize + ?Sized,
R: Clone + Debug + 'static,
Q: ResourceQuantity + 'static,
{
let placeholder = JsonEncodeSession::from_limits(JsonEncodeLimits::<R, Q>::builder().build());
let owned = replace(session, placeholder);
let mut encoder = JsonEncoder::new(owned);
let result = catch_unwind(AssertUnwindSafe(|| encoder.to_vec(value)));
*session = encoder.into_session();
match result {
Ok(result) => result,
Err(payload) => resume_unwind(payload),
}
}
pub(crate) fn write_buffered<W, T, R, Q>(
mut writer: W,
value: &T,
session: &mut JsonEncodeSession<'_, R, Q>,
) -> Result<(), JsonEncodeError<R, Q>>
where
W: Output<Item = u8>,
T: Serialize + ?Sized,
R: Clone + Debug + 'static,
Q: ResourceQuantity + 'static,
{
let placeholder = JsonEncodeSession::from_limits(JsonEncodeLimits::<R, Q>::builder().build());
let owned = replace(session, placeholder);
let mut encoder = JsonEncoder::new(owned);
let result = catch_unwind(AssertUnwindSafe(|| encoder.write_buffered(&mut writer, value)));
*session = encoder.into_session();
match result {
Ok(result) => result,
Err(payload) => resume_unwind(payload),
}
}
pub(crate) fn write_incremental<W, T, R, Q>(
mut writer: W,
value: &T,
session: &mut JsonEncodeSession<'_, R, Q>,
) -> Result<(), JsonEncodeError<R, Q>>
where
W: Output<Item = u8>,
T: Serialize + ?Sized,
R: Clone + Debug + 'static,
Q: ResourceQuantity + 'static,
{
let placeholder = JsonEncodeSession::from_limits(JsonEncodeLimits::<R, Q>::builder().build());
let owned = replace(session, placeholder);
let mut encoder = JsonEncoder::new(owned);
let result = catch_unwind(AssertUnwindSafe(|| encoder.write_incremental(&mut writer, value)));
*session = encoder.into_session();
match result {
Ok(result) => result,
Err(payload) => resume_unwind(payload),
}
}