I want to wrap the ReadConsoleInputW Windows console method into the Read trait so that I can use the chars() method, but I need also to know which key modifiers are applied (control, alt/meta).
One solution (like the one used by the Unix console) is to encode key events into control characters or ANSI escape codes.
Another solution would be to keep the key modifiers around but I can't make it work because the chars() method consume/move the input:
struct InputBuffer {
handle: winapi::HANDLE,
ctrl: bool,
meta: bool,
}
impl Read for InputBuffer {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut rec: winapi::INPUT_RECORD = unsafe { mem::zeroed() };
// kernel32::ReadConsoleInputW(self.0, &mut rec, 1 as winapi::DWORD, &mut count);
// ...
if rec.EventType != winapi::KEY_EVENT {
continue;
}
let key_event = unsafe { rec.KeyEvent() };
// ...
self.ctrl = key_event.dwControlKeyState &
(winapi::LEFT_CTRL_PRESSED | winapi::RIGHT_CTRL_PRESSED) ==
(winapi::LEFT_CTRL_PRESSED | winapi::RIGHT_CTRL_PRESSED);
self.meta = ...;
let utf16 = key_event.UnicodeChar;
// ...
let (bytes, len) = try!(InputBuffer::wide_char_to_multi_byte(utf16));
return (&bytes[..len]).read(buf);
}
}
fn main() {
let handle = try!(get_std_handle(STDIN_FILENO));
let mut stdin = InputBuffer(handle);
let mut chars = stdin.chars(); // stdin moved here
loop {
let c = chars.next().unwrap();
let mut ch = try!(c);
if stdin.ctrl { // use of moved value
//...
}
// ...
}
}
How to do this in Rust?
You could put these flags into Rc<RefCell<somestruct>> and clone it before consuming stdin.
This is a common pattern that allows you to have "access" to the same data, from two places. Rc takes care of shared ownership, and RefCell checks if you don't have overlapping accesses.
Related
I've been working to try to optimize a section of my code and I've hit an area where I think I could use some community wisdom. I'm essentially trying to merge two elements of a list without moving the elements in the list (via two removes and an insert), because as far as I can tell in Rust doing so to a vector costs O(n) time.
Take a glance at the code that captures the essence of my problem:
use std::cell::RefCell;
use std::rc::Rc;
use std::collections::BinaryHeap;
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Num {
pub num: usize
}
impl Num {
pub fn new(num: usize) -> Num {
Num {
num
}
}
}
fn main() {
let mut a = vec![];
for i in 0..10 {
a.push(Rc::new(RefCell::new(Num::new(i))));
}
let mut b = BinaryHeap::with_capacity(a.len());
for i in 0..a.len() - 1 {
b.push((i, Rc::clone(&a[i]), Rc::clone(&a[i + 1])));
}
drop(a);
while !b.is_empty() {
let c = b.pop().unwrap();
let first = c.1;
let next = c.2;
println!("c: c.0: {}", c.0);
println!("c: first.num before: {}", RefCell::borrow(&first).num);
println!("c: next.num before: {}", RefCell::borrow(&next).num);
// Here I want to replace the two structs referenced in first and next
// with a single new struct that first and next both point to.
// e.g. first -> new_num <- next
println!("c: first.num after: {}", RefCell::borrow(&first).num);
println!("c: next.num after: {}", RefCell::borrow(&next).num);
assert_eq!(RefCell::borrow(&first).num, RefCell::borrow(&next).num);
}
}
I want to be able to take two elements within a list, merge them into one pseudo-element, where the two previous "elements" are actually just pointers to the same new element. However, I'm having trouble finding a way to do this without copying memory or structures around in the list.
My understanding of your requirement is that you need the Vec to be able to hold items that are either a value or a reference to another item, while keeping the structure similar to what you have presented.
We can model that by changing your item type to an enum, which can hold either a value or a reference to another item:
pub enum Num {
Raw(usize),
Ref(Rc<RefCell<Num>>),
}
And add methods to include abstractions for constructing the different variants and for accessing the underlying numeric value:
impl Num {
pub fn new(num: usize) -> Num {
Num::Raw(num)
}
pub fn new_ref(other: Rc<RefCell<Num>>) -> Num {
Num::Ref(other)
}
pub fn get_num(&self) -> usize {
match &self {
Num::Raw(n) => *n,
Num::Ref(r) => r.borrow().get_num()
}
}
}
If you create a new value like this:
let new_num = Rc::new(RefCell::new(Num::new(100)));
You can reference it in other nodes like this:
*first.borrow_mut() = Num::new_ref(Rc::clone(&new_num));
*next.borrow_mut() = Num::new_ref(Rc::clone(&new_num));
The full code then looks like this:
use std::cell::RefCell;
use std::rc::Rc;
use std::collections::BinaryHeap;
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub enum Num {
Raw(usize),
Ref(Rc<RefCell<Num>>),
}
impl Num {
pub fn new(num: usize) -> Num {
Num::Raw(num)
}
pub fn new_ref(other: Rc<RefCell<Num>>) -> Num {
Num::Ref(other)
}
pub fn get_num(&self) -> usize {
match &self {
Num::Raw(n) => *n,
Num::Ref(r) => r.borrow().get_num()
}
}
}
fn main() {
let mut a = vec![];
for i in 0..10 {
a.push(Rc::new(RefCell::new(Num::new(i))));
}
let mut b = BinaryHeap::with_capacity(a.len());
for i in 0..a.len() - 1 {
b.push((i, Rc::clone(&a[i]), Rc::clone(&a[i + 1])));
}
drop(a);
let new_num = Rc::new(RefCell::new(Num::new(100)));
while !b.is_empty() {
let c = b.pop().unwrap();
let first = c.1;
let next = c.2;
println!("c: c.0: {}", c.0);
println!("c: first.num before: {}", RefCell::borrow(&first).get_num());
println!("c: next.num before: {}", RefCell::borrow(&next).get_num());
*first.borrow_mut() = Num::new_ref(Rc::clone(&new_num))
*next.borrow_mut() = Num::new_ref(Rc::clone(&new_num))
println!("c: first.num after: {}", RefCell::borrow(&first).get_num());
println!("c: next.num after: {}", RefCell::borrow(&next).get_num());
assert_eq!(RefCell::borrow(&first).get_num(), RefCell::borrow(&next).get_num());
}
}
As for whether this will prove to be better performance than a different approach, it's hard to say. Your starting point seems quite complicated, and if you can simplify that and use a different underlying data structure, then you should try it and benchmark. I have often been surprised at the actual speed of O(n) operations on a Vec, even when the size is around 1000 items or more.
I would like to have a struct which has a writable field, but explicitly borrowable:
struct App<W: Clone<BorrowMut<Write>>> {
stdout: W,
}
... so it can internally use it:
impl<W: Clone<BorrowMut<Write>>> App<W> {
fn hello(&mut self) -> Result<()> {
Rc::clone(&self.stdout).borrow_mut().write(b"world\n")?;
Ok(())
}
}
I tried to pass it a cursor and then use it:
let mut cursor = Rc::new(RefCell::new(Cursor::new(vec![0])));
let mut app = App { stdout: cursor };
app.hello().expect("failed to write");
let mut line = String::new();
Rc::clone(&cursor).borrow_mut().read_line(&mut line).unwrap();
Rust barks:
error[E0107]: wrong number of type arguments: expected 0, found 1
--> src/bin/play.rs:6:21
|
6 | struct App<W: Clone<BorrowMut<Write>>> {
| ^^^^^^^^^^^^^^^^ unexpected type argument
My end goal: pass stdin, stdout and stderr to an App struct. In fn main, these would be real stdin/stdout/stderr. In tests, these could be cursors. Since I need to access these outside of App (e.g. in tests), I need multiple owners (thus Rc) and runtime mutable borrow (thus RefCount).
How can I implement this?
This isn't how you apply multiple constraints to a type parameter. Instead you use the + operator, like this: <W: Clone + Write + BorrowMut>
But, if you want BorrowMut to be an abstraction for RefCell, it won't work. The borrow_mut method of RefCell is not part of any trait so you will need to depend on RefCell directly in your data structure:
struct App<W: Clone + Write> {
stdout: Rc<RefCell<W>>,
}
Having said that, it's considered best practice not to put unneeded constraints on a struct. You can actually leave them off here, and just mention them on the impl later.
struct App<W> {
stdout: Rc<RefCell<W>>,
}
In order to access the contents of a Rc, you need to dereference with *. This can be a bit tricky in your case because there is a blanket impl of BorrowMut, which means that Rc has a different borrow_mut, which you definitely don't want.
impl<W: Clone + Write> App<W> {
fn hello(&mut self) -> Result<()> {
(*self.stdout).borrow_mut().write(b"world\n")?;
Ok(())
}
}
Again, when you use this, you'll need to dereference the Rc:
let cursor = Rc::new(RefCell::new(Cursor::new(vec![0])));
let mut app = App { stdout: cursor.clone() };
app.hello().expect("failed to write");
let mut line = String::new();
let mut cursor = (&*cursor).borrow_mut();
// move to the beginning or else there's nothing to read
cursor.set_position(0);
cursor.read_line(&mut line).unwrap();
println!("result = {:?}", line);
Also, notice that the Rc was cloned into the cursor. Otherwise it would be moved and you couldn't use it again later.
The below code won't compile because the compiler thinks I shouldn't assign to t1 since it is borrowed, but in reality the function always_returns_no_lifetime will always be returning a variant of the enum that actually doesn't have an lifetime, so it is okay for me to modify t1. How can I get the compiler to understand this or how should I reorganize my code to make this error not happen?
#[derive(Clone)]
enum Types<'a> {
NoLifetime(i32),
AlsoNoLifetime(i32),
AlsoAlsoNoLifetime(i32),
HasLifetime(&'a str)
}
fn always_returns_no_lifetime<'a>(some_type: &'a Types) -> Types<'a> {
match *some_type {
Types::HasLifetime(text) => panic!("I only return the type that has no lifetime"),
_ => some_type.clone()
}
}
fn main() {
let mut t1 = Types::NoLifetime(20);
let copy = always_returns_no_lifetime(&t1);
t1 = Types::NoLifetime(30);
}
playground
The error is:
error[E0506]: cannot assign to `t1` because it is borrowed
--> src/main.rs:23:5
|
21 | let copy = always_returns_no_lifetime(&t1);
| -- borrow of `t1` occurs here
22 |
23 | t1 = Types::NoLifetime(30);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `t1` occurs here
The return type of your function is wrong. If the return value is guaranteed not to have any lifetime, then it should be marked as such, and not tied down to an arbitrary lifetime:
fn always_returns_no_lifetime(...) -> Types<'static>;
With this change, you actually no longer need any input lifetime either, since they are only useful to tie the input and output, leading the following signature:
fn always_returns_no_lifetime(some_type: &Types) -> Types<'static>;
Unfortunately, this means that clone is now out of the table, as it clones the lifetime, so the implementation has to change too:
fn always_returns_no_lifetime(some_type: &Types) -> Types<'static> {
match *some_type {
Types::HasLifetime(_)
=> panic!("I only return values that have no lifetime"),
Types::NoLifetime(i) => Types::NoLifetime(i),
Types::AlsoNoLifetime(i) => Types::AlsoNoLifetime(i),
Types::AlsoAlsoNoLifetime(i) => Types::AlsoAlsoNoLifetime(i),
}
}
The benefit of this implementation can be demonstrated in the following example:
fn tie<'a>(text: &'a str) -> Types<'a> {
if text[0] == 'a' {
Types::HasLifetime(text)
} else {
Types::NoLifetime(0)
}
}
fn main() {
let no_lifetime = {
let string = String::from("Hello, world");
let has_lifetime = tie(&*string);
always_returns_no_lifetime(&has_lifetime)
};
// Requires deriving Debug, all structs really should...
println!("{:?}", no_lifetime);
}
If you preserve the lifetime when you don't need it, you cannot compile this example, it's an unnecessary restriction.
Instead of applying the 'a lifetime parameter on the reference, apply it on Types, as you already did with the return type. The lifetime on the reference is not important when you call .clone() on it.
fn always_returns_no_lifetime<'a>(some_type: &Types<'a>) -> Types<'a> {
match *some_type {
Types::HasLifetime(text) => panic!("I only return the type that has no lifetime"),
_ => some_type.clone()
}
}
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.
Why does the call self.f2() in the following code trip the borrow checker? Isn't the else block in a different scope? This is quite a conundrum!
use std::str::Chars;
struct A;
impl A {
fn f2(&mut self) {}
fn f1(&mut self) -> Option<Chars> {
None
}
fn f3(&mut self) {
if let Some(x) = self.f1() {
} else {
self.f2()
}
}
}
fn main() {
let mut a = A;
}
Playground
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:16:13
|
13 | if let Some(x) = self.f1() {
| ---- first mutable borrow occurs here
...
16 | self.f2()
| ^^^^ second mutable borrow occurs here
17 | }
| - first borrow ends here
Doesn't the scope of the borrow for self begin and end with the self.f1() call? Once the call from f1() has returned f1() is not using self anymore hence the borrow checker should not have any problem with the second borrow. Note the following code fails too...
// ...
if let Some(x) = self.f1() {
self.f2()
}
// ...
Playground
I think the second borrow should be fine here since f1 and f3 are not using self at the same time as f2.
I put together an example to show off the scoping rules here:
struct Foo {
a: i32,
}
impl Drop for Foo {
fn drop(&mut self) {
println!("Foo: {}", self.a);
}
}
fn generate_temporary(a: i32) -> Option<Foo> {
if a != 0 { Some(Foo { a: a }) } else { None }
}
fn main() {
{
println!("-- 0");
if let Some(foo) = generate_temporary(0) {
println!("Some Foo {}", foo.a);
} else {
println!("None");
}
println!("-- 1");
}
{
println!("-- 0");
if let Some(foo) = generate_temporary(1) {
println!("Some Foo {}", foo.a);
} else {
println!("None");
}
println!("-- 1");
}
{
println!("-- 0");
if let Some(Foo { a: 1 }) = generate_temporary(1) {
println!("Some Foo {}", 1);
} else {
println!("None");
}
println!("-- 1");
}
{
println!("-- 0");
if let Some(Foo { a: 2 }) = generate_temporary(1) {
println!("Some Foo {}", 1);
} else {
println!("None");
}
println!("-- 1");
}
}
This prints:
-- 0
None
-- 1
-- 0
Some Foo 1
Foo: 1
-- 1
-- 0
Some Foo 1
Foo: 1
-- 1
-- 0
None
Foo: 1
-- 1
In short, it seems that the expression in the if clause lives through both the if block and the else block.
On the one hand it is not surprising since it is indeed required to live longer than the if block, but on the other hand it does indeed prevent useful patterns.
If you prefer a visual explanation:
if let pattern = foo() {
if-block
} else {
else-block
}
desugars into:
{
let x = foo();
match x {
pattern => { if-block }
_ => { else-block }
}
}
while you would prefer that it desugars into:
bool bypass = true;
{
let x = foo();
match x {
pattern => { if-block }
_ => { bypass = false; }
}
}
if not bypass {
else-block
}
You are not the first one being tripped by this, so this may be addressed at some point, despite changing the meaning of some code (guards, in particular).
It's annoying, but you can work around this by introducing an inner scope and changing the control flow a bit:
fn f3(&mut self) {
{
if let Some(x) = self.f1() {
// ...
return;
}
}
self.f2()
}
As pointed out in the comments, this works without the extra braces. This is because an if or if...let expression has an implicit scope, and the borrow lasts for this scope:
fn f3(&mut self) {
if let Some(x) = self.f1() {
// ...
return;
}
self.f2()
}
Here's a log of an IRC chat between Sandeep Datta and mbrubeck:
mbrubeck: std:tr::Chars contains a borrowed reference to the string that created it. The full type name is Chars<'a>. So f1(&mut self) -> Option<Chars> without elision is f1(&'a mut self) -> Option<Chars<'a>> which means that self remains borrowed as long as
the return value from f1 is in scope.
Sandeep Datta: Can I use 'b for self and 'a for Chars to avoid this problem?
mbrubeck: Not if you are actually returning an iterator over something from self. Though if you can make a function from &self -> Chars (instead of &mut self -> Chars) that would fix the issue.
As of Rust 2018, available in Rust 1.31, the original code will work as-is. This is because Rust 2018 enables non-lexical lifetimes.
A mutable reference is a very strong guarantee: that there's only one pointer to a particular memory location. Since you've already had one &mut borrow, you can't also have a second. That would introduce a data race in a multithreaded context, and iterator invalidation and other similar issues in a single-threaded context.
Right now, borrows are based on lexical scope, and so the first borrow lasts until the end of the function, period. Eventually, we hope to relax this restriction, but it will take some work.
Here is how you can get rid of the spurious errors. I am new to Rust so there may be serious errors in the following explanation.
use std::str::Chars;
struct A<'a> {
chars: Chars<'a>,
}
The 'a here is a lifetime parameter (just like template parameters in C++). Types can be parameterised by lifetimes in Rust.
The Chars type also takes a lifetime parameter. What this implies is that the Chars type probably has a member element which needs a lifetime parameter. Lifetime parameters only make sense on references (since lifetime here actually means "lifetime of a borrow").
We know that Chars needs to keep a reference to the string from which it was created, 'a will probably be used to denote the source string's lifetime.
Here we simply supply 'a as the lifetime parameter to Chars telling the Rust compiler that the lifetime of Chars is the same as the lifetime of the struct A. IMO "lifetime 'a of type A" should be read as "lifetime 'a of the references contained in the struct A".
I think the struct implementation can be parameterised independently from the struct itself hence we need to repeat the parameters with the impl keyword. Here we bind the name 'a to the lifetime of the struct A.
impl<'a> A<'a> {
The name 'b is introduced in the context of the function f2. Here it is used to bind with the lifetime of the reference &mut self.
fn f2<'b>(&'b mut self) {}
The name 'b is introduced in the context of the function f1.This 'b does not have a direct relationship with the 'b introduced by f2 above.
Here it is used to bind with the lifetime of the reference &mut self. Needless to say this reference also does not have any relationship with the &mut self in the previous function, this is a new independent borrow of self.
Had we not used explicit lifetime annotation here Rust would have used its lifetime elision rules to arrive at the following function signature...
//fn f1<'a>(&'a mut self) -> Option<Chars<'a>>
As you can see this binds the lifetime of the reference &mut self parameter to the lifetime of the Chars object being returned from this function (this Chars object need not be the same as self.chars) this is absurd since the returned Chars will outlive the &mut self reference. Hence we need to separate the two lifetimes as follows...
fn f1<'b>(&'b mut self) -> Option<Chars<'a>> {
self.chars.next();
Remember &mut self is a borrow of self and anything referred to by &mut self is also a borrow. Hence we cannot return Some(self.chars) here. self.chars is not ours to give (Error: cannot move out of borrowed content.).
We need to create a clone of self.chars so that it can be given out.
Some(self.chars.clone())
Note here the returned Chars has the same lifetime as the struct A.
And now here is f3 unchanged and without compilation errors!
fn f3<'b>(&'b mut self) {
if let Some(x) = self.f1() { //This is ok now
} else {
self.f2() //This is also ok now
}
}
The main function just for completeness...
fn main() {
let mut a = A { chars:"abc".chars() };
a.f3();
for c in a.chars {
print!("{}", c);
}
}
I have updated the code the make the lifetime relationships clearer.