What's the difference between the "serialize" and "rustc-serialize" crates? - rust

This is the serialize crate, and this is the rustc-serialize crate.
I'm getting deprecation warnings from the compiler when using the Encodable and Decodable traits from the serialize crate. The compiler tells me to use RustcEncodable and RustcDecodable from the rustc-serialize crate.
It seems like this just makes things less readable for the same functionality (apart from base64 encoding provided in rustc-serialize). What's the difference between these crates?

The serialize crate is an internal part of the standard Rust distribution. It won't be available in the Rust 1.0 stable/beta channels.
The rustc-serialize crate used to be serialize, but it was moved out to a separate repository and uploaded to crates.io so that it can evolve on its own.
This was done because the utility of rustc-serialize is enormous but it was not realistic to get it stabilized in time for Rust 1.0. Since the Rust distribution will prohibit unstable features on the stable channel, the only way to continue using the serialization infrastructure is to 1) stabilize what we have or 2) move it to crates.io, where the unstable restrictions don't apply.
rustc-serialize has a lot of known downsides, and it is being worked on, so stabilizing what was there really isn't an option.
But the Decodable/Encodable features require compiler support (because compiler plugins won't be stable either for Rust 1.0). As a stopgap measure, RustcDecodable/RustcEncodable were invented as a temporary measure for the rustc-serialize crate to use explicitly. It's a bit weird, but it leaves the Decodable/Encodable names available for a future backwards-compatible version of a serialize crate that is better than what we have now (perhaps this is what serde2 will become from the aforementioned link).
So for the time being, stick to use rustc-serialize and RustcDecodable/RustcEncodable.
(I apologize that I can't come up with a link to cite all of this. It's knowledge I've accrued over time from GitHub issues. Maybe there is an RFC that lays all of this out though. I can't remember.)

To expand on BurntSushi5's answer, as of the time of this writing, the Rust compiler in both Stable and Beta channels throws the following error when attempting to use vanilla serialize:
error: use of unstable library feature 'rustc_private': deprecated in favor of rustc-serialize on crates.io (see issue #27812)
--> src/main.rs:2:1
|
2 | extern crate serialize;
| ^^^^^^^^^^^^^^^^^^^^^^^
The linked Github issue is not very helpful. In short, use rustc-serialize.

Related

How to use a type from dependence's dependence?

I'd like to use a type returned by a function in crate A that is actually defined in crate B, but crate A doesn't reexport it.
Although I can explicitly add crate B in my Cargo.toml, I'm not sure how to keep its version sync with the one used in crate A.
To be more specific, the type is url::ParseError, crate A is reqwest and crate B is url.
There are no "official" guidelines around this issue. There was a discussion regarding best practices a while back with no definite conclusion. Many crates wrap external types so they aren't exposed directly, or they re-export items. This specific issue with reqwest was discussed here and it was decided to not re-export url::ParseError:
My personal feeling is that this is somewhat niche, and so for those who don't need it, it just clutters the API. For anyone who does need to inspect for this specific error, they can add the url crate as a dependency.

Linking against binary crate

There's a crate I want to use as a library for some of my own code (speedtest-rs specifically, but it doesn't really matter). However, whenever I try to use this crate, the compiler doesn't want to play nice with it.
$ cargo build
Compiling my-project v0.1.0 (/home/nick/Documents/code/my-project)
error[E0432]: unresolved import `speedtest_rs`
--> src/main.rs:1:5
|
1 | use speedtest_rs::*;
| ^^^^^^^^^^^^ use of undeclared type or module `speedtest_rs`
Looking at the Rust book, it seems like there's a distinction between a binary and library crae
The rand crate is a library crate which contains code intended to be used in other programs
Some googling has shown me that binary crates just have an extra link step, so I should be able to link against them, right? I know a lot of Rust packages have both a library and a binary in them, but what do you do when an author does not seem to follow this pattern?
Some googling has shown me that binary crates just have an extra link step, so I should be able to link against them, right?
No. It's not that simple. Plus that extra step creates an executable file rather than a library file. An executable cannot be used as a library.
I know a lot of Rust packages have both a library and a binary in them, but what do you do when an author does not seem to follow this pattern?
You can:
Ask them on GitHub to publish a library.
Fork the crate and make your own library (which you can do since it is published with the usual dual “Apache License, Version 2.0” + “MIT” license).
There isn't an automated way to use a binary crate as a library because in particular:
Rust won't generate a library.
Since the crate is missing a src/lib.rs file, nothing is exported. This is akin to have all items in that crate private. You wouldn't be able to use anything.

Can Rust code compile without the standard library?

I'm currently in the progress of learning Rust. I'm mainly using The Rust Programming Language book and this nice reference which relates Rust features/syntax to C++ equivalents.
I'm having a hard time understanding where the core language stops and the standard library starts. I've encountered a lot of operators and/or traits which seems to have a special relationship with the compiler. For example, Rust has a trait (which from what I understand is like an interface) called Deref which let's a type implementing it be de-referenced using the * operator:
fn main() {
let x = 5;
let y = Box::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
Another example is the ? operator, which seems to depend on the Result and Option types.
Can code that uses those operators can be compiled without the standard library? And if not, what parts of the Rust language are depending on the standard library? Is it even possible to compile any Rust code without it?
The Rust standard library is in fact separated into three distinct crates:
core, which is the glue between the language and the standard library. All types, traits and functions required by the language are found in this crate. This includes operator traits (found in core::ops), the Future trait (used by async fn), and compiler intrinsics. The core crate does not have any dependencies, so you can always use it.
alloc, which contains types and traits related to or requiring dynamic memory allocation. This includes dynamically allocated types such as Box<T>, Vec<T> and String.
std, which contains the whole standard library, including things from core and alloc but also things with further requirements, such as file system access, networking, etc.
If your environment does not provide the functionality required by the std crate, you can choose to compile without it. If your environment also does not provide dynamic memory allocation, you can choose to compile without the alloc crate as well. This option is useful for targets such as embedded systems or writing operating systems, where you usually won't have all of the things that the standard library usually requires.
You can use the #![no_std] attribute in the root of your crate to tell the compiler to compile without the standard library (only core). Many libraries also usually support "no-std" compilation (e.g. base64 and futures), where functionality may be restricted but it will work when compiling without the std crate.
DISCLAIMER: This is likely not the answer you're looking for. Consider reading the other answers about no_std, if you're trying to solve a problem. I suggest you only read on, if you're interested in trivia about the inner workings of Rust.
If you really want full control over the environment you use, it is possible to use Rust without the core library using the no_core attribute.
If you decide to do so, you will run into some problems, because the compiler is integrated with some items defined in core.
This integration works by applying the #[lang = "..."] attribute to those items, making them so called "lang items".
If you use no_core, you'll have to define your own lang items for the parts of the language you'll actually use.
For more information I suggest the following blog posts, which go into more detail on the topic of lang items and no_core:
Rust Tidbits: What Is a Lang Item?
Oxidizing the technical interview
So yes, in theory it is possible to run Rust code without any sort of standard library and supplied types, but only if you then supply the required types yourself.
Also this is not stable and will likely never be stabilized and it is generally not a recommended way of using Rust.
When you're not using std, you rely on core, which is a subset of the std library which is always (?) available. This is what's called a no_std environment, which is commonly used for some types of "embedded" programming. You can find more about no_std in the Rust Embedded book, including some guidance on how to get started with no_std programming.

How do I add #![feature(***)] to another crate's attributes without forking the crate?

Every time I see an error like:
error: associated constants are experimental (see issue #29646)
...
= help: add #![feature(associated_consts)] to the crate attributes to enable
= note: this error originates in a macro outside of the current crate
I fork the crate and add the feature to the crate attributes and then replace the dependency in my Cargo.toml:
[replace."bitflags:1.0.0"]
git = "https://github.com/boehm-s/bitflags"
rev = "bb2afce"
Is there a way to get rid of these errors without forking crates?
Associated constants were stabilized recently in Rust 1.20; this error should disappear without any code changes if you upgrade your Rust compiler.
In addition to [replace] and [patch], there's also the option of using .cargo/config to override a dependency locally without changing Cargo.toml.
How do I add #![feature(***)] to another crate's attributes without forking the crate?
You don't. You cannot change another crate without... changing it.
You are using an old nightly compiler; update it. If you are using a nightly compiler, it's your responsibility to keep it up-to-date. If you don't know why you have a nightly compiler, switch to a stable compiler.
This can only occur if:
You are using a nightly compiler. If you weren't, you wouldn't get the suggestion to add the attribute, it'd be a hard error.
You are using a crate that relies on a feature that has not been stabilized in your version of the compiler and thus requires the attribute to enable it.
The feature has been stabilized in a newer version of Rust and thus the crate no longer needs to have the attribute itself.
For this example, you can read the crates changelog:
1.0.0
[breaking change] Macro now generates associated constants (#24)
[breaking change] Minimum supported version is Rust 1.20, due to usage of associated constants

How to dynamically allocate a fixed runtime-sized array?

I'm essentially looking for malloc/free in Rust.
I found alloc::heap, but when I try to use it I get the following error:
main.rs:1:1: 1:19 error: unstable feature
main.rs:1 ![feature(alloc)]
note: this feature may not be used in the stable release channel
If you want to do it in high-level Rust (RAII, memory safety, bounds checking), you should allocate by creating a Vec. You can optionally use into_boxed_slice to disable resizing the container. See the book's FFI example (specifically the uncompress function) for an example of using Vec as an allocator.
Either use a nightly Rust or you will have to use libc::funcs::c95::stdlib::malloc(size: size_t) from the libc crate. You'll have to transmute the result of course.

Resources