Selective model lib - rust

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.

Related

How to benchmark rust library with cargo features?

I am working on a library that is configurable with cargo features, and I can't figure out how to get the bencher crate (for benchmarking) to work. In lib.rs I have
#[cfg(feature = "single_threaded")]
pub fn my_function() {...}
In benches/bench.rs I have
#[macro_use]
extern crate bencher;
extern crate my_crate;
use bencher::Bencher;
use my_crate::*;
fn single_thread(bench: &mut Bencher) {
bench.iter(|| {
for _ in 0..10 {
my_function();
}
})
}
benchmark_group!(benches, single_thread);
benchmark_main!(benches);
As is, the compiler says that it cannot find my_function because I haven't specified a configuration. If I add #[cfg(feature = "single_threaded")] above fn single_thread(), it can then find my_function, but that seems to put single_thread in a different context from everything else, such that the two macros at the bottom cannot find single_thread().
If I add #[cfg(feature = "single_threaded")] above each of the two macros, the compiler says to "consider adding a main function to benches/bench.rs," but a main function is added by benchmark_main!. If I put the entire file into a module and declare #[cfg(feature = "single_threaded")] once for the whole module, I get the same error about not having a main function. Any suggestions?
Oh and my Cargo.toml looks like this
[package]
name = "my_crate"
version = "0.1.0"
edition = "2021"
authors = ["Me"]
[dependencies]
[dev-dependencies]
bencher = "0.1.5"
[features]
single_threaded = []
[[bench]]
name = "benches"
harness = false

How to set dependencies for a macro in Rust?

I wrote a macro in a crate and import it in the main function of a main project.
The macro depends on:
use chrono::{Utc, Local, DateTime, Date};
Currently I include the dependency in the Cargo.toml of the main project.
Will I need to do the same for all main projects? Or Can I declare the dependency in the Cargo.toml of the macro crate?
//lib.rs //Mymacro
#[macro_export]
macro_rules! time {
() => {
use chrono::{Utc, Local, DateTime, Date};
let local_datetime: DateTime<Local> = Local::now();
println!("{:?}",local_datetime);
}
}
//main.rs // main project
extern crate Mymacro;
#[macro_use]
fn main() {
time!();
}
// Cargo.html
[dependencies]
chrono=""
Will I need to do the same for all main projects? Or Can I declare the dependency in the Cargo.toml of the macro crate?
You can, by either (1) having your macro call a function in your library or (2) by re-exporting chrono (partially or completely).
Let's consider that we have a workspace, with a lib and bin crate.
[workspace]
members = [
"bin",
"lib",
]
Now in your Cargo.toml for the lib crate you'd include chrono as a dependency, like you otherwise would.
[dependencies]
chrono = "0.4"
While the Cargo.toml for the bin crate only has the dependency of lib.
[dependencies]
lib = { path = "../lib" }
Now, let's consider that main.rs in the bin crate looks like this:
use lib::time;
fn main() {
time!();
}
It will remain the same, regardless of which option you go with.
The following snippets represent lib.rs.
Library Function
If you never actually return any chrono specific types, then this might be the easiest. As you avoid re-exporting chrono completely.
use chrono::{DateTime, Local};
pub fn _time() {
let local_datetime: DateTime<Local> = Local::now();
println!("{:?}", local_datetime);
}
#[macro_export]
macro_rules! time {
() => {
$crate::_time();
};
}
If you don't want _time to appear in the documentation of your library, then you can use the #[doc(hidden)] attribute.
Re-export some items
Alternatively, if you want everything to remain within the macro, then you can re-export the chrono types it uses, and prepend the types in your macro with $crate::.
The downside to this, is that if your bin crate needs a chrono type that is not re-exported, then that can be an "annoyance" and thus bin would need to depend on chrono = "0.4" anyways.
pub use chrono::{DateTime, Local};
#[macro_export]
macro_rules! time {
() => {
let local_datetime: $crate::DateTime<$crate::Local> = $crate::Local::now();
println!("{:?}", local_datetime);
};
}
In main.rs if you instead do use lib::*;, then you'd of course not need to prepend $crate::, but it's best to avoid doing use lib::*;.
Re-export Chrono
Lastly, if you need the chrono types in you bin crate. Then you can also re-export the whole chrono crate with pub extern crate chrono;.
Note that this time, you need to prepend the types in your macro with $crate::chrono::.
pub extern crate chrono;
#[macro_export]
macro_rules! time {
() => {
let local_datetime: $crate::chrono::DateTime<$crate::chrono::Local> =
$crate::chrono::Local::now();
println!("{:?}", local_datetime);
};
}

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?

Importing a crate into a const block

I'm trying to write a procedural macro that implements a #[derive()] trait for a struct. In the generated implementation code I need to use AnyMap.
To avoid multi crate imports, and based on what I read in some other crate's code (namely Serde) I put my generated code into a const _IMPL_xxx_FOR_xxx : () = { /* generated code */ }; block but it fails to compile.
I was able to replicate my issue with the following code
const BLOCK_1: () = {
extern crate anymap;
use anymap::AnyMap;
};
const BLOCK_2: () = {
extern crate anymap;
use anymap::AnyMap;
};
fn main() {
println!("foo");
}
The compile error I'm getting is the following:
error[E0432]: unresolved import `anymap::AnyMap`
--> src/main.rs:3:9
|
3 | use anymap::AnyMap;
| ^^^^^^^^^^^^^^ Maybe a missing `extern crate anymap;`?
error[E0432]: unresolved import `anymap::AnyMap`
--> src/main.rs:9:9
|
9 | use anymap::AnyMap;
| ^^^^^^^^^^^^^^ Maybe a missing `extern crate anymap;`?
Is it an issue specific to AnyMap? Would you know of any way to fix this (including maybe a different approach to generating procedural macro code if the pattern I'm using is not recommended?
I can replicate this on the playground using simply
const A: () = {
extern crate core;
use core::option::Option;
};
fn main() {}
However, it appears only the use statement is broken, and I can still use items from core, but I have to name them explicitly each time:
const A: () = {
extern crate core;
do_stuff!(core::option::Option)
};
The reason is that use statements typically assume a path relative to the root, and there is no way to explicitly name the block you are in (self refers to the current module unfortunately).
Here's a better workaround - as I said before, Rust uses self to refer to the current module, so you can just put a module in your code block and then have the use statements reference self.
In your case it would be:
const BLOCK_1: () = {
mod inner {
extern crate anymap;
use self::anymap::AnyMap;
}
};
On the specific issue of making this work for procedural macro, a suggested solution was to reexport the needed crate as part of the crate containing the derive macro (or the one containing the class I'm trying to export) using something like pub extern crate anymap and then use <my_crate>::anymap::AnyMap;

Resources