workflow_wasm/extensions/
jsvalue.rs1use crate::error::Error;
8use js_sys::Uint8Array;
9use wasm_bindgen::prelude::*;
10
11pub trait JsValueExtension {
13 fn try_as_u8(&self) -> Result<u8, Error>;
15 fn try_as_u16(&self) -> Result<u16, Error>;
17 fn try_as_u32(&self) -> Result<u32, Error>;
19 fn try_as_u64(&self) -> Result<u64, Error>;
21 fn try_as_vec_u8(&self) -> Result<Vec<u8>, Error>;
23}
24
25impl JsValueExtension for JsValue {
26 fn try_as_u8(&self) -> Result<u8, Error> {
27 let f = self
28 .as_f64()
29 .ok_or_else(|| Error::WrongType(format!("value is not a number: `{self:?}`")))?;
30 if f < 0.0 || f > u8::MAX as f64 {
31 Err(Error::Bounds(format!(
32 "value `{f}` is out of bounds (0..{})",
33 u8::MAX
34 )))
35 } else {
36 Ok(f as u8)
37 }
38 }
39
40 fn try_as_u16(&self) -> Result<u16, Error> {
41 let f = self
42 .as_f64()
43 .ok_or_else(|| Error::WrongType(format!("value is not a number: `{self:?}`")))?;
44 if f < 0.0 || f > u16::MAX as f64 {
45 Err(Error::Bounds(format!(
46 "value `{f}` is ount of bounds (0..{})",
47 u16::MAX
48 )))
49 } else {
50 Ok(f as u16)
51 }
52 }
53
54 fn try_as_u32(&self) -> Result<u32, Error> {
55 let f = self
56 .as_f64()
57 .ok_or_else(|| Error::WrongType(format!("value is not a number: `{self:?}`")))?;
58 if f < 0.0 || f > u32::MAX as f64 {
59 Err(Error::Bounds(format!(
60 "value `{f}` is ount of bounds (0..{})",
61 u32::MAX
62 )))
63 } else {
64 Ok(f as u32)
65 }
66 }
67
68 fn try_as_u64(&self) -> Result<u64, Error> {
69 if self.is_string() {
70 let hex_str = self.as_string().unwrap();
71 if hex_str.len() > 16 {
72 Err(Error::WrongSize(
73 "try_as_u64(): supplied string must be < 16 chars".to_string(),
74 ))
75 } else {
76 let mut out = [0u8; 8];
77 let mut input = [b'0'; 16];
78 let start = input.len() - hex_str.len();
79 input[start..].copy_from_slice(hex_str.as_bytes());
80 faster_hex::hex_decode(&input, &mut out)?;
81 Ok(u64::from_be_bytes(out))
82 }
83 } else if self.is_bigint() {
84 Ok(self.clone().try_into().map_err(|err| {
85 Error::Convert(format!(
86 "try_as_u64(): unable to convert BigInt value to u64: `{self:?}`: {err:?}"
87 ))
88 })?)
89 } else {
90 Ok(self
91 .as_f64()
92 .ok_or_else(|| Error::WrongType(format!("value is not a number ({self:?})")))?
93 as u64)
94 }
95 }
96
97 fn try_as_vec_u8(&self) -> Result<Vec<u8>, Error> {
98 if self.is_string() {
99 let hex_string = self.as_string().unwrap();
100 let len = hex_string.len();
101 if len == 0 {
102 Ok(vec![])
103 } else if len & 0x1 == 1 {
104 Err(Error::HexStringNotEven(hex_string))
105 } else {
106 let mut vec = vec![0u8; hex_string.len() / 2];
107 faster_hex::hex_decode(hex_string.as_bytes(), &mut vec)?;
108 Ok(vec)
109 }
110 } else if self.is_object() {
111 let array = Uint8Array::new(self);
112 let vec: Vec<u8> = array.to_vec();
113 Ok(vec)
114 } else {
115 Err(Error::WrongType(
116 "value is not a hex string or an array".to_string(),
117 ))
118 }
119 }
120}