Make front codegen work with multi-field structs containing Strings, create decky template
This commit is contained in:
parent
ed5f96361b
commit
9171682e4d
15 changed files with 606 additions and 601 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "templates/decky"]
|
||||
path = templates/decky
|
||||
url = https://git.ngni.us/NG-SD-Plugins/usdpl-decky-plugin-template
|
833
Cargo.lock
generated
833
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,8 @@ members = [
|
|||
]
|
||||
|
||||
exclude = [
|
||||
"templates/decky/backend"
|
||||
"templates/decky/backend",
|
||||
"templates/decky/src/rust"
|
||||
]
|
||||
|
||||
resolver = "2"
|
||||
|
|
1
templates/decky
Submodule
1
templates/decky
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit b82d3edf77deba94beef53d4d32c705487da918c
|
|
@ -11,8 +11,8 @@ description = "Universal Steam Deck Plugin Library back-end"
|
|||
[features]
|
||||
default = ["blocking"]
|
||||
decky = ["usdpl-core/decky"]
|
||||
any = []
|
||||
blocking = [] # synchronous API for async functionality, using tokio
|
||||
#encrypt = ["usdpl-core", "obfstr", "hex"]
|
||||
|
||||
[dependencies]
|
||||
usdpl-core = { version = "1.0", path = "../usdpl-core"}
|
||||
|
@ -35,10 +35,6 @@ tokio = { version = "1", features = [ "full" ]}
|
|||
async-trait = "0.1.57"
|
||||
async-recursion = "1.0.0"
|
||||
|
||||
# encryption helpers
|
||||
obfstr = { version = "0.3", optional = true }
|
||||
hex = { version = "0.4", optional = true }
|
||||
|
||||
# translations
|
||||
gettext-ng = { version = "0.4.1" }
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@ use std::path::PathBuf;
|
|||
|
||||
/// The home directory of the user currently running the Steam Deck UI.
|
||||
pub fn home() -> Option<PathBuf> {
|
||||
#[cfg(not(any(feature = "decky", feature = "crankshaft")))]
|
||||
#[cfg(not(any(feature = "decky")))]
|
||||
let result = crate::api_any::dirs::home();
|
||||
#[cfg(all(feature = "decky", not(any(feature = "crankshaft"))))]
|
||||
#[cfg(all(feature = "decky", not(any(feature = "any"))))]
|
||||
let result = crate::api_decky::home()
|
||||
.ok()
|
||||
.map(|x| PathBuf::from(x).join("..").canonicalize().ok())
|
||||
|
@ -17,9 +17,9 @@ pub fn home() -> Option<PathBuf> {
|
|||
|
||||
/// The plugin's root folder.
|
||||
pub fn plugin() -> Option<PathBuf> {
|
||||
#[cfg(not(any(feature = "decky", feature = "crankshaft")))]
|
||||
#[cfg(not(any(feature = "decky")))]
|
||||
let result = None; // TODO
|
||||
#[cfg(all(feature = "decky", not(any(feature = "crankshaft"))))]
|
||||
#[cfg(all(feature = "decky", not(any(feature = "any"))))]
|
||||
let result = crate::api_decky::plugin_dir().ok().map(|x| x.into());
|
||||
|
||||
result
|
||||
|
@ -27,9 +27,9 @@ pub fn plugin() -> Option<PathBuf> {
|
|||
|
||||
/// The recommended log directory
|
||||
pub fn log() -> Option<PathBuf> {
|
||||
#[cfg(not(any(feature = "decky", feature = "crankshaft")))]
|
||||
#[cfg(not(any(feature = "decky")))]
|
||||
let result = crate::api_any::dirs::log();
|
||||
#[cfg(all(feature = "decky", not(any(feature = "crankshaft"))))]
|
||||
#[cfg(all(feature = "decky", not(any(feature = "any"))))]
|
||||
let result = crate::api_decky::log_dir().ok().map(|x| x.into());
|
||||
|
||||
result
|
||||
|
|
|
@ -55,7 +55,7 @@ fn generate_service_methods(
|
|||
#field_name: #js_type_name,
|
||||
});
|
||||
params_to_fields.push(quote::quote! {
|
||||
#field_name: #rs_type_name::from_wasm(#field_name.into()),//: #field_name,
|
||||
#field_name: #rs_type_name::from_wasm(#field_name),//: #field_name,
|
||||
});
|
||||
}
|
||||
let params_to_fields_transformer = if input_type.field.len() == 1 {
|
||||
|
@ -67,11 +67,11 @@ fn generate_service_methods(
|
|||
.expect("Protobuf message field needs a name")
|
||||
);
|
||||
quote::quote! {
|
||||
let val = #method_input::from_wasm(#field_name.into());
|
||||
let val = #method_input::from_wasm(#field_name);
|
||||
}
|
||||
} else if input_type.field.is_empty() {
|
||||
quote::quote! {
|
||||
let val = #method_input {};
|
||||
let val = ();
|
||||
}
|
||||
} else {
|
||||
quote::quote! {
|
||||
|
@ -94,22 +94,8 @@ fn generate_service_methods(
|
|||
},
|
||||
Err(e) => {
|
||||
if let Some(e_handler) = &self.error_handler {
|
||||
let error_info = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("service"),
|
||||
&JsValue::from(self.service.descriptor())
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("method"),
|
||||
&JsValue::from(#method_name_str)
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("error"),
|
||||
&JsValue::from("todo"/*TODO*/)
|
||||
).unwrap();
|
||||
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||
|
||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||
// log error
|
||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||
|
@ -145,22 +131,8 @@ fn generate_service_methods(
|
|||
},
|
||||
Err(e) => {
|
||||
if let Some(e_handler) = &self.error_handler {
|
||||
let error_info = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("service"),
|
||||
&JsValue::from(self.service.descriptor())
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("method"),
|
||||
&JsValue::from(#method_name_str)
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("error"),
|
||||
&JsValue::from("todo"/*TODO*/)
|
||||
).unwrap();
|
||||
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||
|
||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||
// log error
|
||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||
|
@ -215,7 +187,7 @@ fn generate_service_methods(
|
|||
}
|
||||
} else if input_type.field.is_empty() {
|
||||
quote::quote! {
|
||||
let val = #method_input {};
|
||||
let val = ();
|
||||
}
|
||||
} else {
|
||||
quote::quote! {
|
||||
|
@ -236,22 +208,8 @@ fn generate_service_methods(
|
|||
match next_result {
|
||||
Err(e) => {
|
||||
if let Some(e_handler) = &self.error_handler {
|
||||
let error_info = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("service"),
|
||||
&JsValue::from(self.service.descriptor())
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("method"),
|
||||
&JsValue::from(#method_name_str)
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("error"),
|
||||
&JsValue::from("todo"/*TODO*/)
|
||||
).unwrap();
|
||||
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||
|
||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||
// log error
|
||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||
|
@ -293,22 +251,8 @@ fn generate_service_methods(
|
|||
},
|
||||
Err(e) => {
|
||||
if let Some(e_handler) = &self.error_handler {
|
||||
let error_info = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("service"),
|
||||
&JsValue::from(self.service.descriptor())
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("method"),
|
||||
&JsValue::from(#method_name_str)
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("error"),
|
||||
&JsValue::from("todo"/*TODO*/)
|
||||
).unwrap();
|
||||
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||
|
||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||
// log error
|
||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||
|
@ -342,22 +286,8 @@ fn generate_service_methods(
|
|||
match next_result {
|
||||
Err(e) => {
|
||||
if let Some(e_handler) = &self.error_handler {
|
||||
let error_info = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("service"),
|
||||
&JsValue::from(self.service.descriptor())
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("method"),
|
||||
&JsValue::from(#method_name_str)
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("error"),
|
||||
&JsValue::from("todo"/*TODO*/)
|
||||
).unwrap();
|
||||
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||
|
||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||
// log error
|
||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||
|
@ -399,22 +329,8 @@ fn generate_service_methods(
|
|||
},
|
||||
Err(e) => {
|
||||
if let Some(e_handler) = &self.error_handler {
|
||||
let error_info = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("service"),
|
||||
&JsValue::from(self.service.descriptor())
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("method"),
|
||||
&JsValue::from(#method_name_str)
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("error"),
|
||||
&JsValue::from("todo"/*TODO*/)
|
||||
).unwrap();
|
||||
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||
|
||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||
// log error
|
||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||
|
@ -622,7 +538,21 @@ fn generate_wasm_struct_interop(
|
|||
if descriptor.field.len() == 0 {
|
||||
quote::quote! {
|
||||
pub type #msg_name = ();
|
||||
pub type #msg_name_wasm = #msg_name;
|
||||
pub type #msg_name_wasm = JsValue;//#msg_name;
|
||||
|
||||
impl std::convert::Into<super::#super_msg_name> for #msg_name {
|
||||
#[inline]
|
||||
fn into(self) -> super::#super_msg_name {
|
||||
super::#super_msg_name {}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<super::#super_msg_name> for #msg_name {
|
||||
#[inline]
|
||||
fn from(_: super::#super_msg_name) -> Self {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
#(#gen_nested_types)*
|
||||
|
||||
|
@ -662,7 +592,8 @@ fn generate_wasm_struct_interop(
|
|||
}
|
||||
}
|
||||
};*/
|
||||
|
||||
let into_converter_tokens = type_enum.to_into_prost_type();
|
||||
let from_converter_tokens = type_enum.to_from_prost_type(&field_name);
|
||||
|
||||
quote::quote! {
|
||||
pub type #msg_name = #type_name;
|
||||
|
@ -672,7 +603,7 @@ fn generate_wasm_struct_interop(
|
|||
#[inline]
|
||||
fn into(self) -> super::#super_msg_name {
|
||||
super::#super_msg_name {
|
||||
#field_name: self
|
||||
#field_name: self #into_converter_tokens
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -681,7 +612,8 @@ fn generate_wasm_struct_interop(
|
|||
#[inline]
|
||||
#[allow(unused_variables)]
|
||||
fn from(other: super::#super_msg_name) -> Self {
|
||||
other.#field_name
|
||||
#from_converter_tokens
|
||||
//other.#field_name
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -692,8 +624,11 @@ fn generate_wasm_struct_interop(
|
|||
#(#gen_enums)*
|
||||
}
|
||||
} else {
|
||||
// struct with more than one field
|
||||
|
||||
let mut gen_into_wasm_streamable_fields = Vec::with_capacity(descriptor.field.len());
|
||||
let mut gen_from_wasm_streamable_fields = Vec::with_capacity(descriptor.field.len());
|
||||
let mut gen_from_wasm_map_infallible = Vec::with_capacity(descriptor.field.len());
|
||||
|
||||
for field in &descriptor.field {
|
||||
let field_name_str = field
|
||||
|
@ -710,33 +645,29 @@ fn generate_wasm_struct_interop(
|
|||
|
||||
let into_wasm_streamable = type_enum.to_into_wasm_streamable(field_name_str, &js_map_name);
|
||||
let from_wasm_streamable = type_enum.to_from_wasm_streamable(field_name_str, &js_map_name);
|
||||
let from_wasm_map_infallible = type_enum.to_from_map_infallible(field_name_str, &js_map_name);
|
||||
//let wasm_type_name = type_enum.to_wasm_tokens();
|
||||
gen_fields.push(quote::quote! {
|
||||
pub #field_name: #type_name,
|
||||
});
|
||||
gen_into_fields.push(quote::quote! {
|
||||
#field_name: self.#field_name.into(),
|
||||
|
||||
let into_converter_tokens = type_enum.to_into_prost_type();
|
||||
gen_into_fields.push(quote::quote!{
|
||||
#field_name: self.#field_name #into_converter_tokens,
|
||||
});
|
||||
|
||||
gen_from_fields.push(quote::quote! {
|
||||
#field_name: <_>::from(other.#field_name),
|
||||
let from_converter_tokens = type_enum.to_from_prost_type(&field_name);
|
||||
gen_from_fields.push(quote::quote!{
|
||||
#field_name: #from_converter_tokens,
|
||||
});
|
||||
|
||||
gen_into_wasm_streamable_fields.push(into_wasm_streamable);
|
||||
gen_from_wasm_streamable_fields.push(from_wasm_streamable);
|
||||
gen_from_wasm_map_infallible.push(from_wasm_map_infallible);
|
||||
}
|
||||
|
||||
let wasm_attribute_maybe =
|
||||
if (descriptor.field.len() == 1 || !is_response_msg) && !descriptor.field.is_empty() {
|
||||
quote::quote! {}
|
||||
} else {
|
||||
quote::quote! {
|
||||
#[wasm_bindgen]
|
||||
}
|
||||
};
|
||||
|
||||
quote::quote! {
|
||||
#wasm_attribute_maybe
|
||||
#[derive(Default)]
|
||||
pub struct #msg_name {
|
||||
#(#gen_fields)*
|
||||
}
|
||||
|
@ -755,7 +686,24 @@ fn generate_wasm_struct_interop(
|
|||
}
|
||||
}
|
||||
|
||||
type #msg_name_wasm = #msg_name;
|
||||
impl IntoWasmable<js_sys::Map> for #msg_name {
|
||||
fn into_wasm(self) -> js_sys::Map {
|
||||
let #js_map_name = js_sys::Map::new();
|
||||
#(#gen_into_wasm_streamable_fields)*
|
||||
#js_map_name
|
||||
}
|
||||
}
|
||||
|
||||
impl FromWasmable<js_sys::Map> for #msg_name {
|
||||
fn from_wasm(js: js_sys::Map) -> Self {
|
||||
let #js_map_name = js_sys::Map::from(js);
|
||||
Self {
|
||||
#(#gen_from_wasm_map_infallible)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type #msg_name_wasm = js_sys::Map;//#msg_name;
|
||||
|
||||
impl std::convert::Into<super::#super_msg_name> for #msg_name {
|
||||
#[inline]
|
||||
|
@ -935,7 +883,7 @@ impl ProtobufType {
|
|||
Self::Sfixed32 => quote::quote! {i32},
|
||||
Self::Sfixed64 => quote::quote! {i64},
|
||||
Self::Bool => quote::quote! {bool},
|
||||
Self::String => quote::quote! {String},
|
||||
Self::String => quote::quote! {js_sys::JsString},
|
||||
Self::Bytes => quote::quote! {Vec<u8>},
|
||||
Self::Repeated(_) => quote::quote! {js_sys::Array},
|
||||
Self::Map { .. } => quote::quote! {js_sys::Map},
|
||||
|
@ -958,6 +906,27 @@ impl ProtobufType {
|
|||
quote::quote!{#field_ident: #type_tokens::from_wasm_streamable(#js_map_name.get(&JsValue::from(#field_name)))?,}
|
||||
}
|
||||
|
||||
fn to_from_map_infallible(&self, field_name: &str, js_map_name: &syn::Ident) -> proc_macro2::TokenStream {
|
||||
let type_tokens = self.to_tokens();
|
||||
let field_ident = quote::format_ident!("{}", field_name);
|
||||
quote::quote!{#field_ident: #type_tokens::from_wasm_streamable(#js_map_name.get(&JsValue::from(#field_name))).unwrap_or_default(),}
|
||||
}
|
||||
|
||||
fn to_into_prost_type(&self) -> proc_macro2::TokenStream {
|
||||
match self {
|
||||
//Self::String => quote::quote!{.as_string().unwrap()},
|
||||
_ => quote::quote!{.into()}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn to_from_prost_type(&self, field_name: &syn::Ident) -> proc_macro2::TokenStream {
|
||||
match self {
|
||||
//Self::String => quote::quote!{#field_name: },
|
||||
_ => quote::quote!{<_>::from(other.#field_name)}
|
||||
}
|
||||
}
|
||||
|
||||
/*fn is_already_wasm_streamable(&self) -> bool {
|
||||
!matches!(self, Self::Custom(_))
|
||||
}*/
|
||||
|
@ -991,6 +960,9 @@ fn generate_wasm_enum_interop(
|
|||
.as_ref()
|
||||
.expect("Protobuf enum needs a name")
|
||||
);
|
||||
if descriptor.value.is_empty() {
|
||||
panic!("Cannot generate enum {} with 0 variants because it is not possible to initialize", descriptor.name.as_ref().unwrap());
|
||||
}
|
||||
let mut gen_values = Vec::with_capacity(descriptor.value.len());
|
||||
let mut gen_into_values = Vec::with_capacity(descriptor.value.len());
|
||||
let mut gen_from_values = Vec::with_capacity(descriptor.value.len());
|
||||
|
@ -998,7 +970,10 @@ fn generate_wasm_enum_interop(
|
|||
// TODO deal with options when necessary
|
||||
todo!("Deal with enum options when necessary");
|
||||
}
|
||||
for value in &descriptor.value {
|
||||
gen_values.push(quote::quote!{
|
||||
#[default]
|
||||
});
|
||||
for value in descriptor.value.iter() {
|
||||
let val_name = quote::format_ident!(
|
||||
"{}",
|
||||
value
|
||||
|
@ -1041,7 +1016,7 @@ fn generate_wasm_enum_interop(
|
|||
quote::quote! {
|
||||
#[wasm_bindgen]
|
||||
#[repr(i32)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub enum #enum_name {
|
||||
#(#gen_values)*
|
||||
}
|
||||
|
@ -1066,34 +1041,46 @@ fn generate_wasm_enum_interop(
|
|||
|
||||
#impl_wasm_compat
|
||||
|
||||
impl FromWasmable<i32> for #enum_name {
|
||||
fn from_wasm(js: i32) -> Self {
|
||||
#enum_name::from(super::#super_enum_name::from_i32(js).unwrap())
|
||||
impl KnownWasmCompatible for #enum_name_wasm {}
|
||||
|
||||
impl FromWasmable<#enum_name_wasm> for #enum_name {
|
||||
fn from_wasm(js: #enum_name_wasm) -> Self {
|
||||
js
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoWasmable<i32> for #enum_name {
|
||||
fn into_wasm(self) -> i32 {
|
||||
self as i32
|
||||
impl IntoWasmable<#enum_name_wasm> for #enum_name {
|
||||
fn into_wasm(self) -> #enum_name_wasm {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for #enum_name {
|
||||
fn from(other: i32) -> Self {
|
||||
#enum_name::from(super::#super_enum_name::from_i32(other).unwrap())
|
||||
impl std::convert::From<i32> for #enum_name {
|
||||
fn from(x: i32) -> Self {
|
||||
#enum_name::from(super::#super_enum_name::from_i32(x).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<i32> for #enum_name {
|
||||
impl std::convert::Into<i32> for #enum_name {
|
||||
fn into(self) -> i32 {
|
||||
self as i32
|
||||
}
|
||||
}
|
||||
|
||||
impl #enum_name {
|
||||
fn from_f64(f: f64) -> Self {
|
||||
Self::from(super::#super_enum_name::from_i32(f as i32).unwrap())
|
||||
}
|
||||
|
||||
fn into_f64(self) -> f64 {
|
||||
(self as i32).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::usdpl_front::wasm::FromWasmStreamableType for #enum_name {
|
||||
fn from_wasm_streamable(js: JsValue) -> Result<Self, ::usdpl_front::wasm::WasmStreamableConversionError> {
|
||||
if let Some(float) = js.as_f64() {
|
||||
Ok(Self::from_wasm(float as i32))
|
||||
Ok(Self::from_f64(float))
|
||||
} else {
|
||||
Err(::usdpl_front::wasm::WasmStreamableConversionError::UnexpectedType {
|
||||
expected: ::usdpl_front::wasm::JsType::Number,
|
||||
|
@ -1105,7 +1092,7 @@ fn generate_wasm_enum_interop(
|
|||
|
||||
impl ::usdpl_front::wasm::IntoWasmStreamableType for #enum_name {
|
||||
fn into_wasm_streamable(self) -> JsValue {
|
||||
JsValue::from(self.into_wasm())
|
||||
JsValue::from(self.into_f64())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1224,6 +1211,49 @@ fn generate_service_io_types(
|
|||
}
|
||||
}
|
||||
|
||||
fn generate_error_to_jsobject_fn() -> proc_macro2::TokenStream {
|
||||
quote::quote!{
|
||||
#[allow(dead_code)]
|
||||
fn nrpc_error_to_jsobj(descriptor: &str, method_name: &str, error: &usdpl_front::_helpers::nrpc::ServiceError) -> js_sys::Object {
|
||||
let js_error = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&js_error,
|
||||
&JsValue::from("variant"),
|
||||
&JsValue::from(error.variant())
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&js_error,
|
||||
&JsValue::from("name"),
|
||||
&JsValue::from(error.variant_str())
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&js_error,
|
||||
&JsValue::from("message"),
|
||||
&JsValue::from(error.to_string())
|
||||
).unwrap();
|
||||
|
||||
let error_info = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("service"),
|
||||
&JsValue::from(descriptor)
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("method"),
|
||||
&JsValue::from(method_name)
|
||||
).unwrap();
|
||||
js_sys::Reflect::set(
|
||||
&error_info,
|
||||
&JsValue::from("error"),
|
||||
&JsValue::from("todo"/*TODO*/)
|
||||
).unwrap();
|
||||
|
||||
error_info
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IServiceGenerator for WasmServiceGenerator {
|
||||
fn generate(&mut self, service: Service) -> proc_macro2::TokenStream {
|
||||
let lock = self.shared.lock().expect("Cannot lock shared state");
|
||||
|
@ -1236,6 +1266,7 @@ impl IServiceGenerator for WasmServiceGenerator {
|
|||
let service_str_name = service.name.clone();
|
||||
let service_methods = generate_service_methods(&service, fds);
|
||||
let service_types = generate_service_io_types(&service, fds);
|
||||
let error_translate_fn = generate_error_to_jsobject_fn();
|
||||
let mod_name = quote::format_ident!("js_{}", service.name.to_lowercase());
|
||||
quote::quote! {
|
||||
mod #mod_name {
|
||||
|
@ -1254,6 +1285,8 @@ impl IServiceGenerator for WasmServiceGenerator {
|
|||
|
||||
use usdpl_front::WebSocketHandler;
|
||||
|
||||
#error_translate_fn
|
||||
|
||||
#service_types
|
||||
|
||||
/// WASM/JS-compatible wrapper of a Rust nRPC service
|
||||
|
|
|
@ -9,14 +9,12 @@ readme = "../README.md"
|
|||
description = "Universal Steam Deck Plugin Library core designed for all architectures"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
default = ["any"]
|
||||
decky = []
|
||||
encrypt = ["aes-gcm-siv"]
|
||||
any = []
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.13"
|
||||
aes-gcm-siv = { version = "0.10", optional = true, default-features = false, features = ["alloc", "aes"] }
|
||||
# nrpc = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.3.4"
|
||||
|
|
|
@ -10,11 +10,11 @@ impl Platform {
|
|||
/// The current platform that usdpl-core is configured to target.
|
||||
/// This is determined by feature flags.
|
||||
pub fn current() -> Self {
|
||||
#[cfg(all(feature = "decky", not(any(feature = "crankshaft"))))]
|
||||
#[cfg(all(feature = "decky", not(any(feature = "any"))))]
|
||||
{
|
||||
Self::Decky
|
||||
}
|
||||
#[cfg(not(any(feature = "decky")))]
|
||||
#[cfg(feature = "any")]
|
||||
{
|
||||
Self::Any
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ crate-type = ["cdylib", "rlib"]
|
|||
default = []
|
||||
decky = ["usdpl-core/decky"]
|
||||
debug = ["console_error_panic_hook"]
|
||||
#encrypt = ["usdpl-core/encrypt", "obfstr", "hex"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
|
@ -41,9 +40,6 @@ web-sys = { version = "0.3", features = [
|
|||
]}
|
||||
js-sys = { version = "0.3" }
|
||||
|
||||
obfstr = { version = "0.3", optional = true }
|
||||
hex = { version = "0.4", optional = true }
|
||||
|
||||
nrpc = { version = "1.0", path = "../../nRPC/nrpc", default-features = false}
|
||||
usdpl-core = { version = "1.0", path = "../usdpl-core" }
|
||||
prost = "0.11"
|
||||
|
|
|
@ -32,11 +32,6 @@ const DEFAULT_LOGGER: console_logs::BuiltInLogger = console_logs::BuiltInLogger:
|
|||
|
||||
static mut CACHE: Option<std::collections::HashMap<String, JsValue>> = None;
|
||||
|
||||
#[cfg(feature = "encrypt")]
|
||||
fn encryption_key() -> Vec<u8> {
|
||||
hex::decode(obfstr::obfstr!(env!("USDPL_ENCRYPTION_KEY"))).unwrap()
|
||||
}
|
||||
|
||||
static INIT_DONE: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||
|
||||
/// Initialize the front-end library
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
mod arrays;
|
||||
mod js_function_stream;
|
||||
mod maps;
|
||||
mod not_quite_trivial;
|
||||
mod streaming;
|
||||
mod trivials;
|
||||
mod wasm_traits;
|
||||
|
|
25
usdpl-front/src/wasm/not_quite_trivial.rs
Normal file
25
usdpl-front/src/wasm/not_quite_trivial.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use super::{FromWasmable, IntoWasmable};
|
||||
|
||||
impl FromWasmable<js_sys::JsString> for String {
|
||||
fn from_wasm(js: js_sys::JsString) -> Self {
|
||||
js.as_string().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoWasmable<js_sys::JsString> for String {
|
||||
fn into_wasm(self) -> js_sys::JsString {
|
||||
js_sys::JsString::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromWasmable<wasm_bindgen::JsValue> for () {
|
||||
fn from_wasm(_: wasm_bindgen::JsValue) -> Self {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoWasmable<wasm_bindgen::JsValue> for () {
|
||||
fn into_wasm(self) -> wasm_bindgen::JsValue {
|
||||
wasm_bindgen::JsValue::undefined()
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ trivial_convert! { u64 }
|
|||
trivial_convert! { u128 }
|
||||
|
||||
trivial_convert! { bool }
|
||||
|
||||
trivial_convert! { String }
|
||||
|
||||
trivial_convert! { () }
|
||||
|
|
|
@ -38,3 +38,5 @@ impl KnownWasmCompatible for () {}
|
|||
|
||||
impl KnownWasmCompatible for js_sys::Map {}
|
||||
impl KnownWasmCompatible for js_sys::Array {}
|
||||
impl KnownWasmCompatible for wasm_bindgen::JsValue {}
|
||||
impl KnownWasmCompatible for js_sys::JsString {}
|
||||
|
|
Loading…
Reference in a new issue