1use wasm_bindgen::prelude::*;
4use wowlab_parsers::parcel::{
5 Codec, DecodeExportError, EncodeExportError, ResultExport, decode_result_export,
6 encode_result_export,
7};
8use wowlab_types::wasm_error;
9
10use super::dto::parcel::{ParcelConfigDto, ParcelDecodedDto, ParcelLimitsDto, ResultExportDto};
11
12wasm_error! {
13 #[derive(Debug)]
14 #[non_exhaustive]
15 pub enum WasmParcelError {
16 Config(String) => "ParcelConfigError",
17 Encode(String) => "ParcelEncodeError",
18 Decode(String) => "ParcelDecodeError",
19 Serialize(String) => "ParcelSerializeError",
20 }
21}
22
23fn build_codec(config: &ParcelConfigDto) -> Result<Codec, WasmParcelError> {
24 Codec::new(config.clone().into_codec_config())
25 .map_err(|error| WasmParcelError::Config(error.to_string()))
26}
27
28#[wasm_bindgen(js_name = parcelEncode)]
30pub fn wasm_parcel_encode(
31 config: &ParcelConfigDto,
32 content_type: Option<String>,
33 payload: &[u8],
34) -> Result<String, WasmParcelError> {
35 let codec = build_codec(config)?;
36
37 match content_type {
38 Some(content_type) => codec.encode(payload, Some(&content_type)),
39 None => codec.encode(payload, None),
40 }
41 .map_err(|error| WasmParcelError::Encode(error.code().to_owned()))
42}
43
44#[wasm_bindgen(js_name = parcelDecode)]
45pub fn wasm_parcel_decode(
46 config: &ParcelConfigDto,
47 encoded: &str,
48) -> Result<ParcelDecodedDto, WasmParcelError> {
49 let codec = build_codec(config)?;
50 let decoded = codec
51 .decode(encoded)
52 .map_err(|e| WasmParcelError::Decode(e.code().to_owned()))?;
53
54 Ok(ParcelDecodedDto {
55 payload: decoded.payload,
56 meta: decoded.meta.into(),
57 })
58}
59
60#[wasm_bindgen(js_name = parcelInspect)]
62pub fn wasm_parcel_inspect(
63 config: &ParcelConfigDto,
64 encoded: &str,
65) -> Result<String, WasmParcelError> {
66 let codec = build_codec(config)?;
67
68 Ok(codec.inspect(encoded))
69}
70
71#[wasm_bindgen(js_name = parcelEncodeResultExport)]
72pub fn wasm_parcel_encode_result_export(
73 export: &ResultExportDto,
74) -> Result<String, WasmParcelError> {
75 let canonical: ResultExport = export.clone().into();
76
77 encode_result_export(&canonical).map_err(|error: EncodeExportError| {
78 error.parcel_error().map_or_else(
79 || WasmParcelError::Encode(error.to_string()),
80 |parcel| WasmParcelError::Encode(parcel.code().to_owned()),
81 )
82 })
83}
84
85#[wasm_bindgen(js_name = parcelDecodeResultExport)]
86pub fn wasm_parcel_decode_result_export(encoded: &str) -> Result<ResultExportDto, WasmParcelError> {
87 let canonical = decode_result_export(encoded).map_err(|error: DecodeExportError| {
88 if let Some(parcel) = error.parcel_error() {
89 return WasmParcelError::Decode(parcel.code().to_owned());
90 }
91
92 if let Some(actual) = error.wrong_content_type_value() {
93 return WasmParcelError::Decode(format!("wrong content_type: {actual}"));
94 }
95
96 if let Some(version) = error.unsupported_schema_version() {
97 return WasmParcelError::Decode(format!("unsupported schema version: {version}"));
98 }
99
100 WasmParcelError::Decode(error.to_string())
101 })?;
102
103 Ok(canonical.into())
104}
105
106#[wasm_bindgen(js_name = parcelDefaultLimits)]
107#[must_use]
108pub fn wasm_parcel_default_limits() -> ParcelLimitsDto {
109 ParcelLimitsDto::defaults()
110}
111
112#[wasm_bindgen(js_name = parcelResultExportPrefix)]
113#[must_use]
114pub fn wasm_parcel_result_export_prefix() -> String {
115 wowlab_parsers::parcel::RESULT_EXPORT_PREFIX.to_owned()
116}