How to get value from Reverse()? - rust

I'm trying MinHeap from std::BinaryHeap like
use std::collections::BinaryHeap;
use std::cmp::Reverse;
let mut heap = BinaryHeap::new();
heap.push(Reverse(1));
heap.push(Reverse(5));
heap.push(Reverse(2));
assert_eq!(heap.pop(), Some(Reverse(1)));
assert_eq!(heap.pop(), Some(Reverse(2)));
assert_eq!(heap.pop(), Some(Reverse(5)));
assert_eq!(heap.pop(), None);
But allow varibles from heap.pop() or heap.peek() is Reverse() type, which is not easy to use, how to get value from it?

From the docs we can see that Reverse is a tuple and its only field is public:
pub struct Reverse<T>(pub T);
This means we can access the field with .0 Like this:
let reversed = Reverse(42);
assert_eq!(reversed.0, 42);

Related

How to get 2 mutable references from 2-D vec at the same time?

I have a 2D Vec and want to get two mutable references from it at the same time, here is the demo code
use std::default::Default;
#[derive(Default, Clone, PartialEq)]
struct Ele {
foo: i32,
bar: f32,
}
fn main() {
let mut data:Vec<Vec<Ele>> = vec![vec![Default::default();100];100];
let a = &mut data[1][2];
let b = &mut data[2][4];
if a != b {
a.foo += b.foo;
b.bar += a.bar;
}
}
Use unsafe code is OK.
You shouldn't try to solve this problem using unsafe, but rather by understanding why the compiler doesn't allow you to do something that looks alright, and what are the available tools to convince it (without hiding it behind a black box and just saying "trust me") it's a genuine thing to do (usually these tools will themselves use unsafe code, but since it's behind a safe boundary it's the burden of the writer of these tools to ensure everything works fine even when the compiler can't figure it out on its own, which is better that having this burden yourself).
In particular, Rust doesn't understand that you are accessing two separate region of memory; being conservative, it just assumes that if you are using a single element of an array, it must consider you are using it all. To make it clear you are talking about two separate pieces of an array, the solution is simply to split the array into two distinct pieces. That way, you make it clear that they are different memory regions:
use std::default::Default;
#[derive(Default, Clone, PartialEq)]
struct Ele {
foo: i32,
bar: f32,
}
fn main() {
let mut data:Vec<Vec<Ele>> = vec![vec![Ele::default();100];100];
let (left, right) = data.split_at_mut(2);
let a = &mut left[1][2];
let b = &mut right[0][4];
if a != b {
a.foo += b.foo;
b.bar += a.bar;
}
}
Note that this will not actually split the vector, it will only give two views over the vector that are disjoint, so it's very efficient.
See the playground.

Get a Vector of Strings from a Rc<RefCell<Vec<String>>> in Rust

I have a function that takes in a Vec<String> value. I want to use this function on values contained inside my_ref, so I need to extract a Vec<String> out of a Rc<RefCell<Vec<String>>>.
I thought I could do this by dereferencing a borrow of my my_ref, just like I would for a Rc<RefCell<f32>>> or Rc<RefCell<i32>>> value:
use std::cell::RefCell;
use std::rc::Rc;
fn main() {
let my_ref = Rc::from(RefCell::from(vec![
"Hello 1".to_string(),
"Hello 2".to_string(),
]));
let my_strings: Vec<String> = *my_ref.borrow();
let count = count_strings(my_strings);
}
fn count_strings(strings: Vec<String>) -> usize {
strings.len()
}
But doing so results in a dereferencing error:
error[E0507]: cannot move out of dereference of `Ref<'_, Vec<String>>`
cannot move out of dereference of `Ref<'_, Vec<String>>`
move occurs because value has type `Vec<String>`, which does not implement the `Copy` trait
So then, how do I properly extract a Vec<String> from a Rc<RefCell<Vec<String>>>?
RefCell::borrow returns a reference, not an owned value, that's why you having such an error. I can name two different solution for that problem.
Promoting Rc to exclusively-owned type
Rc::try_unwrap is able to check, whether there's other references to the data. If it's the only one, it can be safely converted to the inner type. Then, an owned RefCell can be converted into its inner via into_inner function.
let my_ref = Rc::from(RefCell::new(vec![..]));
let inner: Vec<_> = Rc::try_unwrap(my_ref).expect("I hereby claim that my_ref is exclusively owned").into_inner();
Replacing inner value
If for some reason you want to grab inner value that is already referenced, you may consider replacing it. Note, that you need to create a appropriate value for the type (i.e. with trait Default). Here's the example:
let my_ref = Rc::from(RefCell::new(vec![..]));
let inner: Vec<_> = my_ref.borrow_mut().take();
// or
let inner: Vec<_> = my_ref.borrow_mut().replace(vec![]);

How to look up values in a HashMap<Option<String>, V> without copying?

I have a HashMap with Option<String> keys; is it possible to do lookups with a key of type Option<&str>? I know I can use a &str to lookup in a HashMap<String, V> because str implements Borrow<String>.
Do I have to convert to an owned string just to do a lookup?
It's slightly less efficient, but you could use Cow here. It avoids the problem with the Borrow trait by instead having a single type that can represent either a reference or an owned value, like so:
use std::borrow::Cow;
use std::collections::HashMap;
fn main() {
let mut map = HashMap::<Option<Cow<'static, str>>, i32>::new();
map.insert(None, 5);
map.insert(Some(Cow::Borrowed("hello")), 10);
map.insert(Some(Cow::Borrowed("world")), 15);
// works with None and constant string slices...
assert_eq!(map.get(&None), Some(&5));
assert_eq!(map.get(&Some(Cow::Borrowed("hello"))), Some(&10));
// ...and also works with heap-allocated strings, without copies
let stack = String::from("world");
assert_eq!(map.get(&Some(Cow::Borrowed(&stack))), Some(&15));
}

Taking ownership of HashMap.get() result without cloning

Is there a more efficient way of getting an owned value from a HashMap than this line?
let output_items = output_tables.get(TABLE_NAME_TLIST).unwrap().to_owned();
This screenshot expands the types:
relates to Rust - Change a reference to own value without clone
If you want to take ownership of the value, HashMap::remove() will return an Option<T> rather than the Option<&T> returned by HashMap::get(). See this playground:
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert(1, "a");
assert_eq!(map.remove(&1), Some("a"));
assert_eq!(map.remove(&1), None);
}
If you want the value to remain in the HashMap but also own the value elsewhere, you can wrap it in an Rc<T> to share ownership. If the object needs to be mutable, you can wrap it in an Rc<RefCell<T>>.

Read an arbitrary number of bytes from type implementing Read

I have something that is Read; currently it's a File. I want to read a number of bytes from it that is only known at runtime (length prefix in a binary data structure).
So I tried this:
let mut vec = Vec::with_capacity(length);
let count = file.read(vec.as_mut_slice()).unwrap();
but count is zero because vec.as_mut_slice().len() is zero as well.
[0u8;length] of course doesn't work because the size must be known at compile time.
I wanted to do
let mut vec = Vec::with_capacity(length);
let count = file.take(length).read_to_end(vec).unwrap();
but take's receiver parameter is a T and I only have &mut T (and I'm not really sure why it's needed anyway).
I guess I can replace File with BufReader and dance around with fill_buf and consume which sounds complicated enough but I still wonder: Have I overlooked something?
Like the Iterator adaptors, the IO adaptors take self by value to be as efficient as possible. Also like the Iterator adaptors, a mutable reference to a Read is also a Read.
To solve your problem, you just need Read::by_ref:
use std::io::Read;
use std::fs::File;
fn main() {
let mut file = File::open("/etc/hosts").unwrap();
let length = 5;
let mut vec = Vec::with_capacity(length);
file.by_ref().take(length as u64).read_to_end(&mut vec).unwrap();
let mut the_rest = Vec::new();
file.read_to_end(&mut the_rest).unwrap();
}
1. Fill-this-vector version
Your first solution is close to work. You identified the problem but did not try to solve it! The problem is that whatever the capacity of the vector, it is still empty (vec.len() == 0). Instead, you could actually fill it with empty elements, such as:
let mut vec = vec![0u8; length];
The following full code works:
#![feature(convert)] // needed for `as_mut_slice()` as of 2015-07-19
use std::fs::File;
use std::io::Read;
fn main() {
let mut file = File::open("/usr/share/dict/words").unwrap();
let length: usize = 100;
let mut vec = vec![0u8; length];
let count = file.read(vec.as_mut_slice()).unwrap();
println!("read {} bytes.", count);
println!("vec = {:?}", vec);
}
Of course, you still have to check whether count == length, and read more data into the buffer if that's not the case.
2. Iterator version
Your second solution is better because you won't have to check how many bytes have been read, and you won't have to re-read in case count != length. You need to use the bytes() function on the Read trait (implemented by File). This transform the file into a stream (i.e an iterator). Because errors can still happen, you don't get an Iterator<Item=u8> but an Iterator<Item=Result<u8, R::Err>>. Hence you need to deal with failures explicitly within the iterator. We're going to use unwrap() here for simplicity:
use std::fs::File;
use std::io::Read;
fn main() {
let file = File::open("/usr/share/dict/words").unwrap();
let length: usize = 100;
let vec: Vec<u8> = file
.bytes()
.take(length)
.map(|r: Result<u8, _>| r.unwrap()) // or deal explicitly with failure!
.collect();
println!("vec = {:?}", vec);
}
You can always use a bit of unsafe to create a vector of uninitialized memory. It is perfectly safe to do with primitive types:
let mut v: Vec<u8> = Vec::with_capacity(length);
unsafe { v.set_len(length); }
let count = file.read(vec.as_mut_slice()).unwrap();
This way, vec.len() will be set to its capacity, and all bytes in it will be uninitialized (likely zeros, but possibly some garbage). This way you can avoid zeroing the memory, which is pretty safe for primitive types.
Note that read() method on Read is not guaranteed to fill the whole slice. It is possible for it to return with number of bytes less than the slice length. There are several RFCs on adding methods to fill this gap, for example, this one.

Resources