Skip to main content

dpp_plugin_sdk/
codec.rs

1//! Pure glue (host-testable, no linear-memory side effects): JSON
2//! encode/decode between a [`DppSectorPlugin`] and the ABI byte buffers.
3
4use dpp_plugin_traits::{AbiResult, DppSectorPlugin, PluginError, PluginInput};
5use serde::Serialize;
6
7pub(crate) fn to_bytes<T: Serialize>(value: &T) -> Vec<u8> {
8    serde_json::to_vec(value).unwrap_or_default()
9}
10
11fn parse_input(bytes: &[u8]) -> Result<PluginInput, PluginError> {
12    serde_json::from_slice(bytes).map_err(|e| PluginError::InvalidInput(e.to_string()))
13}
14
15/// Parse `input`, run `call` on success, wrap the outcome as an [`AbiResult`],
16/// and serialise it to bytes. Shared by every entry point below — they differ
17/// only in which plugin method `call` invokes and how `wrap` turns a success
18/// value into the envelope's JSON payload.
19fn dispatch<T>(
20    input: &[u8],
21    call: impl FnOnce(PluginInput) -> Result<T, PluginError>,
22    wrap: impl FnOnce(T) -> AbiResult,
23) -> Vec<u8> {
24    let outcome = match parse_input(input).and_then(call) {
25        Ok(value) => wrap(value),
26        Err(e) => AbiResult::Error(e),
27    };
28    to_bytes(&outcome)
29}
30
31/// Serialise the plugin's [`PluginMeta`](dpp_plugin_traits::PluginMeta) to JSON bytes.
32pub fn metadata_bytes<P: DppSectorPlugin>(plugin: &P) -> Vec<u8> {
33    to_bytes(&plugin.meta())
34}
35
36/// Serialise the plugin's [`PluginCapabilities`](dpp_plugin_traits::PluginCapabilities) to JSON bytes.
37pub fn describe_bytes<P: DppSectorPlugin>(plugin: &P) -> Vec<u8> {
38    to_bytes(&plugin.capabilities())
39}
40
41/// Run `validate_input` and serialise the [`AbiResult`] envelope.
42pub fn validate_bytes<P: DppSectorPlugin>(plugin: &P, input: &[u8]) -> Vec<u8> {
43    dispatch(
44        input,
45        |value| plugin.validate_input(&value),
46        |()| AbiResult::Ok(serde_json::Value::Null),
47    )
48}
49
50/// Run `calculate_metrics` and serialise the [`AbiResult`] envelope.
51pub fn calculate_metrics_bytes<P: DppSectorPlugin>(plugin: &P, input: &[u8]) -> Vec<u8> {
52    dispatch(
53        input,
54        |value| plugin.calculate_metrics(&value),
55        |result| AbiResult::ok(&result),
56    )
57}
58
59/// Run `generate_passport` and serialise the [`AbiResult`] envelope.
60pub fn generate_passport_bytes<P: DppSectorPlugin>(plugin: &P, input: &[u8]) -> Vec<u8> {
61    dispatch(
62        input,
63        |value| plugin.generate_passport(value),
64        AbiResult::Ok,
65    )
66}