Using a struct which implements a traits from a different crate - rust

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.

Related

Selective model lib

how can i have crate that depend on with feature use another version of same crate like below
[features]
serde_1 = ["dep_serde_1"]
serde_1_0_133 = ["dep_serde_1_0_133"]
[dependencies]
dep_serde_1 = { package = "serde", version = "1.0.0", optional = true}
dep_serde_1_0_133 = { package = "serde", version = "1.0.133", optional = true}
my problem is compiler force me to use
use dep_serde_1::*;
except like this
use serde::*;
i just enable one of them at time and in code with cfg(feature = serde_1) i'll chose what code must compile
sorry about my poor English
[Edit]
main idea drive form this problem, for example
if my model use actix-0.10 and another crate that use my lib use actix-0.12 it generate compiler error
I'm not quite sure I understand what you want. If you want the name of the crate to be serde in your use statements, you can rename them back:
#[cfg(feature = "dep_serde_1")]
extern crate dep_serde_1 as serde;
#[cfg(feature = "dep_serde_1_0_133")]
extern crate dep_serde_1_0_133 as serde;
// Now you can
use serde::*;
[Edit:] The above takes care of your use of serde, but serde_derive has its own ideas. When you define a struct like
#[derive(Serialize)]
struct Asdf { /* … */ }
serde generates code that looks roughly like this:
const _: () = {
extern crate serde as _serde;
#[automatically_derived]
impl _serde::Serialize for Asdf { /* …
i.e. it ignores the renaming of the serde crate and tries to use the crate by its original name.
You can override this behavior with the crate container attribute:
#[derive(Serialize)]
#[serde(crate = "serde")]
struct Asdf { /* … */ }
which will make the generated code use the serde from the outer namespace:
const _: () = {
use serde as _serde;
#[automatically_derived]
impl serde::Serialize for Asdf {
Note, that mutually exclusive features are not a good idea. If you can, it's better to make one the default and the other to override it.
I'm also not sure your cargo dependencies are actually doing what you want them to. Cargo doesn't allow depending on a crate twice, and if I force dep_serde_1 to =1.0.0 cargo will complain that there is a conflict.

structopt unable to find its Args parser when defined in a separate file

I'm starting on a command-line tool in Rust, and hitting a wall right from the get-go. I can parse command-line arguments using StructOpt if the Opt struct is defined in main.rs, but since I want to be able to pass the Opt struct into the library code, I'm defining it in its own file so that other parts of the library know what it's all about.
Here's the version of the code that's dumping the fewest errors, although I concede that it's largely cobbled together by trying things suggested by the compiler and some random SO suggestions, so it may be completely wrong.
The build error I'm getting is:
$ cargo run
Compiling basic v0.1.0 (/home/mpalmer/src/action-validator/blobble)
error[E0433]: failed to resolve: maybe a missing crate `structopt`?
--> src/opt.rs:8:5
|
8 | /// Activate debug mode
| ^^^^^^^^^^^^^^^^^^^^^^^ not found in `structopt::clap`
|
help: consider importing this struct
|
3 | use opt::structopt::clap::Arg;
|
For more information about this error, try `rustc --explain E0433`.
error: could not compile `basic` due to previous error
$ cargo --version
cargo 1.56.0 (4ed5d137b 2021-10-04)
$ rustc --version
rustc 1.56.0 (09c42c458 2021-10-18)
(Yes, I have tried adding use opt::structopt::clap::Arg;, just in case, but the error doesn't go away and I get a warning about an unused import -- while still being told to try adding the same use that is unused, which is amusing)
Cargo.toml
[package]
name = "basic"
version = "0.1.0"
authors = ["User"]
[dependencies]
structopt = "0.3"
src/main.rs
extern crate basic;
extern crate structopt;
use basic::Opt;
use structopt::StructOpt;
fn main() {
let opt = Opt::from_args();
println!("{:#?}", opt)
}
src/lib.rs
mod opt;
pub use crate::opt::Opt;
src/opt.ts
extern crate structopt;
use self::structopt::StructOpt;
#[derive(StructOpt, Debug)]
#[structopt(name = "basic")]
pub struct Opt {
/// Activate debug mode
#[structopt(short,long)]
debug: bool,
}
Suggestions gratefully appreciated.
A working version is
Cargo.toml
[package]
name = "basic"
version = "0.1.0"
authors = ["User"]
edition = "2018"
[dependencies]
structopt = "0.3"
lib.rs
#[macro_use] extern crate structopt;
use structopt::StructOpt;
pub mod opt;
opt.rs
#[derive(StructOpt, Debug)]
#[structopt(name = "basic")]
pub struct Opt {
/// Activate debug mode
#[structopt(short,long)]
debug: bool,
}
main.rs
#[macro_use] extern crate structopt;
use structopt::StructOpt;
fn main() {
let opt = basic::opt::Opt::from_args();
println!("{:#?}", opt);
}
You need to declare use structopt::StructOpt because from_args trait must be in the scope.

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