Project with serde cannot compile - rust

When I try to run the example from the serde repository:
#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
// Convert the Point to a JSON string.
let serialized = serde_json::to_string(&point).unwrap();
// Prints serialized = {"x":1,"y":2}
println!("serialized = {}", serialized);
// Convert the JSON string back to a Point.
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
// Prints deserialized = Point { x: 1, y: 2 }
println!("deserialized = {:?}", deserialized);
}
I get an error:
error: failed to run rustc to learn about target-specific
information
Caused by: process didn't exit successfully: rustc - --crate-name _
--print=file-names --crate-type bin --crate-type proc-macro --crate-type rlib --target x86_64-unknown-linux-gnu (exit code: 101)
--- stderr error: unknown crate type: proc-macro
My Rust version is 1.13.0 and my Cargo.toml has these dependencies:
[dependencies]
serde = "*"
serde_derive = "*"
Should I use other dependencies or extra configuration?

The #![feature(...)] attribute indicates code that uses Rust features which have not been stabilized yet. At the time the question was asked, the proc_macro feature was not yet stable. Serde needs this feature for its #[derive(Serialize, Deserialize)] macros.
Custom derives have been stabilized as of Rust 1.15 so the code in the question (with the feature attribute removed) should work on any Rust compiler since that version.

Related

Rust no_std static lib panic_handler

I want to build a no_std static library with rust.
I got the following:
[package]
name = "nostdlb"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
lib.rs:
#![no_std]
pub fn add(left: usize, right: usize) -> usize {
left + right
}
Despite setting the panic behaviour for both dev and release to abort cargo gives the following error:
error: `#[panic_handler]` function required, but not found
error: could not compile `nostdlb` due to previous error
I thought the panic handler is only required when there is no stack unwinding provided by std?
No, you need to write your own one. If you need just aborting, consider using the following one:
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
I also highly recommend to unmangle the function and use C calling convention if you’re going to use this symbol somewhere (not import it the library as a crate, but link it manually):
#[no_mangle]
extern fn add(right: usize, left: usize) -> usize {
right + left
}

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.

Rust trait not satisfied

I'm new to rust and tried searching in stackoverflow as well as reading the serde documentation
https://docs.serde.rs/serde/trait.Serialize.html and https://serde.rs/impl-serialize.html, but I was a bit lost.
I would like to use Tera to generate html and the struct I'm passing it does not have the trait serde::ser::Serialize implemented and I tried to implement it but it doesn't appear quite right.
Cargo.toml dependencies
serde = "1.0.115"
serde_derive = "1.0.115"
serde-xml-rs = "0.4.0"
tera = "0.7.2"
main.rs
extern crate tera;
#[macro_use]
extern crate serde_derive;
extern crate serde;
use tera::Context;
use serde::ser::{Serialize, SerializeStruct, Serializer};
#[derive(Serialize, Debug)]
struct Person {
firstname: String,
lastname: String,
age: i32,
}
#[derive(Debug)]
struct Attendees {
people: Vec<Person>,
updatedOn: String,
updatedBy: String,
}
impl Serialize for Attendees {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut s = serializer.serialize_struct("Person", 3)?;
s.serialize_field("people", &self.people)?;
s.serialize_field("updatedOn", &self.updatedOn)?;
s.serialize_field("updatedBy", &self.updatedBy)?;
s.end()
}
}
fn main() {
let mut context = Context::new();
let mut peeps: Vec<Person> = Vec::new();
let mut attendees = Attendees {
people: peeps,
updatedOn: String::from("today"),
updatedBy: String::from("someone"),
};
context.add("attendees", &attendees);
}
compiler says:
mytest % cargo run
Compiling mytest v0.1.0 (/home/mike/mytest)
error[E0277]: the trait bound `Attendees: serde::ser::Serialize` is not satisfied
--> src/main.rs:44:29
|
44 | context.add("attendees", &attendees);
| ^^^^^^^^^^ the trait `serde::ser::Serialize` is not implemented for `Attendees`
error: aborting due to previous error
I am clearly missing something... Can anyone please help?
The trait you implemented and the trait that the error is referring are not the same, because they refer to two different versions of serde.
[[package]]
name = "tera"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c37e2aaa53871f9c3722a20f8951fea0afd366955e11542a58feb71997c6d769"
dependencies = [
"chrono",
"error-chain",
"glob",
"humansize",
"lazy_static 0.2.11",
"pest",
"regex",
"serde 0.9.15",
"serde_json",
"slug",
"url",
]
tera 0.7.2 is not using the version 1.0.* of serde, but 0.9.*.
You may use a more recent of tera, or use a compatible serde version in your Cargo.toml:
[dependencies]
serde = "0.9.15"
serde_derive = "0.9.15"

Rust is not honoring a custom cfg feature flag for conditional compilation [duplicate]

This question already has an answer here:
Example of how to use Conditional Compilation Macros in Rust
(1 answer)
Closed 4 years ago.
I'm trying to use rust's conditional compilation feature and it is not working at all. I'm attempting to use this to toggle between a default library and a different one, using the cfg to re-export one of two different submodules depending on if the feature flag is set or not. The code:
lib.rs:
pub mod ffi;
#[cfg(ffiv1)]
mod ffiv1;
#[cfg(not(ffiv1))]
mod ffiv2;
#[test]
fn test_ffi_struct() {
let _fs = ffi::FFIStruct{ x: 42};
}
#[cfg(ffiv1)]
#[test]
fn test_v1() {
println!("v1 enabled");
}
ffi.rs:
//re-export as ffi::FFIStruct
#[cfg(ffiv1)]
pub use ffiv1::FFIStruct;
#[cfg(not(ffiv1))]
pub use ffiv2::FFIStruct;
ffiv1.rs:
pub struct FFIStruct {
pub x: i32,
y: IShouldFail
}
ffiv2.rs:
pub struct FFIStruct {
pub x: i64
}
Cargo.toml:
[features]
ffiv1 = []
With the default cargo build/test, this builds and works as expected, everything is ok.
With cargo build --features ffiv1, it behaves as no feature flags were passed at all. Running cargo with --verbose shows --cfg 'feature="ffiv1"' going to rustc.
I would expect the compilation to fail on the undefined symbol IShouldFail in ffiv1.rs. (and the extra test to run if it compiled).
What is wrong here?
The syntax for conditional compilation based on Cargo features is like this:
#[cfg(feature = "...")]
/* ... */
#[cfg(not(feature = "..."))]
/* ... */
In your case that would be #[cfg(feature = "ffiv1")]. The #[cfg(ffiv1)] also means something but is controlled by a different rustc flag than what Cargo uses for optional features.

How do I access files in the src directory from files in my tests directory?

I have a project layout that looks like the following:
src/
int_rle.rs
lib.rs
tests/
test_int_rle.rs
The project compiles with cargo build, but I am unable to run the test with cargo test. I get the error
error[E0432]: unresolved import `int_rle`. There is no `int_rle` in the crate root
--> tests/test_int_rle.rs:1:5
|
1 | use int_rle;
| ^^^^^^^
error[E0433]: failed to resolve. Use of undeclared type or module `int_rle`
--> tests/test_int_rle.rs:7:9
|
7 | int_rle::IntRle { values: vec![1, 2, 3] }
| ^^^^^^^^^^^^^^^ Use of undeclared type or module `int_rle`
error: aborting due to 2 previous errors
error: Could not compile `minimal_example_test_directories`.
My code:
// src/lib.rs
pub mod int_rle;
// src/int_rle.rs
#[derive(Debug, PartialEq)]
pub struct IntRle {
pub values: Vec<i32>,
}
// tests/test_int_rle.rs
use int_rle;
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
int_rle::IntRle { values: vec![1, 2, 3] }
}
}
// Cargo.toml
[package]
name = "minimal_example_test_directories"
version = "0.1.0"
authors = ["Johann Gambolputty de von Ausfern ... von Hautkopft of Ulm"]
[dependencies]
Related: How do I compile a multi-file crate in Rust? (how to do it if the test and source files are in the same folder.)
The files src/int_rle.rs and src/lib.rs form your library, and together are called a crate.
Your tests and examples folders are not considered part of the crate. This is good, because when someone uses your library, they don't need your tests, they just need your library.
You can fix your issue by adding the line extern crate minimal_example_test_directories; to the top of tests/test_int_rle.rs.
You can read more about Rust's crate and module structure in the book, here.
This should be a working version of your test file:
// tests/test_int_rle.rs
extern crate minimal_example_test_directories;
pub use minimal_example_test_directories::int_rle;
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
super::int_rle::IntRle { values: vec![1, 2, 3] };
}
}

Resources