chronotope / chrono

Date and time library for Rust
Other
3.3k stars 523 forks source link

the trait bound `DateTime<Utc>: OptionFrom/ToWasmAbi` is not satisfied when targeting wasm32 #1556

Closed callmeclover closed 6 months ago

callmeclover commented 6 months ago
Error message ``` error[E0277]: the trait bound `DateTime: OptionIntoWasmAbi` is not satisfied --> src\model.rs:15:1 | 15 | #[wasm_bindgen] | ^^^^^^^^^^^^^^^ the trait `OptionIntoWasmAbi` is not implemented for `DateTime` | = help: the following other types implement trait `OptionIntoWasmAbi`: bool char i8 i16 u8 u16 model::MessageSent Box<[T]> and 178 others = note: required for `std::option::Option>` to implement `IntoWasmAbi` = note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `DateTime: OptionFromWasmAbi` is not satisfied --> src\model.rs:15:1 | 15 | #[wasm_bindgen] | ^^^^^^^^^^^^^^^ the trait `OptionFromWasmAbi` is not implemented for `DateTime` | = help: the following other types implement trait `OptionFromWasmAbi`: bool char i8 i16 u8 u16 model::MessageSent Box<[T]> and 78 others = note: required for `std::option::Option>` to implement `FromWasmAbi` = note: this error originates in the attribute macro `wasm_bindgen` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0277`. error: could not compile `rwst` (lib) due to 2 previous errors Error: Compiling your crate to WebAssembly failed Caused by: Compiling your crate to WebAssembly failed Caused by: failed to execute `cargo build`: exited with exit code: 101 full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown" ```
lib.rs ```rust mod model; use model::*; use wasm_bindgen::prelude::*; use web_sys::{ window, Element }; use ewebsock::{ Options, WsEvent, WsMessage::Text }; use urlencoding::encode; extern crate console_error_panic_hook; use std::panic; use web_sys_main_loop::FrameState; #[wasm_bindgen(start)] fn start_wasm() { panic::set_hook(Box::new(console_error_panic_hook::hook)); let window = window().expect("no global `window` exists"); let document = window.document().expect("should have a document on window"); let body = document.body().expect("document should have a body"); let elem = document.create_element("p").unwrap(); elem.set_text_content(Some("WASM module loaded!")); body.append_child(&elem).unwrap(); } #[wasm_bindgen] pub fn main() { let window = window().expect("no global `window` exists"); let document = window.document().expect("should have a document on window"); let body = document.body().expect("document should have a body"); let (mut sender, receiver) = ewebsock ::connect("unnecessary to be here", Options::default()) .expect(""); sender.send( ewebsock::WsMessage::Text( serde_json ::to_string( &(MessageSent { user: "test42".to_string(), msg: "hello".to_string(), time: None, }) ) .unwrap() ) ); web_sys_main_loop::start(&window, move |_frame_state: FrameState| { while let Some(WsEvent::Message(Text(event))) = receiver.try_recv() { match serde_json::from_str::(&event).unwrap() { MessageTypes::MessageSent(response) => { println!("Recieved event 'MessageSent' data (1/1) {:?}", response); body.append_child(&create_message_element(response.clone())).expect(""); } MessageTypes::RetrieveMessages(response) => { let iterator = response.msgs.iter(); for (i, d) in iterator.clone().enumerate() { println!( "Recieved event 'RetrieveMessages' data ({}/{}) {:?}", i + 1, iterator.len(), d ); body.append_child(&create_message_element(d.clone())).expect(""); } } MessageTypes::UserJoin(response) => { println!("Recieved event 'UserJoin' data (1/1) {:?}", response); } MessageTypes::UserLeft(response) => { println!("Recieved event 'UserLeft' data (1/1) {:?}", response); } } } }); } #[wasm_bindgen] pub fn create_message_element(res: MessageSent) -> Element { // Get the document and create a new div element let document = window().unwrap().document().unwrap(); let outer_div = document.create_element("div").unwrap(); outer_div.set_attribute("style", "margin: 10px 0;").unwrap(); // Create the inner div with the class "userDisplay" let user_display_div = document.create_element("div").unwrap(); user_display_div.set_class_name("userDisplay"); // Create and append the jdenticon element /*let jdenticon_svg = document.create_element("svg").unwrap(); jdenticon_svg.set_inner_html(&format!("{}", jdenticon.to_svg(username[2], 26))); We'll wait for this... user_display_div.append_child(&jdenticon_svg).unwrap();*/ // Create and append the anchor element let anchor = document.create_element("a").unwrap(); anchor.set_attribute("href", &format!("/profile/{}", encode(&res.user))).unwrap(); anchor.set_text_content(Some(&res.user)); user_display_div.append_child(&anchor).unwrap(); // Create and append the span element with class "msgTime" let time_span = document.create_element("span").unwrap(); time_span.set_class_name("msgTime"); time_span.set_inner_html( &format!( "[at ]", res.time, res.time.expect("no time when creating msg element").format("%x %r") ) ); user_display_div.append_child(&time_span).unwrap(); outer_div.append_child(&user_display_div).unwrap(); // Create the message div with id "message" and a pre element inside let message_div = document.create_element("div").unwrap(); message_div.set_id("message"); let pre_element = document.create_element("pre").unwrap(); pre_element.set_text_content(Some(&res.msg)); message_div.append_child(&pre_element).unwrap(); outer_div.append_child(&message_div).unwrap(); return outer_div; } ```
model.rs ```rust use serde::{ Deserialize, Serialize }; use chrono::{ DateTime, Utc }; use wasm_bindgen::prelude::*; #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(untagged)] pub enum MessageTypes { MessageSent(MessageSent), RetrieveMessages(RetrieveMessages), UserJoin(UserJoin), UserLeft(UserLeft), } #[derive(Serialize, Deserialize, Debug, Clone)] #[wasm_bindgen] pub struct MessageSent { pub msg: String, pub user: String, #[serde(skip_serializing)] pub time: Option>, // Error occurs here! } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct RetrieveMessages { pub msgs: Vec, } // User related messages #[derive(Serialize, Deserialize, Debug, Clone)] pub struct UserJoin { pub userjoin: String, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct UserLeft { pub userleft: String, } ```
Cargo.toml ```toml [package] name = "rwst" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen = "0.2.92" ewebsock = "0.5.0" chrono = { version = "0.4.37", features = ["serde", "wasmbind"] } serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" urlencoding = "2.1.3" web-sys-main-loop = "0.1.8" console_error_panic_hook = "0.1.7" [dependencies.web-sys] version = "0.3.4" features = [ 'Document', 'Element', 'HtmlElement', 'Node', 'Window', ] ```

Why does this happen? I compile with wasmbind explicitly enabled, so I don't know what could be happening here.

pitdicker commented 6 months ago

I don't think this is the right place to ask, this is not a problem in Chrono. Maybe wasm_bindgen can't derive a binding because of the Option or because of the DateTime? I suggest opening in issue in their repo.

pitdicker commented 6 months ago

I suppose the value must be converted to a js_sys::Date type. Chrono provides a From implementation.

pitdicker commented 6 months ago

I suppose the value must be converted to a js_sys::Date type. Chrono provides a From implementation.