Why can I use Ok and Err directly without the Result:: prefix? - enums

For example:
enum Foobar {
Foo(i32),
Bar(i32),
}
fn main() {
let a: Result<i32, i32> = Result::Ok(1);
let b: Result<i32, i32> = Ok(1);
let c: Foobar = Foobar::Foo(1);
let d: Foobar = Foo(1); // Error!
}
I have to write Foobar::Foo() instead of just Foo(), but I can just write Ok() without Result::. Why is that? I have the same question for Some and None.

A use item can add enum variants to a namespace, so that you don't have to prefix them by the enum's name.
use Foobar::*;
enum Foobar {
Foo(i32),
Bar(i32)
}
fn main() {
let a: Result<i32, i32> = Result::Ok(1);
let b: Result<i32, i32> = Ok(1);
let c: Foobar = Foobar::Foo(1);
let d: Foobar = Foo(1); // Not an error anymore!
}
The reason why Ok, Err, Some and None are available without qualification is that the prelude has some use items that add these names to the prelude (in addition to the enums themselves):
pub use option::Option::{self, Some, None};
pub use result::Result::{self, Ok, Err};

Related

Set same attribute on multiple instances of struct without for loop in Rust

I have a Vec of MyStruct (Vec<MyStruct>):
struct MyStruct {
attr1: i32,
...
}
let mut my_vec = Vec::new();
for _ in 1..100 {
my_vec.push(MyStruct::new());
}
And I need to set the attr1 to the same value val1 on all the instances on that Vec. What I have right now to do this is:
let new_attr1 = 42;
for my_str in my_vec.iter_mut() {
my_str.attr1 = new_attr1;
}
Is there a way to do this without a for loop that's more idiomatic?
Is there a way to do this without a for loop
Using for_each() maybe?
my_vec.iter_mut().for_each(|my_str| my_str.attr1 = new_attr1);
that's more idiomatic
No. In fact, it's the opposite:
It's generally more idiomatic to use a for loop
Two things to note about this code, however:
Prefer for my_str in &mut my_vec to for my_str in my_vec.iter_mut(). In fact, there's even a Clippy lint for that.
If you find yourself doing that a lot of times, you can define a macro for it:
macro_rules! set_all {
( $collection:ident . $attr:ident = $value:expr ) => {
for item in &mut $collection {
item.$attr = $value;
}
};
}
set_all!(my_vec.attr1 = new_attr1);
But I doubt this is better.

Access the methods of primitive Rust types

How can I access the methods of primitive types in Rust?
Concretely, I want to pass either one of the two slice methods split_first_mut and split_last_mut to a function operating on slices. I know you can wrap them in closures as a workaround, but I’d like to know if direct access is possible.
You can access the methods on primitives just like regular types:
u8::to_le();
str::from_utf8();
<[_]>::split_first_mut();
You can create a function that accepts a slice ops function:
fn do_thing<T>(f: impl Fn(&mut [u8])) -> Option<(&mut T, &mut [T])>) {
// ...
}
And pass in both split_first_mut and split_last_mut:
fn main() {
do_thing(<[_]>::split_first_mut);
do_thing(<[_]>::split_last_mut);
}
You have to refer to the method using fully-qualified syntax. In a nutshell: <T>::{method_name} where T is the type and {method_name} is the name of the method. For example, if you're modifying a [i32] then you'd to prefix the method name with <[i32]>:: like this:
fn apply_fn<T, U>(t: T, t_fn: fn(T) -> U) -> U {
t_fn(t)
}
fn main() {
let mut items: Vec<i32> = vec![1, 2, 3];
let slice: &mut [i32] = items.as_mut_slice();
let first_split = apply_fn(slice, <[i32]>::split_first_mut);
let slice: &mut [i32] = items.as_mut_slice();
let last_split = apply_fn(slice, <[i32]>::split_last_mut);
}
playground

Is it possible to unpack a tuple into method arguments?

Unpacking a tuple as arguments and calling a function with those values is covered by Is it possible to unpack a tuple into function arguments?, but is it possible to do the same trick on methods?
#![feature(fn_traits)]
struct Foo;
impl Foo {
fn method(&self, a: i32, b: i32) {
println!("{:?}, {:?}", a, b);
}
}
fn main() {
let foo = Foo;
let tuple = (10, 42);
// does not compile
//foo.method.call(tuple);
// nor this one
//std::ops::Fn::call(&foo.method, tuple);
}
For both I get the following error:
error[E0615]: attempted to take value of method `method` on type `Foo`
--> src/main.rs:20:9
|
20 | foo.method.call(tuple);
| ^^^^^^ help: use parentheses to call the method: `method(...)`
I do not control the method I call, so changing the signature to accept tuples is not an option.
Methods are functions that
Are associated with a type (called associated functions). Most people are familiar with "constructor" associated functions like new. These are referenced as Type::function_name.
Take some kind of Self as the first argument.
Thus you need to use Foo::method and provide a matching self:
#![feature(fn_traits)]
struct Foo;
impl Foo {
fn method(&self, a: i32, b: i32) {
println!("{:?}, {:?}", a, b);
}
}
fn main() {
let foo = Foo;
let tuple = (&foo, 10, 42);
std::ops::Fn::call(&Foo::method, tuple);
}
See also:
Fully-qualified syntax
What types are valid for the `self` parameter of a method?

How to match enum variants dynamically in Rust? [duplicate]

I have an enum with the following structure:
enum Expression {
Add(Add),
Mul(Mul),
Var(Var),
Coeff(Coeff)
}
where the 'members' of each variant are structs.
Now I want to compare if two enums have the same variant. So if I have
let a = Expression::Add({something});
let b = Expression::Add({somethingelse});
cmpvariant(a, b) should be true. I can imagine a simple double match code that goes through all the options for both enum instances. However, I am looking for a fancier solution, if it exists. If not, is there overhead for the double match? I imagine that internally I am just comparing two ints (ideally).
As of Rust 1.21.0, you can use std::mem::discriminant:
fn variant_eq(a: &Op, b: &Op) -> bool {
std::mem::discriminant(a) == std::mem::discriminant(b)
}
This is nice because it can be very generic:
fn variant_eq<T>(a: &T, b: &T) -> bool {
std::mem::discriminant(a) == std::mem::discriminant(b)
}
Before Rust 1.21.0, I'd match on the tuple of both arguments and ignore the contents of the tuple with _ or ..:
struct Add(u8);
struct Sub(u8);
enum Op {
Add(Add),
Sub(Sub),
}
fn variant_eq(a: &Op, b: &Op) -> bool {
match (a, b) {
(&Op::Add(..), &Op::Add(..)) => true,
(&Op::Sub(..), &Op::Sub(..)) => true,
_ => false,
}
}
fn main() {
let a = Op::Add(Add(42));
let b = Op::Add(Add(42));
let c = Op::Add(Add(21));
let d = Op::Sub(Sub(42));
println!("{}", variant_eq(&a, &b));
println!("{}", variant_eq(&a, &c));
println!("{}", variant_eq(&a, &d));
}
I took the liberty of renaming the function though, as the components of enums are called variants, and really you are testing to see if they are equal, not comparing them (which is usually used for ordering / sorting).
For performance, let's look at the LLVM IR in generated by Rust 1.60.0 in release mode (and marking variant_eq as #[inline(never)]). The Rust Playground can show you this:
; playground::variant_eq
; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind nonlazybind readonly uwtable willreturn
define internal fastcc noundef zeroext i1 #_ZN10playground10variant_eq17hc64d59c7864eb861E(i8 %a.0.0.val, i8 %b.0.0.val) unnamed_addr #2 {
start:
%_8.not = icmp eq i8 %a.0.0.val, %b.0.0.val
ret i1 %_8.not
}
This code directly compares the variant discriminant.
If you wanted to have a macro to generate the function, something like this might be good start.
struct Add(u8);
struct Sub(u8);
macro_rules! foo {
(enum $name:ident {
$($vname:ident($inner:ty),)*
}) => {
enum $name {
$($vname($inner),)*
}
impl $name {
fn variant_eq(&self, b: &Self) -> bool {
match (self, b) {
$((&$name::$vname(..), &$name::$vname(..)) => true,)*
_ => false,
}
}
}
}
}
foo! {
enum Op {
Add(Add),
Sub(Sub),
}
}
fn main() {
let a = Op::Add(Add(42));
let b = Op::Add(Add(42));
let c = Op::Add(Add(21));
let d = Op::Sub(Sub(42));
println!("{}", Op::variant_eq(&a, &b));
println!("{}", Op::variant_eq(&a, &c));
println!("{}", Op::variant_eq(&a, &d));
}
The macro does have limitations though - all the variants need to have a single variant. Supporting unit variants, variants with more than one type, struct variants, visibility, etc are all real hard. Perhaps a procedural macro would make it a bit easier.

Transmuting u8 buffer to struct in Rust

I have a byte buffer of unknown size, and I want to create a local struct variable pointing to the memory of the beginning of the buffer. Following what I'd do in C, I tried a lot of different things in Rust and kept getting errors. This is my latest attempt:
use std::mem::{size_of, transmute};
#[repr(C, packed)]
struct MyStruct {
foo: u16,
bar: u8,
}
fn main() {
let v: Vec<u8> = vec![1, 2, 3];
let buffer = v.as_slice();
let s: MyStruct = unsafe { transmute(buffer[..size_of::<MyStruct>()]) };
}
I get an error:
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> src/main.rs:12:42
|
12 | let s: MyStruct = unsafe { transmute(buffer[..size_of::<MyStruct>()]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
If you don't want to copy the data to the struct but instead leave it in place, you can use slice::align_to. This creates a &MyStruct instead:
#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
struct MyStruct {
foo: u16,
bar: u8,
}
fn main() {
let v = vec![1u8, 2, 3];
// I copied this code from Stack Overflow
// without understanding why this case is safe.
let (head, body, _tail) = unsafe { v.align_to::<MyStruct>() };
assert!(head.is_empty(), "Data was not aligned");
let my_struct = &body[0];
println!("{:?}", my_struct);
}
Here, it's safe to use align_to to transmute some bytes to MyStruct because we've used repr(C, packed) and all of the types in MyStruct can be any arbitrary bytes.
See also:
How to read a struct from a file in Rust?
Can I take a byte array and deserialize it into a struct?
You can use methods on raw pointers and functions in std::ptr to directly read/write objects in place.
std::ptr::read
std::ptr::read_unaligned
std::ptr::write
std::ptr::write_unaligned
In your case:
fn main() {
let v: Vec<u8> = vec![1, 2, 3];
let s: MyStruct = unsafe { std::ptr::read(v.as_ptr() as *const _) };
println!("here is the struct: {:?}", s);
}
I would encourage you to wrap this in a reusable method and perform a length check on the source buffer before attempting the read.
I gave up on the transmute stuff. *mut (raw pointers) in Rust are pretty similar to C pointers, so this was easy:
#[repr(C, packed)] // necessary
#[derive(Debug, Copy, Clone)] // not necessary
struct MyStruct {
foo: u16,
bar: u8,
}
fn main() {
let v: Vec<u8> = vec![1, 2, 3];
let buffer = v.as_slice();
let mut s_safe: Option<&MyStruct> = None;
let c_buf = buffer.as_ptr();
let s = c_buf as *mut MyStruct;
unsafe {
let ref s2 = *s;
s_safe = Some(s2);
}
println!("here is the struct: {:?}", s_safe.unwrap());
}
The unsafe tag there is no joke, but the way I'm using this, I know my buffer is filled and take the proper precautions involving endianness later on.

Resources