Java enum-like behavior in Rust - rust

I want to have an enum where each value in the enum stores a constant array of bytes that represent the RGBA values for a color. In Java I would do this:
public enum Color {
BLACK([0x0C, 0x00, 0x05, 0xFF]),
BLUE([0x00, 0x2D, 0xFF, 0xFF]),
RED([0xFF, 0x3E, 0x00, 0xFF]);
private final byte[] rgba;
Color(byte[] rgba) {
this.rgba = rgba;
}
public int[] value() {
return rgba;
}
}
Then I could pass around Color types and just use color.value() to get the bytes out. This is what I have in Rust:
struct Color;
impl Color {
pub const BLACK: [u8; 4] = [0x0C, 0x00, 0x05, 0xFF];
pub const BLUE: [u8; 4] = [0x00, 0x2D, 0xFF, 0xFF];
pub const RED: [u8; 4] = [0xFF, 0x3E, 0x00, 0xFF];
}
But this means that anywhere I want to pass a Color the type is [u8; 4]. I could call the struct Colors and then do pub type Color = [u8; 4]. Then you could have the type as Color but then it would be Colors::BLACK which seems weird.

If you want to have a strong type for the byte array in the Color struct, you can use the following notation, called a tuple struct:
struct Color([u8; 4]);
impl Color {
pub const BLACK: Color = Color([0x0C, 0x00, 0x05, 0xFF]);
pub const BLUE: Color = Color([0x00, 0x2D, 0xFF, 0xFF]);
pub const RED: Color = Color([0xFF, 0x3E, 0x00, 0xFF]);
}
fn main() {
// classic way of accessing data
println!("{:?}", Color::BLACK.0);
// using destructuring
let Color(bytes) = Color::BLUE;
println!("{:?}", bytes);
}
Playground link

I have created a crate enumeration just for this.
Example using my crate:
use enumeration::prelude::*;
enumerate!(pub Color(u8; [u8; 4])
Black = [0x0C, 0x00, 0x05, 0xFF]
Blue = [0x00, 0x2D, 0xFF, 0xFF]
Red = [0xFF, 0x3E, 0x00, 0xFF]
);
pub fn main() {
assert_eq!(*Color::Black.value(), [0x0C, 0x00, 0x05, 0xFF]);
assert_eq!(*Color::Blue.value(), [0x00, 0x2D, 0xFF, 0xFF]);
assert_eq!(*Color::Red.value(), [0xFF, 0x3E, 0x00, 0xFF]);
}

Related

How to manipulate buffer in Rust?

a few weeks ago I got interested in Rust. So far I have only read online tutorials and wonder how to manipulate buffer memory in Rust. Let's say I have C code like this:
int main()
{
char buffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa };
int a = *(int*)&buffer[0];
a = 0xdeadc0de;
short b = *(short*)&buffer[4];
b = 0xbadf;
*(int*)&buffer[0] = a;
*(short*)&buffer[4] = b;
//buffer memory: de c0 ad de df ba 77 88 99 aa
return 0;
}
Could anyone write this in Rust please? I think there's no casting in Rust, right?
Direct buffer manipulation through transmuted references is considered unsafe in Rust. You can of course use the unsafe keyword for writing into memory directly, but that would negate the whole safety advantage of using Rust.
You can create an u32, convert it to a [u8] array and then write that into the buffer. But you cannot safely get a &u32 reference from a buffer.
fn main() {
let mut buffer = vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa];
let a: u32 = 0xdeadc0de;
let a_bytes = a.to_le_bytes();
buffer[0..4].copy_from_slice(&a_bytes);
let b: u16 = 0xbadf;
let b_bytes = b.to_le_bytes();
buffer[4..6].copy_from_slice(&b_bytes);
println!("{:x?}", buffer);
}
[de, c0, ad, de, df, ba, 77, 88, 99, aa]
Just for reference, this is how this would look like with unsafe code.
I highly discourage this solution, though.
fn main() {
let mut buffer: Vec<u8> = vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa];
unsafe {
let ptr = buffer.as_mut_ptr();
let a = ptr.offset(0) as *mut u32;
*a = 0xdeadc0de;
let b = ptr.offset(4) as *mut u16;
*b = 0xbadf;
}
println!("{:x?}", buffer);
}
[de, c0, ad, de, df, ba, 77, 88, 99, aa]
Note that the unsafe solution does not behave exactly like the safe solution. It will flip the bytes if compiled on a big-endian architecture.
This is what to_le_bytes prevents.

How to implement "take while, but at most N characters" in nom?

How can I give nom's take_while an upper limit on the number of characters it should match? I want to take characters according to a certain condition, but at most N.
Since this will be a very performance critical part of the parser, I'd like to avoid using a bunch of individual take(1usize). Partly, because it feels awkward having to deal with single element slices one-by-one, but also because the compiler probably cannot know at compile time that they must have a size of 1, i.e., it will likely have to generate bound checks or size assertions, right?
Conceptually, a take_while with an upper limit would feel more appropriate. I was hoping I can do the counting with a mutable loop variable myself like so:
let mut i = 0;
let (input, _) = take_while(|c| {
i += 1;
c >= 0x80 && i < 9
})(input)?;
In fact, I could even extract the necessary information in the closure, which most like should result in a very efficient code generation. (The goal is to implement a certain kind of VarInt LSB encoding, i.e., I could update a local mutable variable x = x + (if last_byte { c } else { c & 0x7f }) << 7.)
Unfortunately take_while seems to allow only Fn and not FnMut which probably means this is impossible (why the limitation?). What else could I do to implement that nicely?
Use a Cell to make your closure have interior mutability. Then it can have mutable state, but still implement Fn:
let i = Cell::new(0);
let (input, _) = take_while(|c| {
i.set(i.get() + 1);
c > 0x80 && i.get() < 9
})(input)?;
There is a nom-function take_while_m_n:
const N: usize = ...
fn take_native(input: &[u8]) -> IResult<&[u8], &[u8]> {
take_while_m_n(0, N, |c| c > 0x80)(input)
}
However, with quick benchmark it seems to be remarkably slower than the Cell -answer (or benchmark optimizes wrongly, since the Cell -version takes only 1ns/iter compared to 13ns/iter for the take_while_m_n).
#![feature(test)]
extern crate test;
use std::cell::Cell;
use nom::{
bytes::complete::{take_while, take_while_m_n},
IResult,
};
fn take_cell(input: &[u8]) -> IResult<&[u8], &[u8]> {
let i = Cell::new(0);
let (input, output) = take_while(|c| {
i.set(i.get() + 1);
c > 0x80 && i.get() < 5
})(input)?;
Ok((input, output))
}
fn take_native(input: &[u8]) -> IResult<&[u8], &[u8]> {
take_while_m_n(0, 4, |c| c > 0x80)(input)
}
#[cfg(test)]
mod tests {
use super::*;
const INPUT: &[u8] = &[
0x81, 0x82, 0x83, 0x84, 0x81, 0x82, 0x83, 0x84, 0x81, 0x82, 0x83, 0x84, 0x81, 0x82, 0x83,
0x84, 0x81, 0x82, 0x83, 0x84, 0x81, 0x82, 0x83, 0x84, 0x81, 0x82, 0x83, 0x84,
];
#[bench]
fn bench_cell(b: &mut test::Bencher) {
assert_eq!(take_cell(INPUT).unwrap().1, &[0x81, 0x82, 0x83, 0x84]);
b.iter(|| take_cell(INPUT).unwrap());
}
#[bench]
fn bench_native(b: &mut test::Bencher) {
assert_eq!(take_native(INPUT).unwrap().1, &[0x81, 0x82, 0x83, 0x84]);
b.iter(|| take_native(INPUT).unwrap());
}
}

How to execute raw instructions from a memory buffer in Rust?

I'm attempting to make a buffer of memory executable, then execute it in Rust. I've gotten all the way until I need to cast the raw executable bytes as code/instructions. You can see a working example in C below.
Extra details:
Rust 1.34
Linux
CC 8.2.1
unsigned char code[] = {
0x55, // push %rbp
0x48, 0x89, 0xe5, // mov %rsp,%rbp
0xb8, 0x37, 0x00, 0x00, 0x00, // mov $0x37,%eax
0xc9, // leaveq
0xc3 // retq
};
void reflect(const unsigned char *code) {
void *buf;
/* copy code to executable buffer */
buf = mmap(0, sizeof(code), PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_ANON,-1,0);
memcpy(buf, code, sizeof(code));
((void (*) (void))buf)();
}
extern crate mmap;
use mmap::{MapOption, MemoryMap};
unsafe fn reflect(instructions: &[u8]) {
let map = MemoryMap::new(
instructions.len(),
&[
MapOption::MapAddr(0 as *mut u8),
MapOption::MapOffset(0),
MapOption::MapFd(-1),
MapOption::MapReadable,
MapOption::MapWritable,
MapOption::MapExecutable,
MapOption::MapNonStandardFlags(libc::MAP_ANON),
MapOption::MapNonStandardFlags(libc::MAP_PRIVATE),
],
)
.unwrap();
std::ptr::copy(instructions.as_ptr(), map.data(), instructions.len());
// How to cast into extern "C" fn() ?
}
Use mem::transmute to cast a raw pointer to a function pointer type.
use std::mem;
let func: unsafe extern "C" fn() = mem::transmute(map.data());
func();

How to implement bitwise operations on a bitflags enum?

I have an enum that looks like this:
#[repr(u8)]
pub enum PublicFlags {
PublicFlagVersion = 0x01,
PublicFlagReset = 0x02,
NoncePresent = 0x04,
IdPresent = 0x08,
PktNumLen4 = 0x30,
PktNumLen2 = 0x20,
PktNumLen1 = 0x10,
Multipath = 0x40,
}
I want to do a bitwise operation on several of the enum values. However, the Rust compiler complains:
an implementation of `std::ops::BitAnd` might be missing for `PublicFlags`.
An enum in Rust is not intended to be used as bit flags. PublicFlags can only take the values given in the enum (and not a combination). So for instance, the following match statement is exhaustive:
let flags: PublicFlags;
...
match flags {
PublicFlagVersion => {...}
PublicFlagReset => {...}
NoncePresent => {...}
IdPresent => {...}
PktNumLen4 => {...}
PktNumLen2 => {...}
PktNumLen1 => {...}
Multipath => {...}
}
There is no way to have a PublicFlags variable with a combination of the flags.
The solution is to actually store the value as a u8, then use constants to store the value of each flag. This can be cumbersome, but thankfully the bitflags crate wraps all the boilerplate up in a macro for you. Here is an example how you would create your struct using bitflags:
#[macro_use]
extern crate bitflags;
bitflags! {
flags PublicFlags: u8 {
const PUBLIC_FLAG_VERSION = 0x01,
const PUBLIC_FLAG_RESET = 0x02,
const NONCE_PRESENT = 0x04,
const ID_PRESENT = 0x08,
const PKT_NUM_LEN_4 = 0x30,
const PKT_NUM_LEN_2 = 0x20,
const PKT_NUM_LEN_1 = 0x10,
const MULTIPATH = 0x40,
}
}
fn main() {
let flag = PUBLIC_FLAG_VERSION | ID_PRESENT;
assert!((flag & MULTIPATH).is_empty());
assert!(flag.contains(ID_PRESENT));
}
This could work as an alternative answer without new dependencies.
pub mod PublicFlags {
pub const PublicFlagVersion: u8 = 0x01;
pub const PublicFlagReset: u8 = 0x02;
pub const NoncePresent: u8 = 0x04;
pub const IdPresent: u8 = 0x08;
pub const PktNumLen4: u8 = 0x30;
pub const PktNumLen2: u8 = 0x20;
pub const PktNumLen1: u8 = 0x10;
pub const Multipath: u8 = 0x40;
}
You can refer to the values just like with an enum with PublicFlags::PublicFlagVersion, or add use PublicFlags::*; if it is cleaner to reference the values without specifying the namespace.

How do I get an enum as a string?

I have an enum with many values and I'd like to write the name of one of its values to a stream:
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
// ...
Quux = 0xFF,
}
I can derive Debug and do
writer.write(format!("I am {:?}", Foo::Quux).as_bytes())
which will output e.g. I am Quux. That's fine, except that
I want to do this for user-facing output, so Debug isn't appropriate
It would be very helpful to get the enum as a string (rather than writing directly to a stream), because then I can incorporate its length into some wonky formatting calculations I want to do.
Probably the easiest way would be to implement Display by calling into Debug:
impl fmt::Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
// or, alternatively:
// fmt::Debug::fmt(self, f)
}
}
Then you can use to_string() to get a String representation:
let s: String = Foo::Quux.to_string();
If you have many enums which you want to print, you can write a trivial macro to generate the above implementation of Display for each of them.
Unfortunately, in Rust reflective programming is somewhat difficult. There is no standard way, for example, to get a list of all variants of a C-like enum. Almost always you have to abstract the boilerplate with custom-written macros (or find something on crates.io). Maybe this will change in the future if someone would write an RFC and it would get accepted.
Since the names of enum variants are fixed, you don't need to allocate a String, a &'static str will suffice. A macro can remove the boilerplate:
macro_rules! enum_str {
(enum $name:ident {
$($variant:ident = $val:expr),*,
}) => {
enum $name {
$($variant = $val),*
}
impl $name {
fn name(&self) -> &'static str {
match self {
$($name::$variant => stringify!($variant)),*
}
}
}
};
}
enum_str! {
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
//...
Quux = 0xFF,
}
}
fn main() {
assert_eq!(Foo::Baz.name(), "Baz");
}
Even better, you can derive these with a crate like strum_macros.
In strum 0.10, you can use AsStaticRef / AsStaticStr to do the exact same code:
extern crate strum; // 0.10.0
#[macro_use]
extern crate strum_macros; // 0.10.0
use strum::AsStaticRef;
#[derive(AsStaticStr)]
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
//...
Quux = 0xFF,
}
fn main() {
assert_eq!(Foo::Baz.as_static(), "Baz");
}
In strum 0.9, the string slice's lifetime is not 'static in this case:
#[macro_use]
extern crate strum_macros; // 0.9.0
#[derive(AsRefStr)]
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
//...
Quux = 0xFF,
}
fn main() {
assert_eq!(Foo::Baz.as_ref(), "Baz");
}

Resources