How to deserialize a parking_lot::Mutex with Serde? - rust

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,
{
}

Related

(De)serialize RFC-3339 timestamp with serde to time-rs OffsetDateTime

My goal is to (de)serialize objects with RFC-3339 timestamps from Json to Rust structs (and vice versa) using serde and time-rs.
I would expect this ...
use serde::Deserialize;
use time::{OffsetDateTime};
#[derive(Deserialize)]
pub struct DtoTest {
pub timestamp: OffsetDateTime,
}
fn main() {
let deserialization_result = serde_json::from_str::<DtoTest>("{\"timestamp\": \"2022-07-08T09:10:11Z\"}");
let dto = deserialization_result.expect("This should not panic");
println!("{}", dto.timestamp);
}
... to create the struct and display the timestamp as the output, but I get ...
thread 'main' panicked at 'This should not panic: Error("invalid type: string \"2022-07-08T09:10:11Z\", expected an `OffsetDateTime`", line: 1, column: 36)', src/main.rs:12:38
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
My dependencies look like this:
[dependencies]
serde = { version = "1.0.138", features = ["derive"] }
serde_json = "1.0.82"
time = { version = "0.3.11", features = ["serde"] }
According to the documentation of the time-rs crate, this seems to be possible but I must be missing something.
The default serialization format for time is some internal format. If you want other formats, you should enable the serde-well-known feature and use the serde module to choose the format you want:
#[derive(Deserialize)]
pub struct DtoTest {
#[serde(with = "time::serde::rfc3339")]
pub timestamp: OffsetDateTime,
}
The solution below is based on the serde_with crate. As per its documentation, it aims to be more flexible and composable.
use serde_with::serde_as;
use time::OffsetDateTime;
use time::format_description::well_known::Rfc3339;
#[serde_as]
#[derive(Deserialize)]
pub struct DtoTest {
#[serde_as(as = "Rfc3339")]
pub timestamp: OffsetDateTime,
}
And the Cargo.toml file should have:
[dependencies]
serde_with = { version = "2", features = ["time_0_3"] }
At the following page are listed all De/Serialize transformations available.

Error E0412: use of undeclared crate or module `tokio` when importing tokio::sync

In my rust project, cargo complains about a used type not being in scope when using tokio::sync:
use tokio::sync::RwLock;
| ^^^^^ use of undeclared crate or module `tokio`
but it clearly is in scope:
use tokio::sync::RwLock;
#[derive(Deserialize, Serialize)]
pub struct MyStruct {
some_field: RwLock<SomeType>
}
According to the documentation, the sync module is only available after enabling the sync feature flag, which I have done both explicitly and implicitly:
tokio = { version = "0.3", features = ["macros", "sync"] }
tokio = { version = "0.3", features = ["full"] }
But it does not work with either.
I didn't notice that I only had tokio under the dev-dependencies, which is why cargo was not able to compile the project.

How can I fix cannot find derive macro `Deserialize` in this scope? [duplicate]

I have this:
#[derive(FromPrimitive)]
pub enum MyEnum {
Var1 = 1,
Var2
}
And an error:
error: cannot find derive macro `FromPrimitive` in this scope
|
38 | #[derive(FromPrimitive)]
| ^^^^^^^^^^^^^
Why do I get this? How do I fix it?
The compiler has a small set of built-in derive macros. For any others, you have to import the custom derives before they can be used.
Before Rust 1.30, you need to use #[macro_use] on the extern crate line of the crate providing the macros. With Rust 1.30 and up, you can use them instead.
In this case, you need to import FromPrimitive from the num_derive crate:
After Rust 1.30
use num_derive::FromPrimitive; // 0.2.4 (the derive)
use num_traits::FromPrimitive; // 0.2.6 (the trait)
Before Rust 1.30
#[macro_use]
extern crate num_derive; // 0.2.4
extern crate num_traits; // 0.2.6
use num_traits::FromPrimitive;
Usage
#[derive(Debug, FromPrimitive)]
pub enum MyEnum {
Var1 = 1,
Var2,
}
fn main() {
println!("{:?}", MyEnum::from_u8(2));
}
Each project has their own crate containing their own derive macros. A small sample:
Num (e.g. FromPrimitive) => num_derive
Serde (e.g. Serialize, Deserialize) => serde_derive
Diesel (e.g. Insertable, Queryable) => diesel (it's actually the same as the regular crate!)
Some crates re-export their derive macros. For example, you can use the derive feature of Serde and then import it from the serde crate directly:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
use serde::{Serialize, Deserialize}; // imports both the trait and the derive macro
FromPrimitive was actually part of the standard library before Rust 1.0. It wasn't useful enough to continue existing in the standard library, so it was moved to the external num crate. Some very old references might not have been updated for this change.
For more information about converting C-like enums to and from integers, see:
How do I match enum values with an integer?
How do I get the integer value of an enum?

How do I fix "cannot find derive macro in this scope"?

I have this:
#[derive(FromPrimitive)]
pub enum MyEnum {
Var1 = 1,
Var2
}
And an error:
error: cannot find derive macro `FromPrimitive` in this scope
|
38 | #[derive(FromPrimitive)]
| ^^^^^^^^^^^^^
Why do I get this? How do I fix it?
The compiler has a small set of built-in derive macros. For any others, you have to import the custom derives before they can be used.
Before Rust 1.30, you need to use #[macro_use] on the extern crate line of the crate providing the macros. With Rust 1.30 and up, you can use them instead.
In this case, you need to import FromPrimitive from the num_derive crate:
After Rust 1.30
use num_derive::FromPrimitive; // 0.2.4 (the derive)
use num_traits::FromPrimitive; // 0.2.6 (the trait)
Before Rust 1.30
#[macro_use]
extern crate num_derive; // 0.2.4
extern crate num_traits; // 0.2.6
use num_traits::FromPrimitive;
Usage
#[derive(Debug, FromPrimitive)]
pub enum MyEnum {
Var1 = 1,
Var2,
}
fn main() {
println!("{:?}", MyEnum::from_u8(2));
}
Each project has their own crate containing their own derive macros. A small sample:
Num (e.g. FromPrimitive) => num_derive
Serde (e.g. Serialize, Deserialize) => serde_derive
Diesel (e.g. Insertable, Queryable) => diesel (it's actually the same as the regular crate!)
Some crates re-export their derive macros. For example, you can use the derive feature of Serde and then import it from the serde crate directly:
[dependencies]
serde = { version = "1.0", features = ["derive"] }
use serde::{Serialize, Deserialize}; // imports both the trait and the derive macro
FromPrimitive was actually part of the standard library before Rust 1.0. It wasn't useful enough to continue existing in the standard library, so it was moved to the external num crate. Some very old references might not have been updated for this change.
For more information about converting C-like enums to and from integers, see:
How do I match enum values with an integer?
How do I get the integer value of an enum?

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

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"

Resources