Closed Relrin closed 8 years ago
struct Point(i32, i32)
is a tuple struct, not a newtype struct. Try using something like struct Meters(i32)
.
See https://serde.rs/impl-serialize.html#serializing-a-struct and The Book for the different types of structs.
You also need to set up Serde to generate a Serialize implementation for your struct. As an example see how Bincode does this, and it is documented at https://serde.rs/codegen.html.
In Cargo.toml add:
[dev-dependencies]
serde_macros = "0.8"
In tests/tests.rs add:
#![feature(plugin, custom_derive)]
#![plugin(serde_macros)]
#[test]
fn serialize_newtype_struct() {
#[derive(Serialize, Deserialize)]
struct Meters(i32);
let km = Meters(1000);
assert_eq!(
term_to_binary(&km).unwrap(),
// ... some result there
);
}
You need to move your tests out of src
and into a tests directory, the way Bincode has them. Otherwise your crate will depend on serde_macros even when not running tests.
Also this setup requires that your tests are run with a nightly compiler only (which is good enough for Bincode). There is a Rust PR https://github.com/rust-lang/rust/pull/35957 which will allow it to work on stable so we are not that far away, but if you want it to work on a stable compiler now, there is a more complicated setup using a build script - see serde-yaml as an example.
EDIT: never mind about the crossed out part. You can put this in src/lib.rs and keep the tests where they are.
#![cfg_attr(test, feature(plugin, custom_derive))]
#![cfg_attr(test, plugin(serde_macros))]
So, I have separated my module into two different: bert
and bert_tests
.
In the bert module my Cargo.toml looks like this:
[dependencies]
serde = "0.8.3"
num = "0.1.34"
byteorder = "0.5.3"
[dev-dependencies]
serde_macros = "0.8.*"
And in bert_tests
Cargo.toml file:
[features]
default = ["serde_macros"]
with-syntex = ["syntex", "serde_codegen", "indoc/with-syntex"]
[build-dependencies]
syntex = { version = "*", optional = true }
serde_codegen = { version = "0.8.0", optional = true }
indoc = "*"
[dependencies]
bert = { path = "../bert" }
serde = "0.8.3"
serde_macros = { version = "0.8.0", optional = true }
[[test]]
name = "test"
path = "tests/test.rs"
In the test.rs of bert_tests crate:
#![cfg_attr(not(feature = "with-syntex"), feature(custom_derive, plugin))]
#![cfg_attr(not(feature = "with-syntex"), plugin(serde_macros))]
extern crate serde;
extern crate bert;
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/test.rs"));
#[cfg(not(feature = "with-syntex"))]
include!("test.rs.in");
But in the result I'd taken an error from the Rust compiler:
relrin at MacBook-Relrin in ~/code/bert-rs/bert_tests on git:serde-rs-support+? => cargo test Compiling aster v0.25.0 Compiling rustc-serialize v0.3.19 Compiling num-traits v0.1.35 Compiling serde_codegen v0.8.4 Compiling quasi v0.18.0 /Users/savicvalera/.cargo/registry/src/github.com-1ecc6299db9ec823/aster-0.25.0/src/lib.rs:1:43: 1:66 error: #[feature] may not be used on the stable release channel /Users/savicvalera/.cargo/registry/src/github.com-1ecc6299db9ec823/aster-0.25.0/src/lib.rs:1 #![cfg_attr(not(feature = "with-syntex"), feature(rustc_private))] ^
~~~~~~ error: aborting due to previous error Build failed, waiting for other jobs to finish... /Users/savicvalera/.cargo/registry/src/github.com-1ecc6299db9ec823/quasi-0.18.0/src/lib.rs:11:43: 11:66 error: #[feature] may not be used on the stable release channel /Users/savicvalera/.cargo/registry/src/github.com-1ecc6299db9ec823/quasi-0.18.0/src/lib.rs:11 #![cfg_attr(not(feature = "with-syntex"), feature(rustc_private))] ^~~~~~~ error: aborting due to previous error error: Could not compileaster
.To learn more, run the command again with --verbose.
Running the tests with serde_macros (the default) requires a nightly compiler.
$ rustup run nightly cargo test
Running them without serde_macros on a stable compiler:
$ rustup run stable cargo test --no-default-features --features with-syntex
# or if you are using stable by default, just:
$ cargo test --no-default-features --features with-syntex
In bert_tests/Cargo.toml you can set stable to be the default by doing this, although typically it will compile faster on nightly so I would recommend keeping the default as nightly.
[features]
default = ["with-syntex"] # instead of "serde-macros"
Then on stable:
$ rustup run stable cargo test
And on nightly:
$ rustup run nightly cargo test --no-default-features --features serde_macros
I don't understand this clearly, because I'm new in Rust lang. Could you say, whether I'm doing it right? Maybe I'm doing it wrong:
1) Installed rustup
toolchain on my Mac.
2) Set default in rustup
toolchain to stable and downloaded nightly build also.
3) I've fixed my test.rs and Cargo.toml files in the bert_tests crate to this:
test.rs:
#![cfg_attr(not(feature = "with-syntex"), feature(custom_derive, plugin))]
#![cfg_attr(not(feature = "with-syntex"), plugin(serde_macros))]
extern crate serde;
extern crate bert;
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/test.rs"));
#[cfg(not(feature = "with-syntex"))]
include!("test.rs.in");
Cargo.toml
[features]
default = ["with-syntex"]
with-syntex = ["syntex", "serde_codegen"]
[build-dependencies]
syntex = { version = "*", optional = true }
serde_codegen = { version = "0.8.0", optional = true }
[dependencies]
bert = { path = "../bert" }
serde = "0.8.3"
serde_macros = { version = "0.8.0", optional = true }
[[test]]
name = "test"
path = "tests/test.rs"
5) Fixed bert/src/lib.rs to this:
#![cfg_attr(test, feature(plugin, custom_derive))]
#![cfg_attr(test, plugin(serde_macros))]
extern crate byteorder;
extern crate num;
extern crate serde;
pub use errors::{Error};
pub use serializers::{Serializer, term_to_binary, to_vec, to_writer};
pub use types::{
BERT_LABEL, EXT_VERSION,
BertTag, BertNil, BertTime, BertRegex
};
mod serializers;
mod types;
mod errors;
5) After that in my terminal I must: Run my tests on the stable branch:
$ rustup run stable cargo test
and nightly branch:
$ rustup run nightly cargo test --no-default-features --features serde_macros
6) All this tests should successfully passed?
If all these steps are right, so... Compiler warn me, that some of functionality are private, not public:
rustup run nightly cargo test
Downloading syntex v0.42.2
Downloading syntex_syntax v0.42.0
Downloading syntex_errors v0.42.0
Downloading log v0.3.6
Downloading syntex_pos v0.42.0
Downloading term v0.4.4
Downloading unicode-xid v0.0.3
Downloading winapi v0.2.8
Downloading kernel32-sys v0.2.2
Downloading winapi-build v0.1.1
Downloading bitflags v0.5.0
Compiling winapi-build v0.1.1
Compiling unicode-xid v0.0.3
Compiling log v0.3.6
Compiling syntex_pos v0.42.0
Compiling bitflags v0.5.0
Compiling winapi v0.2.8
Compiling kernel32-sys v0.2.2
Compiling term v0.4.4
Compiling syntex_errors v0.42.0
Compiling syntex_syntax v0.42.0
Compiling serde_codegen_internals v0.7.0
Compiling syntex v0.42.2
Compiling aster v0.25.0
Compiling quasi v0.18.0
Compiling quasi_codegen v0.18.0
Compiling serde_codegen v0.8.4
Compiling bert_tests v0.1.0 (file:///Users/savicvalera/code/bert-rs/bert_tests)
error: module `serializers` is private
--> /Users/savicvalera/code/bert-rs/bert_tests/target/debug/build/bert_tests-b995ea8bc9a96268/out/test.rs:5:29
|
5 | use bert::serializers::{Serializer, term_to_binary, to_vec};
| ^^^^^^^^^^
error: module `serializers` is private
--> /Users/savicvalera/code/bert-rs/bert_tests/target/debug/build/bert_tests-b995ea8bc9a96268/out/test.rs:5:41
|
5 | use bert::serializers::{Serializer, term_to_binary, to_vec};
| ^^^^^^^^^^^^^^
error: module `serializers` is private
--> /Users/savicvalera/code/bert-rs/bert_tests/target/debug/build/bert_tests-b995ea8bc9a96268/out/test.rs:5:57
|
5 | use bert::serializers::{Serializer, term_to_binary, to_vec};
| ^^^^^^
error: module `types` is private
--> /Users/savicvalera/code/bert-rs/bert_tests/target/debug/build/bert_tests-b995ea8bc9a96268/out/test.rs:6:23
|
6 | use bert::types::{BertTag};
| ^^^^^^^
error: aborting due to 4 previous errors
error: Could not compile `bert_tests`.
To learn more, run the command again with --verbose.
See Crates and Modules: Exporting a Public Interface.
In bert/src/lib.rs
you have mod serializers
and pub use serializers::{Serializer, term_to_binary, to_vec, to_writer}
, which means bert::serializers
is private but bert::serializers::Serializer
is exposed publically as just bert::Serializer
(and similarly for the other types/functions/modules). Your tests (and other crates) should be using the public interface: bert::{Serializer, term_to_binary, to_vec, to_writer}
.
I've fixed this issue. Just add the pub
before the mod
keyword. Now all tests have passed and works fine. Thanks!
You shouldn't have both pub mod serializers
and pub use serializers::{...}
because then the types and functions are exposed publically in two places which is confusing: bert::term_to_binary
and bert::serializers::term_to_binary
. I would recommend using just mod serializers
like you had before, but fixing the tests to use bert::{...}
instead of bert::serializers::{...}
.
I've got it! Thanks for the useful tip. 😃
Currently I'm trying to implement serializing newtype structs. So, we have the next code:
And simple test for this stuff:
term_to_binary
function it's no more than a little wrapper, which let so use BERT serializer more easier way. It has the next signature:So, how can I invoke the
serialize_newtype_struct
method with passed into term_to_binary newtype struct from test?