How to extend `serde_v8` to handle custom logic?
Hi guys! I'm currently I have the following struct to represent my Tensor object:
It's working well with
---
From the Js land I need to pass an object with the given format, where
The problem is that even if I use
I can't handle
// Type alias for TensorElementType (External lib proxy)
// https://serde.rs/remote-derive.html
#[derive(Debug, Serialize, Deserialize)]
#[serde(remote = "TensorElementType", rename_all = "lowercase")]
pub enum JsTensorType {
/// 32-bit floating point number, equivalent to Rust's `f32`.
Float32,
/// Unsigned 8-bit integer, equivalent to Rust's `u8`.
Uint8,
/// String, equivalent to Rust's `String`.
String,
...
}
#[derive(Serialize, Deserialize)]
struct JsTensorTypeSerdeHelper(#[serde(with = "JsTensorType")] TensorElementType);
#[derive(Debug, Serialize, Deserialize)]
pub struct JsTensor {
#[serde(rename = "type", with = "JsTensorType")]
data_type: TensorElementType,
data: JsBuffer,
dims: Vec<i64>,
}
// Type alias for TensorElementType (External lib proxy)
// https://serde.rs/remote-derive.html
#[derive(Debug, Serialize, Deserialize)]
#[serde(remote = "TensorElementType", rename_all = "lowercase")]
pub enum JsTensorType {
/// 32-bit floating point number, equivalent to Rust's `f32`.
Float32,
/// Unsigned 8-bit integer, equivalent to Rust's `u8`.
Uint8,
/// String, equivalent to Rust's `String`.
String,
...
}
#[derive(Serialize, Deserialize)]
struct JsTensorTypeSerdeHelper(#[serde(with = "JsTensorType")] TensorElementType);
#[derive(Debug, Serialize, Deserialize)]
pub struct JsTensor {
#[serde(rename = "type", with = "JsTensorType")]
data_type: TensorElementType,
data: JsBuffer,
dims: Vec<i64>,
}
#[serde]
attribute on my op
function. The problem is that I need to extend it to also support string
arrays like: ["foo", "bar"]
, and I can't handle it as JsBuffer
so I need to explicit do pattern matching:
enum JsTensorData {
StringArray(Vec<String>),
TypedArrayBuffer(JsBuffer),
}
pub struct JsTensor {
data_type: TensorElementType,
data: JsTensorData,
dims: Vec<i64>,
}
enum JsTensorData {
StringArray(Vec<String>),
TypedArrayBuffer(JsBuffer),
}
pub struct JsTensor {
data_type: TensorElementType,
data: JsTensorData,
dims: Vec<i64>,
}
TypedArray
could be any theses:
type Tensor = {
type: 'float32' | 'uint8' | 'string' // etc...
data: TypedArray | string[]
dims: number[]
}
type Tensor = {
type: 'float32' | 'uint8' | 'string' // etc...
data: TypedArray | string[]
dims: number[]
}
#[serde(untagged)]
:
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
enum JsTensorData {
StringArray(Vec<String>),
TypedArrayBuffer(JsBuffer),
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
enum JsTensorData {
StringArray(Vec<String>),
TypedArrayBuffer(JsBuffer),
}
JsBuffer
, cause of the following error:
TypeError: data did not match any variant of untagged enum JsTensorData
TypeError: data did not match any variant of untagged enum JsTensorData
1 Reply
I'm already did the followin
But I need to handle it like this from my
from_v8
impl:
impl<'a> FromV8<'a> for JsTensor {
type Error = StdAnyError;
fn from_v8(
scope: &mut deno_core::v8::HandleScope<'a>,
value: deno_core::v8::Local<'a, deno_core::v8::Value>,
) -> Result<Self, Self::Error> {
// Deserialize the raw `v8::Value` into a proxy struct to inspect "type" and data
#[derive(Deserialize)]
struct RawJsTensor<'a> {
#[serde(rename = "type", with = "JsTensorType")]
data_type: TensorElementType,
data: serde_v8::Value<'a>, // Keep data as raw `serde_v8::Value` for now
dims: Vec<i64>,
}
let js_tensor = serde_v8::from_v8::<RawJsTensor>(scope, value).map_err(AnyError::from)?;
// Apply the correct `JsTensorData`
let data = match js_tensor.data_type {
TensorElementType::String => JsTensorData::StringArray(
serde_v8::from_v8(scope, js_tensor.data.v8_value).map_err(AnyError::from)?,
),
_ => JsTensorData::TypedArrayBuffer(
serde_v8::from_v8(scope, js_tensor.data.v8_value).map_err(AnyError::from)?,
),
};
Ok(JsTensor {
data,
data_type: js_tensor.data_type,
dims: js_tensor.dims,
})
}
}
impl<'a> FromV8<'a> for JsTensor {
type Error = StdAnyError;
fn from_v8(
scope: &mut deno_core::v8::HandleScope<'a>,
value: deno_core::v8::Local<'a, deno_core::v8::Value>,
) -> Result<Self, Self::Error> {
// Deserialize the raw `v8::Value` into a proxy struct to inspect "type" and data
#[derive(Deserialize)]
struct RawJsTensor<'a> {
#[serde(rename = "type", with = "JsTensorType")]
data_type: TensorElementType,
data: serde_v8::Value<'a>, // Keep data as raw `serde_v8::Value` for now
dims: Vec<i64>,
}
let js_tensor = serde_v8::from_v8::<RawJsTensor>(scope, value).map_err(AnyError::from)?;
// Apply the correct `JsTensorData`
let data = match js_tensor.data_type {
TensorElementType::String => JsTensorData::StringArray(
serde_v8::from_v8(scope, js_tensor.data.v8_value).map_err(AnyError::from)?,
),
_ => JsTensorData::TypedArrayBuffer(
serde_v8::from_v8(scope, js_tensor.data.v8_value).map_err(AnyError::from)?,
),
};
Ok(JsTensor {
data,
data_type: js_tensor.data_type,
dims: js_tensor.dims,
})
}
}
op
function:
#[op2(async)]
#[serde]
pub async fn op_sb_ai_ort_run_session(
state: Rc<RefCell<OpState>>,
#[string] model_id: String,
#[serde] input_values: HashMap<String, JsTensor>,
) -> Result<HashMap<String, ToJsTensor>> {
...
}
#[op2(async)]
#[serde]
pub async fn op_sb_ai_ort_run_session(
state: Rc<RefCell<OpState>>,
#[string] model_id: String,
#[serde] input_values: HashMap<String, JsTensor>,
) -> Result<HashMap<String, ToJsTensor>> {
...
}