Skip to content

Commit

Permalink
Wasm as_string
Browse files Browse the repository at this point in the history
  • Loading branch information
tinrab committed Jan 16, 2024
1 parent a0d4cf6 commit e41fe7e
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 133 deletions.
8 changes: 7 additions & 1 deletion bomboni_common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ mysql = ["dep:sqlx"]
serde = ["dep:serde"]
tokio = ["dep:tokio"]
chrono = ["dep:chrono"]
wasm = ["dep:js-sys", "dep:wasm-bindgen", "time/wasm-bindgen"]
wasm = [
"dep:bomboni_wasm_derive",
"dep:js-sys",
"dep:wasm-bindgen",
"time/wasm-bindgen",
]
js = []

[dependencies]
Expand All @@ -32,6 +37,7 @@ sqlx = { version = "0.7", features = ["mysql"], optional = true }
chrono = { version = "0.4.31", optional = true }
js-sys = { version = "0.3.67", optional = true }
wasm-bindgen = { version = "0.2.90", optional = true }
bomboni_wasm_derive = { path = "../bomboni_wasm_derive", version = "0.1.53", optional = true }

[dev-dependencies]
serde_json = "1.0.111"
Expand Down
100 changes: 9 additions & 91 deletions bomboni_common/src/id/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,6 @@ use std::{
#[cfg(feature = "serde")]
use serde::{de::Unexpected, Deserialize, Deserializer, Serialize, Serializer};

#[cfg(all(
target_family = "wasm",
not(any(target_os = "emscripten", target_os = "wasi")),
feature = "wasm"
))]
use wasm_bindgen::{
convert::{FromWasmAbi, IntoWasmAbi, OptionFromWasmAbi, OptionIntoWasmAbi},
describe::WasmDescribe,
prelude::*,
};

pub mod generator;
#[cfg(feature = "mysql")]
mod mysql;
Expand All @@ -31,6 +20,15 @@ const WORKER_BITS: i64 = 16;
const SEQUENCE_BITS: i64 = 16;

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(
all(
target_family = "wasm",
not(any(target_os = "emscripten", target_os = "wasi")),
feature = "wasm"
),
derive(bomboni_wasm_derive::Wasm),
wasm(as_string)
)]
pub struct Id(u128);

impl Id {
Expand Down Expand Up @@ -134,86 +132,6 @@ impl<'de> Deserialize<'de> for Id {
}
}

#[cfg(all(
target_family = "wasm",
not(any(target_os = "emscripten", target_os = "wasi")),
feature = "wasm"
))]
mod wasm {
use super::*;

impl WasmDescribe for Id {
fn describe() {
<js_sys::JsString as WasmDescribe>::describe()
}
}

impl From<Id> for js_sys::JsString {
fn from(value: Id) -> Self {
value.to_string().into()
}
}

impl From<js_sys::JsString> for Id {
fn from(value: js_sys::JsString) -> Self {
Self::from_str(&value.as_string().unwrap()).unwrap()
}
}

impl From<&js_sys::JsString> for Id {
fn from(value: &js_sys::JsString) -> Self {
Self::from_str(&value.as_string().unwrap()).unwrap()
}
}

impl IntoWasmAbi for Id {
type Abi = <js_sys::JsString as IntoWasmAbi>::Abi;

fn into_abi(self) -> Self::Abi {
js_sys::JsString::from(self.to_string()).into_abi()
}
}

impl OptionIntoWasmAbi for Id {
#[inline]
fn none() -> Self::Abi {
<js_sys::JsString as OptionIntoWasmAbi>::none()
}
}

impl FromWasmAbi for Id {
type Abi = <js_sys::JsString as FromWasmAbi>::Abi;

unsafe fn from_abi(js: Self::Abi) -> Self {
match js_sys::JsString::from_abi(js)
.as_string()
.as_ref()
.map(|s| Self::from_str(s))
{
Some(Ok(value)) => value,
Some(Err(err)) => {
wasm_bindgen::throw_str(&err.to_string());
}
None => {
wasm_bindgen::throw_str("expected string");
}
}
}
}

impl OptionFromWasmAbi for Id {
#[inline]
fn is_none(js: &Self::Abi) -> bool {
js_sys::JsString::is_none(js)
}
}

#[wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &'static str = r#"
export type Id = string;
"#;
}

#[cfg(test)]
mod tests {

Expand Down
6 changes: 3 additions & 3 deletions bomboni_prost/src/enums.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bomboni_core::string::{str_to_case, Case};
use proc_macro2::{Literal, TokenStream};
use proc_macro2::TokenStream;
use prost_types::EnumDescriptorProto;
use quote::{format_ident, quote};

Expand All @@ -20,7 +20,7 @@ pub fn write_enum(context: &Context, s: &mut TokenStream, enum_type: &EnumDescri
fn write_name(context: &Context, s: &mut TokenStream, enum_type: &EnumDescriptorProto) {
let enum_ident = context.get_type_expr_path(enum_type.name());
let enum_proto_name = context.get_proto_type_name(enum_type.name());
let package_proto_name = Literal::string(&context.package_name);
let package_proto_name = &context.package_name;

s.extend(quote! {
impl #enum_ident {
Expand All @@ -40,7 +40,7 @@ fn write_value_names(context: &Context, s: &mut TokenStream, enum_type: &EnumDes
"{}_VALUE_NAME",
str_to_case(value.name(), Case::ScreamingSnake)
);
let value_name = Literal::string(value.name());
let value_name = value.name();

value_names.extend(quote! {
pub const #value_name_ident: &'static str = #value_name;
Expand Down
15 changes: 6 additions & 9 deletions bomboni_prost/src/messages.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bomboni_core::format_comment;
use bomboni_core::string::{str_to_case, Case};
use proc_macro2::{Literal, TokenStream};
use proc_macro2::TokenStream;
use prost_types::DescriptorProto;
use quote::{format_ident, quote};

Expand Down Expand Up @@ -51,7 +51,7 @@ pub fn write_message(context: &Context, s: &mut TokenStream, message: &Descripto
fn write_name(context: &Context, s: &mut TokenStream, message: &DescriptorProto) {
let message_ident = context.get_type_expr_path(message.name());
let message_proto_name = context.get_proto_type_name(message.name());
let package_proto_name = Literal::string(&context.package_name);
let package_proto_name = &context.package_name;

let type_url = if context.config.api.type_url {
quote!(
Expand Down Expand Up @@ -83,15 +83,12 @@ fn write_type_url(context: &Context, s: &mut TokenStream, message: &DescriptorPr
let message_proto_name = context.get_proto_type_name(message.name());

let type_url = if let Some(domain) = context.config.api.domain.as_ref() {
Literal::string(&format!(
format!(
"{}/{}.{}",
domain, &context.package_name, message_proto_name
))
)
} else {
Literal::string(&format!(
"/{}.{}",
&context.package_name, message_proto_name
))
format!("/{}.{}", &context.package_name, message_proto_name)
};

s.extend(quote! {
Expand All @@ -111,7 +108,7 @@ fn write_field_names(context: &Context, s: &mut TokenStream, message: &Descripto
"{}_FIELD_NAME",
str_to_case(field.name(), Case::ScreamingSnake)
);
let field_name = Literal::string(field.name());
let field_name = field.name();
names.extend(quote! {
pub const #field_name_ident: &'static str = #field_name;
});
Expand Down
6 changes: 3 additions & 3 deletions bomboni_prost/src/oneofs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::BTreeMap;

use bomboni_core::string::{str_to_case, Case};
use proc_macro2::{Ident, Literal, TokenStream};
use proc_macro2::{Ident, TokenStream};
use prost_types::{field_descriptor_proto, DescriptorProto, OneofDescriptorProto};
use quote::{format_ident, quote};
use syn::TypePath;
Expand Down Expand Up @@ -57,7 +57,7 @@ fn write_name(
"{}_ONEOF_NAME",
str_to_case(oneof.name(), Case::ScreamingSnake)
);
let oneof_name_literal = Literal::string(oneof.name());
let oneof_name_literal = oneof.name();
s.extend(quote! {
impl #message_ident {
pub const #oneof_name_ident: &'static str = #oneof_name_literal;
Expand All @@ -82,7 +82,7 @@ fn write_variant_names(
"{}_VARIANT_NAME",
str_to_case(field.name(), Case::ScreamingSnake)
);
let variant_name_literal = Literal::string(field.name());
let variant_name_literal = field.name();
variant_names.extend(quote! {
pub const #variant_name_ident: &'static str = #variant_name_literal;
});
Expand Down
32 changes: 14 additions & 18 deletions bomboni_request_derive/src/parse/message/parse.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bomboni_core::syn::type_is_phantom;
use darling::FromMeta;
use proc_macro2::{Ident, Literal, TokenStream};
use proc_macro2::{Ident, TokenStream};
use quote::{quote, ToTokens};

use crate::parse::{DeriveOptions, ParseField, ParseOptions, QueryOptions};
Expand Down Expand Up @@ -172,15 +172,13 @@ fn expand_parse_field(options: &ParseOptions, field: &ParseField) -> syn::Result

if let Some(DeriveOptions { func, source_field }) = field.derive.as_ref() {
return Ok(if let Some(source_field) = source_field.as_ref() {
let source_field_name = Literal::string(
&source_field
.path
.segments
.iter()
.map(|s| s.ident.to_string())
.collect::<Vec<_>>()
.join("."),
);
let source_field_name = &source_field
.path
.segments
.iter()
.map(|s| s.ident.to_string())
.collect::<Vec<_>>()
.join(".");
quote! {
#target_ident: { #func(&source.#source_field, #source_field_name)? },
}
Expand Down Expand Up @@ -720,14 +718,12 @@ fn expand_extract_source_field(field: &ParseField) -> TokenStream {
let mut extract = quote!();
for (i, part) in parts.iter().enumerate() {
let part_ident = Ident::from_string(part).unwrap();
let part_literal = Literal::string(
&parts
.iter()
.take(i + 1)
.copied()
.collect::<Vec<_>>()
.join("."),
);
let part_literal = &parts
.iter()
.take(i + 1)
.copied()
.collect::<Vec<_>>()
.join(".");

extract.extend(if i < parts.len() - 1 {
quote! {
Expand Down
4 changes: 2 additions & 2 deletions bomboni_request_derive/src/parse/oneof/parse.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use darling::FromMeta;
use proc_macro2::{Ident, Literal, TokenStream};
use proc_macro2::{Ident, TokenStream};
use quote::{quote, ToTokens};

use crate::parse::{ParseOptions, ParseTaggedUnion, ParseVariant};
Expand Down Expand Up @@ -122,7 +122,7 @@ fn expand_tagged_union(
}

let field_ident = &tagged_union.field;
let field_literal = Literal::string(&tagged_union.field.to_string());
let field_literal = tagged_union.field.to_string();
let source = &options.source;
let (impl_generics, type_generics, where_clause) = options.generics.split_for_impl();

Expand Down
55 changes: 55 additions & 0 deletions bomboni_wasm_core/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub struct WasmOptions<'a> {
pub into_wasm_abi: bool,
pub from_wasm_abi: bool,
pub as_enum: bool,
pub as_string: Option<AsStringWasm>,
pub proxy: Option<ProxyWasm>,
pub reference_change: ReferenceChangeMap,
pub rename: Option<String>,
Expand Down Expand Up @@ -62,6 +63,12 @@ pub struct ProxyWasm {
pub try_from: Option<Path>,
}

#[derive(Debug)]
pub struct AsStringWasm {
pub into: Option<Path>,
pub try_from: Option<Path>,
}

#[derive(Debug, FromDeriveInput)]
#[darling(attributes(wasm))]
struct Attributes {
Expand All @@ -71,6 +78,7 @@ struct Attributes {
into_wasm_abi: Option<bool>,
from_wasm_abi: Option<bool>,
as_enum: Option<bool>,
as_string: Option<AsStringWasm>,
proxy: Option<ProxyWasm>,
rename: Option<String>,
change_ref: Option<ReferenceChangeMap>,
Expand Down Expand Up @@ -168,6 +176,7 @@ impl<'a> WasmOptions<'a> {
into_wasm_abi: attributes.into_wasm_abi.unwrap_or(wasm_abi),
from_wasm_abi: attributes.from_wasm_abi.unwrap_or(wasm_abi),
as_enum: attributes.as_enum.unwrap_or_default(),
as_string: attributes.as_string,
proxy: attributes.proxy,
rename: attributes.rename,
reference_change: attributes
Expand Down Expand Up @@ -326,6 +335,52 @@ impl FromMeta for ProxyWasm {
}
}

impl FromMeta for AsStringWasm {
fn from_list(items: &[darling::ast::NestedMeta]) -> darling::Result<Self> {
let mut into = None;
let mut try_from = None;
for item in items {
match item {
darling::ast::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
path,
value: syn::Expr::Path(value),
..
})) => {
if path.is_ident("into") {
if into.is_some() {
return Err(
darling::Error::custom("into already specified").with_span(item)
);
}
into = Some(value.path.clone());
} else if path.is_ident("try_from") {
if try_from.is_some() {
return Err(darling::Error::custom("try_from already specified")
.with_span(item));
}
try_from = Some(value.path.clone());
} else {
return Err(
darling::Error::custom("expected into or try_from").with_span(item)
);
}
}
_ => {
return Err(darling::Error::custom("expected proxy path").with_span(item));
}
}
}
Ok(Self { into, try_from })
}

fn from_word() -> darling::Result<Self> {
Ok(Self {
into: None,
try_from: None,
})
}
}

fn get_fields(
serde_fields: &[ast::Field],
field_attributes: &Fields<FieldAttributes>,
Expand Down
Loading

0 comments on commit e41fe7e

Please sign in to comment.