Skip to main content

workflow_rpc/
encoding.rs

1//!
2//! Module containing a helper [`Encoding`] enum use in RPC server constructors.
3//!
4
5use crate::error::Error;
6use serde::{Deserialize, Serialize};
7use std::{
8    fmt::{Debug, Display, Formatter},
9    str::FromStr,
10};
11use wasm_bindgen::convert::TryFromJsValue;
12use wasm_bindgen::prelude::*;
13
14/// wRPC protocol encoding: `Borsh` or `JSON`
15/// @category Transport
16#[derive(Debug, Clone, Copy, Serialize, Deserialize, Hash, Eq, PartialEq)]
17#[wasm_bindgen]
18#[serde(rename_all = "kebab-case")]
19pub enum Encoding {
20    /// Compact binary encoding using Borsh.
21    Borsh = 0,
22    /// Human-readable text encoding using Serde JSON.
23    #[serde(rename = "json")]
24    SerdeJson = 1,
25}
26
27impl Display for Encoding {
28    #[inline]
29    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
30        let s = match self {
31            Encoding::Borsh => "borsh",
32            Encoding::SerdeJson => "json",
33        };
34        f.write_str(s)
35    }
36}
37
38impl FromStr for Encoding {
39    type Err = Error;
40    fn from_str(s: &str) -> Result<Self, Self::Err> {
41        match s.to_lowercase().as_str() {
42            "borsh" => Ok(Encoding::Borsh),
43            "json" => Ok(Encoding::SerdeJson),
44            "serde-json" => Ok(Encoding::SerdeJson),
45            _ => Err(Error::Encoding(
46                "invalid encoding: {s} (must be: 'borsh' or 'json')".to_string(),
47            )),
48        }
49    }
50}
51
52impl TryFrom<u8> for Encoding {
53    type Error = Error;
54    fn try_from(value: u8) -> Result<Self, Self::Error> {
55        match value {
56            0 => Ok(Encoding::Borsh),
57            1 => Ok(Encoding::SerdeJson),
58            _ => Err(Error::Encoding(
59                "invalid encoding: {value} (must be: Encoding.Borsh (0) or Encoding.JSON (1))"
60                    .to_string(),
61            )),
62        }
63    }
64}
65
66impl TryFrom<JsValue> for Encoding {
67    type Error = Error;
68    fn try_from(value: JsValue) -> Result<Self, Self::Error> {
69        match Encoding::try_from_js_value(value.clone()) {
70            Ok(encoding) => Ok(encoding),
71            _ => {
72                if let Some(v) = value.as_f64() {
73                    Ok(Encoding::try_from(v as u8)?)
74                } else if let Some(string) = value.as_string() {
75                    Encoding::from_str(&string)
76                } else {
77                    Err(Error::Encoding(
78                        "invalid encoding value: {value:?}".to_string(),
79                    ))
80                }
81            }
82        }
83    }
84}
85
86const ENCODING: [Encoding; 2] = [Encoding::Borsh, Encoding::SerdeJson];
87
88impl Encoding {
89    /// Iterate over all supported encodings (`Borsh` and `SerdeJson`).
90    pub fn iter() -> impl Iterator<Item = &'static Encoding> {
91        ENCODING.iter()
92    }
93}