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 = [
|
exclude = [
|
||||||
"templates/decky/backend"
|
"templates/decky/backend",
|
||||||
|
"templates/decky/src/rust"
|
||||||
]
|
]
|
||||||
|
|
||||||
resolver = "2"
|
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]
|
[features]
|
||||||
default = ["blocking"]
|
default = ["blocking"]
|
||||||
decky = ["usdpl-core/decky"]
|
decky = ["usdpl-core/decky"]
|
||||||
|
any = []
|
||||||
blocking = [] # synchronous API for async functionality, using tokio
|
blocking = [] # synchronous API for async functionality, using tokio
|
||||||
#encrypt = ["usdpl-core", "obfstr", "hex"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
usdpl-core = { version = "1.0", path = "../usdpl-core"}
|
usdpl-core = { version = "1.0", path = "../usdpl-core"}
|
||||||
|
@ -35,10 +35,6 @@ tokio = { version = "1", features = [ "full" ]}
|
||||||
async-trait = "0.1.57"
|
async-trait = "0.1.57"
|
||||||
async-recursion = "1.0.0"
|
async-recursion = "1.0.0"
|
||||||
|
|
||||||
# encryption helpers
|
|
||||||
obfstr = { version = "0.3", optional = true }
|
|
||||||
hex = { version = "0.4", optional = true }
|
|
||||||
|
|
||||||
# translations
|
# translations
|
||||||
gettext-ng = { version = "0.4.1" }
|
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.
|
/// The home directory of the user currently running the Steam Deck UI.
|
||||||
pub fn home() -> Option<PathBuf> {
|
pub fn home() -> Option<PathBuf> {
|
||||||
#[cfg(not(any(feature = "decky", feature = "crankshaft")))]
|
#[cfg(not(any(feature = "decky")))]
|
||||||
let result = crate::api_any::dirs::home();
|
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()
|
let result = crate::api_decky::home()
|
||||||
.ok()
|
.ok()
|
||||||
.map(|x| PathBuf::from(x).join("..").canonicalize().ok())
|
.map(|x| PathBuf::from(x).join("..").canonicalize().ok())
|
||||||
|
@ -17,9 +17,9 @@ pub fn home() -> Option<PathBuf> {
|
||||||
|
|
||||||
/// The plugin's root folder.
|
/// The plugin's root folder.
|
||||||
pub fn plugin() -> Option<PathBuf> {
|
pub fn plugin() -> Option<PathBuf> {
|
||||||
#[cfg(not(any(feature = "decky", feature = "crankshaft")))]
|
#[cfg(not(any(feature = "decky")))]
|
||||||
let result = None; // TODO
|
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());
|
let result = crate::api_decky::plugin_dir().ok().map(|x| x.into());
|
||||||
|
|
||||||
result
|
result
|
||||||
|
@ -27,9 +27,9 @@ pub fn plugin() -> Option<PathBuf> {
|
||||||
|
|
||||||
/// The recommended log directory
|
/// The recommended log directory
|
||||||
pub fn log() -> Option<PathBuf> {
|
pub fn log() -> Option<PathBuf> {
|
||||||
#[cfg(not(any(feature = "decky", feature = "crankshaft")))]
|
#[cfg(not(any(feature = "decky")))]
|
||||||
let result = crate::api_any::dirs::log();
|
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());
|
let result = crate::api_decky::log_dir().ok().map(|x| x.into());
|
||||||
|
|
||||||
result
|
result
|
||||||
|
|
|
@ -55,7 +55,7 @@ fn generate_service_methods(
|
||||||
#field_name: #js_type_name,
|
#field_name: #js_type_name,
|
||||||
});
|
});
|
||||||
params_to_fields.push(quote::quote! {
|
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 {
|
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")
|
.expect("Protobuf message field needs a name")
|
||||||
);
|
);
|
||||||
quote::quote! {
|
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() {
|
} else if input_type.field.is_empty() {
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
let val = #method_input {};
|
let val = ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
|
@ -94,22 +94,8 @@ fn generate_service_methods(
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(e_handler) = &self.error_handler {
|
if let Some(e_handler) = &self.error_handler {
|
||||||
let error_info = js_sys::Object::new();
|
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||||
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();
|
|
||||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
// log error
|
// log error
|
||||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||||
|
@ -145,22 +131,8 @@ fn generate_service_methods(
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(e_handler) = &self.error_handler {
|
if let Some(e_handler) = &self.error_handler {
|
||||||
let error_info = js_sys::Object::new();
|
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||||
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();
|
|
||||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
// log error
|
// log error
|
||||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
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() {
|
} else if input_type.field.is_empty() {
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
let val = #method_input {};
|
let val = ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
|
@ -236,22 +208,8 @@ fn generate_service_methods(
|
||||||
match next_result {
|
match next_result {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(e_handler) = &self.error_handler {
|
if let Some(e_handler) = &self.error_handler {
|
||||||
let error_info = js_sys::Object::new();
|
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||||
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();
|
|
||||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
// log error
|
// log error
|
||||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||||
|
@ -293,22 +251,8 @@ fn generate_service_methods(
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(e_handler) = &self.error_handler {
|
if let Some(e_handler) = &self.error_handler {
|
||||||
let error_info = js_sys::Object::new();
|
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||||
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();
|
|
||||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
// log error
|
// log error
|
||||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
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 {
|
match next_result {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(e_handler) = &self.error_handler {
|
if let Some(e_handler) = &self.error_handler {
|
||||||
let error_info = js_sys::Object::new();
|
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||||
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();
|
|
||||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
// log error
|
// log error
|
||||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||||
|
@ -399,22 +329,8 @@ fn generate_service_methods(
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(e_handler) = &self.error_handler {
|
if let Some(e_handler) = &self.error_handler {
|
||||||
let error_info = js_sys::Object::new();
|
let error_info = nrpc_error_to_jsobj(self.service.descriptor(), #method_name_str, &e);
|
||||||
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();
|
|
||||||
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
// log error
|
// log error
|
||||||
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
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 {
|
if descriptor.field.len() == 0 {
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
pub type #msg_name = ();
|
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)*
|
#(#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! {
|
quote::quote! {
|
||||||
pub type #msg_name = #type_name;
|
pub type #msg_name = #type_name;
|
||||||
|
@ -672,7 +603,7 @@ fn generate_wasm_struct_interop(
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into(self) -> super::#super_msg_name {
|
fn into(self) -> super::#super_msg_name {
|
||||||
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]
|
#[inline]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn from(other: super::#super_msg_name) -> Self {
|
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)*
|
#(#gen_enums)*
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// struct with more than one field
|
||||||
|
|
||||||
let mut gen_into_wasm_streamable_fields = Vec::with_capacity(descriptor.field.len());
|
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_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 {
|
for field in &descriptor.field {
|
||||||
let field_name_str = 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 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_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();
|
//let wasm_type_name = type_enum.to_wasm_tokens();
|
||||||
gen_fields.push(quote::quote! {
|
gen_fields.push(quote::quote! {
|
||||||
pub #field_name: #type_name,
|
pub #field_name: #type_name,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let into_converter_tokens = type_enum.to_into_prost_type();
|
||||||
gen_into_fields.push(quote::quote!{
|
gen_into_fields.push(quote::quote!{
|
||||||
#field_name: self.#field_name.into(),
|
#field_name: self.#field_name #into_converter_tokens,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let from_converter_tokens = type_enum.to_from_prost_type(&field_name);
|
||||||
gen_from_fields.push(quote::quote!{
|
gen_from_fields.push(quote::quote!{
|
||||||
#field_name: <_>::from(other.#field_name),
|
#field_name: #from_converter_tokens,
|
||||||
});
|
});
|
||||||
|
|
||||||
gen_into_wasm_streamable_fields.push(into_wasm_streamable);
|
gen_into_wasm_streamable_fields.push(into_wasm_streamable);
|
||||||
gen_from_wasm_streamable_fields.push(from_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! {
|
quote::quote! {
|
||||||
#[wasm_bindgen]
|
#[derive(Default)]
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
quote::quote! {
|
|
||||||
#wasm_attribute_maybe
|
|
||||||
pub struct #msg_name {
|
pub struct #msg_name {
|
||||||
#(#gen_fields)*
|
#(#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 {
|
impl std::convert::Into<super::#super_msg_name> for #msg_name {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -935,7 +883,7 @@ impl ProtobufType {
|
||||||
Self::Sfixed32 => quote::quote! {i32},
|
Self::Sfixed32 => quote::quote! {i32},
|
||||||
Self::Sfixed64 => quote::quote! {i64},
|
Self::Sfixed64 => quote::quote! {i64},
|
||||||
Self::Bool => quote::quote! {bool},
|
Self::Bool => quote::quote! {bool},
|
||||||
Self::String => quote::quote! {String},
|
Self::String => quote::quote! {js_sys::JsString},
|
||||||
Self::Bytes => quote::quote! {Vec<u8>},
|
Self::Bytes => quote::quote! {Vec<u8>},
|
||||||
Self::Repeated(_) => quote::quote! {js_sys::Array},
|
Self::Repeated(_) => quote::quote! {js_sys::Array},
|
||||||
Self::Map { .. } => quote::quote! {js_sys::Map},
|
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)))?,}
|
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 {
|
/*fn is_already_wasm_streamable(&self) -> bool {
|
||||||
!matches!(self, Self::Custom(_))
|
!matches!(self, Self::Custom(_))
|
||||||
}*/
|
}*/
|
||||||
|
@ -991,6 +960,9 @@ fn generate_wasm_enum_interop(
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Protobuf enum needs a name")
|
.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_values = Vec::with_capacity(descriptor.value.len());
|
||||||
let mut gen_into_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());
|
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 options when necessary
|
||||||
todo!("Deal with enum 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!(
|
let val_name = quote::format_ident!(
|
||||||
"{}",
|
"{}",
|
||||||
value
|
value
|
||||||
|
@ -1041,7 +1016,7 @@ fn generate_wasm_enum_interop(
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Default)]
|
||||||
pub enum #enum_name {
|
pub enum #enum_name {
|
||||||
#(#gen_values)*
|
#(#gen_values)*
|
||||||
}
|
}
|
||||||
|
@ -1066,34 +1041,46 @@ fn generate_wasm_enum_interop(
|
||||||
|
|
||||||
#impl_wasm_compat
|
#impl_wasm_compat
|
||||||
|
|
||||||
impl FromWasmable<i32> for #enum_name {
|
impl KnownWasmCompatible for #enum_name_wasm {}
|
||||||
fn from_wasm(js: i32) -> Self {
|
|
||||||
#enum_name::from(super::#super_enum_name::from_i32(js).unwrap())
|
impl FromWasmable<#enum_name_wasm> for #enum_name {
|
||||||
|
fn from_wasm(js: #enum_name_wasm) -> Self {
|
||||||
|
js
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoWasmable<i32> for #enum_name {
|
impl IntoWasmable<#enum_name_wasm> for #enum_name {
|
||||||
fn into_wasm(self) -> i32 {
|
fn into_wasm(self) -> #enum_name_wasm {
|
||||||
self as i32
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i32> for #enum_name {
|
impl std::convert::From<i32> for #enum_name {
|
||||||
fn from(other: i32) -> Self {
|
fn from(x: i32) -> Self {
|
||||||
#enum_name::from(super::#super_enum_name::from_i32(other).unwrap())
|
#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 {
|
fn into(self) -> i32 {
|
||||||
self as 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 {
|
impl ::usdpl_front::wasm::FromWasmStreamableType for #enum_name {
|
||||||
fn from_wasm_streamable(js: JsValue) -> Result<Self, ::usdpl_front::wasm::WasmStreamableConversionError> {
|
fn from_wasm_streamable(js: JsValue) -> Result<Self, ::usdpl_front::wasm::WasmStreamableConversionError> {
|
||||||
if let Some(float) = js.as_f64() {
|
if let Some(float) = js.as_f64() {
|
||||||
Ok(Self::from_wasm(float as i32))
|
Ok(Self::from_f64(float))
|
||||||
} else {
|
} else {
|
||||||
Err(::usdpl_front::wasm::WasmStreamableConversionError::UnexpectedType {
|
Err(::usdpl_front::wasm::WasmStreamableConversionError::UnexpectedType {
|
||||||
expected: ::usdpl_front::wasm::JsType::Number,
|
expected: ::usdpl_front::wasm::JsType::Number,
|
||||||
|
@ -1105,7 +1092,7 @@ fn generate_wasm_enum_interop(
|
||||||
|
|
||||||
impl ::usdpl_front::wasm::IntoWasmStreamableType for #enum_name {
|
impl ::usdpl_front::wasm::IntoWasmStreamableType for #enum_name {
|
||||||
fn into_wasm_streamable(self) -> JsValue {
|
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 {
|
impl IServiceGenerator for WasmServiceGenerator {
|
||||||
fn generate(&mut self, service: Service) -> proc_macro2::TokenStream {
|
fn generate(&mut self, service: Service) -> proc_macro2::TokenStream {
|
||||||
let lock = self.shared.lock().expect("Cannot lock shared state");
|
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_str_name = service.name.clone();
|
||||||
let service_methods = generate_service_methods(&service, fds);
|
let service_methods = generate_service_methods(&service, fds);
|
||||||
let service_types = generate_service_io_types(&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());
|
let mod_name = quote::format_ident!("js_{}", service.name.to_lowercase());
|
||||||
quote::quote! {
|
quote::quote! {
|
||||||
mod #mod_name {
|
mod #mod_name {
|
||||||
|
@ -1254,6 +1285,8 @@ impl IServiceGenerator for WasmServiceGenerator {
|
||||||
|
|
||||||
use usdpl_front::WebSocketHandler;
|
use usdpl_front::WebSocketHandler;
|
||||||
|
|
||||||
|
#error_translate_fn
|
||||||
|
|
||||||
#service_types
|
#service_types
|
||||||
|
|
||||||
/// WASM/JS-compatible wrapper of a Rust nRPC service
|
/// 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"
|
description = "Universal Steam Deck Plugin Library core designed for all architectures"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["any"]
|
||||||
decky = []
|
decky = []
|
||||||
encrypt = ["aes-gcm-siv"]
|
any = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
aes-gcm-siv = { version = "0.10", optional = true, default-features = false, features = ["alloc", "aes"] }
|
|
||||||
# nrpc = "0.2"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex-literal = "0.3.4"
|
hex-literal = "0.3.4"
|
||||||
|
|
|
@ -10,11 +10,11 @@ impl Platform {
|
||||||
/// The current platform that usdpl-core is configured to target.
|
/// The current platform that usdpl-core is configured to target.
|
||||||
/// This is determined by feature flags.
|
/// This is determined by feature flags.
|
||||||
pub fn current() -> Self {
|
pub fn current() -> Self {
|
||||||
#[cfg(all(feature = "decky", not(any(feature = "crankshaft"))))]
|
#[cfg(all(feature = "decky", not(any(feature = "any"))))]
|
||||||
{
|
{
|
||||||
Self::Decky
|
Self::Decky
|
||||||
}
|
}
|
||||||
#[cfg(not(any(feature = "decky")))]
|
#[cfg(feature = "any")]
|
||||||
{
|
{
|
||||||
Self::Any
|
Self::Any
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ crate-type = ["cdylib", "rlib"]
|
||||||
default = []
|
default = []
|
||||||
decky = ["usdpl-core/decky"]
|
decky = ["usdpl-core/decky"]
|
||||||
debug = ["console_error_panic_hook"]
|
debug = ["console_error_panic_hook"]
|
||||||
#encrypt = ["usdpl-core/encrypt", "obfstr", "hex"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
|
@ -41,9 +40,6 @@ web-sys = { version = "0.3", features = [
|
||||||
]}
|
]}
|
||||||
js-sys = { version = "0.3" }
|
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}
|
nrpc = { version = "1.0", path = "../../nRPC/nrpc", default-features = false}
|
||||||
usdpl-core = { version = "1.0", path = "../usdpl-core" }
|
usdpl-core = { version = "1.0", path = "../usdpl-core" }
|
||||||
prost = "0.11"
|
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;
|
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);
|
static INIT_DONE: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||||
|
|
||||||
/// Initialize the front-end library
|
/// Initialize the front-end library
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
mod arrays;
|
mod arrays;
|
||||||
mod js_function_stream;
|
mod js_function_stream;
|
||||||
mod maps;
|
mod maps;
|
||||||
|
mod not_quite_trivial;
|
||||||
mod streaming;
|
mod streaming;
|
||||||
mod trivials;
|
mod trivials;
|
||||||
mod wasm_traits;
|
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! { u128 }
|
||||||
|
|
||||||
trivial_convert! { bool }
|
trivial_convert! { bool }
|
||||||
|
|
||||||
trivial_convert! { String }
|
trivial_convert! { String }
|
||||||
|
|
||||||
trivial_convert! { () }
|
trivial_convert! { () }
|
||||||
|
|
|
@ -38,3 +38,5 @@ impl KnownWasmCompatible for () {}
|
||||||
|
|
||||||
impl KnownWasmCompatible for js_sys::Map {}
|
impl KnownWasmCompatible for js_sys::Map {}
|
||||||
impl KnownWasmCompatible for js_sys::Array {}
|
impl KnownWasmCompatible for js_sys::Array {}
|
||||||
|
impl KnownWasmCompatible for wasm_bindgen::JsValue {}
|
||||||
|
impl KnownWasmCompatible for js_sys::JsString {}
|
||||||
|
|
Loading…
Reference in a new issue