-
Notifications
You must be signed in to change notification settings - Fork 1
Home
This is where I am collecting a list of issues, notes, and critiques of the Rust language in the course of translating the Google Brotli decoder from C.
Rust has a habit of complaining about incompatible types, even in cases where an automatic cast should be available. For example, adding a smaller integer to a larger one is an error, unlike in most other languages:
expected `u16`,
found `u32`
(expected u16,
found u32) [E0308]
src\decoder.rs:31 offs += table[offs].value + ((bits >> HUFFMAN_TABLE_BITS) & !((0xffffffff) << nbits ));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src\decoder.rs:31:41: 31:99 help: run `rustc --explain E0308` to see a detailed explanation
src\decoder.rs:31:21: 31:99 error: mismatched types:
While Rust makes many difficult things trivial, such as thread safety, trivial things are often inordinately difficult. There is no elegant, simple way to invoke the memcpy
intrinsic on a pair of slices containing data with the 'Copy' trait. This should be a built-in language element, but the only safe, stable API I've found is to use the std::io
library, as follows:
dst.write( src ).unwrap();
Eww....
Opened a Rust issue: https://github.com/rust-lang/rust/issues/29010
Google has put some effort into optimising Brotli for mobile devices. For example, there are short functions and macros defined in a number of places that expose compiler optimisations or native instructions. Such macros fall through to plain C code on platforms that are missing native support. Rust has some of these instructions or compiler hints exposed in the standard library, but key ones are missing.
For example, the original Google code uses these macros to give the compiler optimisation hints. Note the "LLVM" filter! Rust uses LLVM as a back-end as well, so the back-end support is certainly available!
#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || \
(defined(__llvm__) && __has_builtin(__builtin_expect))
#define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#define PREDICT_FALSE(x) (__builtin_expect(x, 0))
#else
#define PREDICT_FALSE(x) (x)
#define PREDICT_TRUE(x) (x)
#endif
An interesting case is this macro, which checks if a value is known at compile time. This allows some fairly complex optimisations to be made, allowing the rather primitive C language to emulate some of the more advanced features typically only found in languages like C++:
/* IS_CONSTANT macros returns true for compile-time constant expressions. */
#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) || \
(defined(__llvm__) && __has_builtin(__builtin_constant_p))
#define IS_CONSTANT(x) __builtin_constant_p(x)
#else
#define IS_CONSTANT(x) 0
#endif
The biggest gap is the bit/byte manipulation instructions. Some are present, but the ARM rbit
instruction, for example, is missing.
This should compile, but doesn't:
#[derive(Default)]
struct Foo {
bar: [i32;4]
}