Can I render a Template in Rocket with my own serialized struct? - rust

I'm using Rocket and I'm trying to create a Layout struct. I've implemented serde::Serialize, because the documentation says the static method Template::render's second argument accepts a struct that implements Serialize:
struct Layout {
data: String,
second: String,
}
impl Layout {
fn new(data: String, second: String) -> Layout {
Layout { data, second }
}
fn render(&self) -> Template {
Template::render("Layout", &self)
}
}
impl Serialize for Layout {
fn serialize<S>(&self, serialize: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
let mut state = serializer.serialize_struct("Layout", 2);
state.serialize_field("data", &self.data)?;
state.serialize_field("second", &self.data)?;
state.end()
}
}
I get the error
the trait `serde::ser::Serialize` is not implemented for `layout::Layout`
What did I do wrong?

The current version of rocket, v0.2.6, uses serde = "^0.9" and not serde 1.0 yet. This means that if you're saying something like serde = "1" in your Cargo.toml, cargo will download and link two different versions of serde. This leads to the error message.
Furthermore, due to a mistake by the chrono developers, chrono 3.1 uses serde 1.0, while chrono 3.0 uses serde 0.9. But updating a dependency to a new major version should lead to a major version bump in the crate itself (related: What exactly is considered a breaking change to a library crate?). This lead to many breakages. In order to cope with that, you need to say chrono = "=3.0" in your Cargo.toml if you want to use that crate.
This, by the way, is exactly what diesel 0.12 is doing, which is using serde 0.9 as well. Diesel 0.13 is using serde 1.0, so it can depend on chrono = "^0.3.1". So Rocket is probably the last crate which needs to do the transition to serde 1.0. But this shouldn't take too long anymore. Then, everything should be in order again.
Ahhh, nothing beats the smell of dependency hell in the morning.

Just like Lukas explained, there are some dependency issues. Rocket actually has upgraded to the newer Serde versions, but didn't push the changes as a new version of Rocket to crates.io. Therefore I recommend to tell cargo to pull rocket and its related crates from GitHub.
An example dependencies section of the Cargo.toml is provided below:
[dependencies]
chrono = "0.3.1"
rocket = { git = "https://github.com/SergioBenitez/Rocket" }
rocket_codegen = { git = "https://github.com/SergioBenitez/Rocket" }
rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket" }
serde = "1.0.2"
serde_json = "1.0.1"
serde_derive = "1.0.2"

Related

How do I remove this compiler error for use_store with yewdux?

I am learning yewdux and have implemented the tutorial code for global state:
use yew::prelude::*;
use yewdux::prelude::*;
#[derive(Default, Clone, PartialEq, Eq, Store)]
struct State {
count: u32,
}
#[function_component]
fn App() -> Html {
let (state, dispatch) = use_store::<State>();
let onclick = dispatch.reduce_mut_callback(|state| state.count += 1);
html! {
<>
<p>{ state.count }</p>
<button {onclick}>{"+1"}</button>
</>
}
}
fn main() {
yew::Renderer::<App>::new().render();
}
However I am getting a compiler error for the line:
let (state, dispatch) = use_store::<State>();
The compiler error reads:
error[E0277]: the trait bound `impl yew::functional::hooks::Hook<Output = (Rc<State>, Dispatch<State>)>: Hook` is not satisfied
--> src/main.rs:11:29
|
11 | let (state, dispatch) = use_store::<State>();
| ---------^^^^^^^^^^^
| |
| the trait `Hook` is not implemented for `impl yew::functional::hooks::Hook<Output = (Rc<State>, Dispatch<State>)>`
| required by a bound introduced by this call
|
= help: the trait `Hook` is implemented for `BoxedHook<'_, T>`
My Cargo.toml file is:
[package]
name = "yewdux_tutorial"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
stdweb = "0.4.20"
yewdux = "0.9.0"
Please could someone help point me in the right direction for solving this compiler error.
I have searched online for this this answer and found this question Failed to follow yew tutorial on Mac m1 - use of undeclared type `Vec` (Also on a mac m1) and followed the answer to no success.
I also attempted to manually implement a default Store on the State struct but that also did not fix it.
Try to add yew crate this way:
[dependencies]
yew = { version = "0.20", features = ["csr"] }
yewdux = "0.9"
When we did not specify yew by its source, we actually refer to the one in the official crate registry. But if we specify yew by its git repository, we refer to the crate at the default branch if no branch specified. The two crates are not the same in the eye of the Rust compiler.
The crate yewdux in the official crate registry probably also relies on the yew that is in the official crate registry as well, so we need to refer to yew in the official crate registry.
The file Cargo.lock shows more details about crate dependencies. If source = "registry+https://github.com/rust-lang/crates.io-index", then the crate is from the official crate registry. If source = "git+https://github.com/yewstack/yew.git#c40bd0b456f9c80146c99d56bc0b441c88c3fefe", then the crate is from the repo specified and the code version is at the commit c40bd0b456f9c80146c99d56bc0b441c88c3fefe.
Reference: https://intendednull.github.io/yewdux/setup.html#stable-release

Unable to use rocket::serde::json::Json despite both rocket and serde listed as dependencies

I followed the quickstart guide. Now I'm trying to return some super simple JSON and the documentation is wrong and there's no way to submit a ticket without getting on IRC.
Error
error[E0432]: unresolved import `rocket::serde::json`
--> src/main.rs:2:20
|
2 | use rocket::serde::json::Json;
| ^^^^ could not find `json` in `serde`
For more information about this error, try `rustc --explain E0432`.
error: could not compile `my-api` due to previous error
Files
Cargo.toml
[package]
name = "my-api"
version = "0.1.0"
edition = "2021"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rocket = "0.5.0-rc.1"
serde = "1.0.130"
main.rs
#[macro_use] extern crate rocket;
use rocket::serde::{Serialize, json::Json};
#[derive(Serialize)]
struct Location {
lat: String,
lng: String,
}
#[get("/?<lat>&<lng>")]
fn location(lat: &str, lng: &str) -> Json<Location> {
Json(Location {
lat: 111.1111.to_string(),
lng: 222.2222.to_string(),
})
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![location])
}
If you go here you'll see this is almost a direct copy/paste from the documentation. I don't know enough of Rust to troubleshoot dependency errors.
The json feature for rocket needs to be explicitly turned on in your Cargo.toml.
[package]
name = "my-api"
version = "0.1.0"
edition = "2018" // cut back for testing with nixpkgs-provided rust
publish = false
[dependencies]
serde = "1.0.130"
[dependencies.rocket]
version = "0.5.0-rc.1"
features = ["json"]
This is documented in a comment in the Rocket source which generates the document here.
On top of Charles' answer, I'd change the serde import to:
serde = { version = "1.0", features = ["derive"] }
As documented here

Can't make basic example of Serde Serialize work

Serde documentation says:
All of these can be serialized using Serde out of the box.
serde_json is just for the example, not required in general.
This is exactly what I need, a basic serialization of a struct into some basic binary format. I don't need JSON format, I want to keep it simple to be able to store struct in a file or send it to the network. The documentation is not clear on how to use serde for basic (binary or default) serialization, it only shows example with a JSON but this is not what I am looking for. I also don't want to implement my own serialize method, I want to use the default methods that Serde provides.
This is my example, so how do I make it work?
use serde::{Serialize, Deserialize,Serializer};
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
//let serialized = serde::serialize(&point).unwrap(); // <-- doesnt work!
//let serialized = Serializer::serialize(&point); // <-- doesnt work!
//let serialized = point.serialize(Serializer); // <-- doesn't work!
println!("data = {:?}", serialized);
}
Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b57a77399280f19664bb004201319b32
This is my dependency line:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
As noted in the comments, there's no "default" format provided.
You have to pick the binary format you want and include it as an additional dependency, just as you would with serde_json.
There's a list of formats at https://serde.rs/#data-formats. Of those serde_json is the only package hosted under https://github.com/serde-rs, all the binary formats are "third-party". Cross-referencing it with the list of crates tagged "serde" sorted by recent downloads, the CBOR crate seems popular.

How to deserialize a parking_lot::Mutex with Serde?

I have a struct of memory (obj) wrapped in an Arc<Mutex>. The Mutex is an improved version of the std::sync::Mutex in the parking_lot crate. I need to deserialize the wrapped object (obj), however, I get an error:
the trait `_IMPL_DESERIALIZE_FOR_SecurityLevel::_serde::Deserialize<'_>` is not implemented for `lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, Obj>`
In my Cargo.toml, I have (notably):
serde = { version = "1.0.89", features = ["rc"] }
parking_lot = {version = "0.8", features = ["nightly"]}
How should I go about this? Is there a workaround, or must I manually implement the traits?
Support for Serde was added to parking_lot 0.8 under the serde feature flag:
parking_lot = { version = "0.8", features = ["nightly", "serde"] }
Using this, the code you have provided compiles. This also compiles:
use parking_lot::Mutex;
use serde::{Deserialize, Serialize};
fn implements<T>()
where
Mutex<T>: for<'a> Deserialize<'a> + Serialize,
{
}

Using a struct which implements a traits from a different crate

Crate sha2 contains the type Sha256 which implements the trait Digest defined in the crate digest. This trait is also reexported from sha2.
I want to write a file which doesn't mention sha2, just digest:
merkle_tree.rs:
use digest::Digest;
#[derive(Default)]
pub struct MerkleTree<T: Digest> {
digest: T,
}
impl<T: Digest+Default> MerkleTree<T> {
pub fn new() -> MerkleTree<T> {
MerkleTree{ ..Default::default() }
}
}
main.rs:
extern crate digest;
extern crate sha2;
mod merkle_tree;
use sha2::{Digest, Sha256};
use merkle_tree::MerkleTree;
fn main() {
let mut mt = MerkleTree::<Sha256>::new();
println!("Hello, world!");
}
I have the following output:
error: no associated item named new found for type
merkle_tree::MerkleTree<sha2::Sha256> in the current scope
the trait digest::Digest is not implemented for sha2::Sha256
Cargo.toml:
[package]
name = "merkle_tree"
version = "0.1.0"
authors = ["Simon Prykhodko <semion.ababo#gmail.com>"]
[dependencies]
digest = "0.4.0"
sha2 = "0.3.0"
What's wrong here?
The digest you're using and the digest the sha2 crate is using are incompatible. That they have the same name is irrelevant; as far as the compiler is concerned, you're trying to conflate two entirely different crates.
The quickest way to tell would be to see if digest shows up more than once during compilation, or more than once in your Cargo.lock file. You can also verify this manually by looking at crate dependencies. sha2 0.3.0 lists digest 0.3 in its dependencies, and 0.3 is not compatible with 0.4.
You need to either downgrade your crate's dependency on digest, or upgrade your crate's version of sha2 to one that uses a newer version of digest.
I just ran your code and it compiled fine with these dependency versions:
[dependencies]
sha2 = "0.4.2"
digest = "0.4.0"
Try updating one or both.

Resources