I'm having trouble with this code. I have no idea why it errors.
It's supposed to take camera input and then put that inside of a buffer struct, contained inside the putter struct.
extern crate rscam;
// use std::fs::File;
// use std::io::prelude::*;
const WIDTH: usize = 1280;
const HEIGHT: usize = 720;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Pyxel {
r: u8,
g: u8,
b: u8,
}
impl Pyxel {
fn new() -> Pyxel {
Pyxel { r: 0, g: 0, b: 0 }
}
}
#[repr(transparent)]
struct Buffer {
pyxels: [[Pyxel; WIDTH]; HEIGHT],
}
// impl Buffer {
// fn new(s: [[Pyxel; WIDTH]; HEIGHT]) -> Buffer {
// Buffer {
// pyxels: s,
// }
// }
// }
struct Putter {
x: usize,
y: usize,
buffer: &'static mut Buffer,
}
impl Putter {
fn put_pyxel(&mut self, r: u8, g: u8, b: u8) {
if self.x >= WIDTH {
self.move_down();
}
let col = self.x;
let row = self.y;
self.buffer.pyxels[row][col] = Pyxel { r: r, g: g, b: b };
self.x += 1;
}
fn move_down(&mut self) {
self.y += 1;
}
fn new() -> Putter {
Putter {
x: 0,
y: 0,
buffer: &mut Buffer {
pyxels: [[Pyxel::new(); WIDTH]; HEIGHT],
},
}
}
}
fn main() {
let mut camera = rscam::new("/dev/video0").unwrap();
camera
.start(&rscam::Config {
interval: (1, 30),
resolution: (1280, 720),
format: b"RGB3",
..Default::default()
})
.unwrap();
let frame = camera.capture().unwrap();
let mut putter = Putter::new();
}
It errors:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:65:20
|
57 | buffer: &mut Buffer {
| __________________________^
58 | | pyxels: [[Pyxel::new(); WIDTH]; HEIGHT],
59 | | },
| |_____________^ temporary value does not live long enough
60 | }
61 | }
| - temporary value only lives until here
|
= note: borrowed value must be valid for the static lifetime..
How do I use the buffer inside of the putter (structs)?
For the most part, I understand what this errors means, not how it works. I just need a workaround or a solution. Any help is appreciated. I could have written this better but im tired.
This is more or less logical error for me. You should carefully read about Rust ownership.
Consider thinking about how would your code work.
struct Putter {
x: usize,
y: usize,
buffer: &'static mut Buffer,
}
Buffer is a reference which you have lifetime equal to the lifetime of the program,
'static tells compiler that. Error message is pretty clear, you're creating temporary value in place and borrowing it. It will be destroyed right after exiting scope, so your reference will be pointing to invalid memory. Dangling references are prohibited in Rust. In language like C++ this example will compile fine, but will result in run-time error.
To fix this issue buffer should own value and struct design should be rethought while keeping attention to lifetimes.
struct Putter {
x: usize,
y: usize,
buffer: Buffer,
}
Related
I can't understand how to write trait for generating Point in some range.
I try to use rand::Rng for generate random values for Point struct (for coordinates in minesweeper).
I use this site Generate Random Values - Rust Cookbook
And it fine worked for ranges for simple data types. Also, worked examples with Point.
Could someone provide example of code and some explanation about traits for Uniform for Point struct?
use rand::Rng;
use rand::distributions::{Distribution, Uniform};
fn main() {
let width: u8 = 15; let height: u8 = 15;
let mine_count: u8 = 40;
let mut rng = rand::thread_rng();
let ranger = Uniform::from(0..width);
for _i in 0..=mine_count{
let rand_point: Point = ranger.sample(&mut rng);
println!("Random Point: {:?}", rand_point);
}
}
#[derive(Debug)]
struct Point {
x: u8,
y: u8,
}
impl Distribution<Point> for Uniform<Point> {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
let (rand_x, rand_y) = rng.gen();
Point {
x: rand_x,
y: rand_y,
}
}
}
Compiling my-project v0.1.0 (/home/runner/SyntaxTest)
error[E0277]: the trait bound `Point: SampleUniform` is not satisfied
--> src/main.rs:56:30
|
56 | impl Distribution<Point> for Uniform<Point> {
| ^^^^^^^^^^^^^^ the trait `SampleUniform` is not implemented for `Point`
note: required by a bound in `Uniform`
--> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.8.5/src/distributions/uniform.rs:179:23
|
179 | pub struct Uniform<X: SampleUniform>(X::Sampler);
| ^^^^^^^^^^^^^ required by this bound in `Uniform`
error[E0277]: the trait bound `Point: SampleUniform` is not satisfied
--> src/main.rs:57:30
|
57 | fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
| ^^^^^ the trait `SampleUniform` is not implemented for `Point`
note: required by a bound in `Uniform`
--> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.8.5/src/distributions/uniform.rs:179:23
|
179 | pub struct Uniform<X: SampleUniform>(X::Sampler);
| ^^^^^^^^^^^^^ required by this bound in `Uniform`
The problem here is that your code has no concept of what is a distribution of Points.
If you look at the signature of the Uniform struct, its generic has to implement the SampleUniform trait. According to the docs, the SampleUniform trait defines the Sampler type that should be used in order to generate random distributions.
So, when you write this:
impl Distribution<Point> for Uniform<Point> {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
let (rand_x, rand_y) = rng.gen();
Point {
x: rand_x,
y: rand_y,
}
}
}
When you call Uniform::from(0..width), you are also defining a sampler for u8 values, which is not what you want in the end. What you want (judging by your code) is to generate a random distribution of points between a min, say Point { x: 0, y: 0 }, and a maximum value, which could be another point, but it could also be defined as a range, a delta, an area, etc. The idea is to be able to write something like this:
let ranger = Uniform::from(
Point::default()..Point {
x: width,
y: height,
},
);
Where Point::default() is the origin.
To solve your problem you need to be able to tell the rand crate what exactlyis it that you mean when you ask for that distribution of Points.
To keep your code as is, you could rewrite it like this:
use rand::distributions::uniform::{SampleUniform, UniformInt, UniformSampler};
use rand::distributions::{Distribution, Uniform};
use rand::Rng;
fn main() {
let width: u8 = 4;
let height: u8 = 5;
let mine_count: u8 = 40;
let mut rng = rand::thread_rng();
let ranger = Uniform::from(
Point::default()..Point {
x: width,
y: height,
},
);
for _i in 0..=mine_count {
let rand_point: Point = ranger.sample(&mut rng);
println!("Random Point: {:?}", rand_point);
}
}
#[derive(Clone, Copy, Debug, Default)]
struct Point {
x: u8,
y: u8,
}
struct UniformPoint {
x: UniformInt<u8>,
y: UniformInt<u8>,
}
impl SampleUniform for Point {
type Sampler = UniformPoint;
}
impl UniformSampler for UniformPoint {
type X = Point;
fn new<B1, B2>(low: B1, high: B2) -> Self
where
B1: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
B2: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
{
let low = *low.borrow();
let high = *high.borrow();
UniformPoint {
x: UniformInt::<u8>::new_inclusive(low.x, high.x - 1),
y: UniformInt::<u8>::new_inclusive(low.y, high.y - 1),
}
}
fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
where
B1: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
B2: rand::distributions::uniform::SampleBorrow<Self::X> + Sized,
{
let low = *low.borrow();
let high = *high.borrow();
UniformPoint {
x: UniformInt::<u8>::new_inclusive(low.x, high.x),
y: UniformInt::<u8>::new_inclusive(low.y, high.y),
}
}
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
Point {
x: self.x.sample(rng),
y: self.y.sample(rng),
}
}
}
impl Distribution<Point> for Point {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
let (rand_x, rand_y) = rng.gen();
Point {
x: rand_x,
y: rand_y,
}
}
}
Notice that you don't need to implement the Distribution trait any longer, since Uniform::from only requires that your struct implements SampleUniform.
The trick here is that each field in Point needs to be generated from a distribution of values. Since you can use UniformInt::<u8>... to generate those distributions, then all you need is an accessory struct that can as a placeholders for those distributions.
Notice that now, when you call ranger.sample() you're actually making two calls. One to x.sample and one to y.sample.
This results in a neat API, where you can still use the ranger as you did before without any modifications.
Another solution would be to keep your u8 distribution and create your random points by doing:
for _i in 0..=mine_count {
let rand_point = Point {
x: ranger.sample(&mut rng),
y: ranger.sample(&mut rng),
}
println!("Random Point: {:?}", rand_point);
}
This way you don't need to implement anything, but it is also less fun.
Hope this helps.
You want to implement Distribution<Point> for Uniform<u8>, not Uniform<Point>:
use rand::Rng;
use rand::distributions::{Distribution, Uniform};
fn main() {
let width: u8 = 15; let height: u8 = 15;
let mine_count: u8 = 40;
let mut rng = rand::thread_rng();
let ranger = Uniform::from(0..width);
for _i in 0..=mine_count{
let rand_point: Point = ranger.sample(&mut rng);
println!("Random Point: {:?}", rand_point);
}
}
#[derive(Debug)]
struct Point {
x: u8,
y: u8,
}
impl Distribution<Point> for Uniform<u8> {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Point {
let (rand_x, rand_y) = rng.gen();
Point {
x: rand_x,
y: rand_y,
}
}
}
Playground
I'm making a maze algorithm using rust and wasm and I have two structs. A maze, and maze has an Vec of a Block struct.
Like this:
pub struct Maze {
pub cols: usize,
pub rows: usize,
pub blocks: Vec<Block>,
pub stack: Vec<usize>,
}
impl Maze {
pub fn new(cols: usize, rows: usize) -> Maze {
let mut maze = Maze {
cols,
rows,
blocks: vec![],
};
for y in 0..rows {
for x in 0..cols {
maze.blocks.push(Block::new(x, y))
}
}
maze
}
And the struct Block has an attribute called visited.
I want in a struct function of Maze change this value
// in Maze struct impl
pub fn run(&mut self) {
let current_index = self.get_current_index();
let mut current_block = &mut &self.blocks[current_index];
// .....
*current_block.visited = true;
In the last line occur an error:
error[E0614]: type `bool` cannot be dereferenced
--> src/maze.rs:119:17
|
119 | *current_block.visited = true;
| ^^^^^^^^^^^^^^^^^^^^^^
How can I do to change this value?
This is my implementation of Block
pub struct Block {
pub x: usize,
pub y: usize,
pub visited: bool,
}
impl Block {
pub fn new(x: usize, y: usize) -> Block {
Block {
x,
y,
visited: false,
}
}
How can I do to change the visited value from Maze.run?
There are two problems, one which is the error you see and one which you will encounter next. The problem with
*current_block.visited = true;
is that the precedence of * is lower than ., so you've written code equivalent to)
*(current_block.visited) = true;
which does not compile because the type of the visited field is bool, which indeed cannot be dereferenced. You could write
(*current_block).visited = true;
and that would work, but it's also unnecessary, because in Rust the . operator looks through references, so you only need
current_block.visited = true;
to assign to the visited field of an &mut Block.
The second problem is that you have an extra & here:
let mut current_block = &mut &self.blocks[current_index];
This means current_block is of type &mut &Block. You can never mutate through an & reference, so you need to remove the &, and it is not needed anyway:
let mut current_block = &mut self.blocks[current_index];
Hi I have the following this tutorial for learning more in depth what can I do with rust so I'm aware that this might now be the proper way to do thing. Here is the repository which contains all the code to take a in depth look. I'm having a global vga writer instance which needs to be safe for data races so using lazy_static I initialize it. What I want to do is is to be able to aquire the lock only when I actually print the string so that I implement fmt::Write on the WrappedWriter instead of the Writer to not obtain the lock over the spin::Mutex when I want to print a string rather I want to obtain the lock after the params were formatted . But when I call this the write function:
crate::vga_buffer::WRITER.write_fmt(args).unwrap();
I get the following error:
Compiling rust_os v0.1.0 (D:\Workspace\Organiztions\home\rust\rust_os)
error[E0055]: reached the recursion limit while auto-dereferencing `vga_buffer::writer::WrappedWriter`
--> src\lib.rs:19:31
|
19 | crate::vga_buffer::WRITER.write_fmt(args).unwrap();
| ^^^^^^^^^ deref recursion limit reached
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`rust_os`)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0055`.
error: could not compile `rust_os`.
Here is the implementation of the Writer + WrappedWriter
use core::fmt;
use lazy_static::lazy_static;
use volatile::Volatile;
use super::color::*;
use super::screen_character;
use core::ops::{DerefMut, Deref};
// #[allow(dead_code)]
// use crate::serial_print;
// use crate::serial_println;
pub const BUFFER_HEIGHT: usize = 25;
pub const BUFFER_WIDTH: usize = 80;
#[repr(transparent)]
struct Buffer {
chars: [[Volatile<screen_character::ScreenCharacter>; BUFFER_WIDTH]; BUFFER_HEIGHT],
}
pub struct Writer {
column_position: usize,
color_code: ColorCode,
buffer: &'static mut Buffer,
}
impl Writer {
pub fn new(column_position: usize,
color_code: ColorCode) -> Writer {
return Writer {
column_position,
color_code,
buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
};
}
}
impl Writer {
pub fn write_byte(&mut self, byte: u8) {
match byte {
b'\n' => self.new_line(),
byte => {
if self.column_position >= BUFFER_WIDTH {
self.new_line();
}
let row = BUFFER_HEIGHT - 1;
let col = self.column_position;
let color_code = self.color_code;
self.buffer.chars[row][col].write(screen_character::ScreenCharacter::new(byte, color_code));
self.column_position += 1;
}
}
}
pub fn write_string(&mut self, s: &str) {
for byte in s.bytes() {
match byte {
// printable ASCII byte or newline
0x20..=0x7e | b'\n' => self.write_byte(byte),
// not part of printable ASCII range
_ => self.write_byte(0xfe),
}
}
}
fn new_line(&mut self) {
for row in 1..BUFFER_HEIGHT {
for col in 0..BUFFER_WIDTH {
let current_character = self.buffer.chars[row][col].read();
self.buffer.chars[row - 1][col].write(current_character);
}
}
self.clear_row(BUFFER_HEIGHT - 1);
self.column_position = 0;
}
fn clear_row(&mut self, row_index: usize) {
let blank = screen_character::ScreenCharacter::new(b' ', self.color_code);
for col in 0..BUFFER_WIDTH {
self.buffer.chars[row_index][col].write(blank);
}
}
}
// impl fmt::Write for Writer {
// fn write_str(&mut self, s: &str) -> fmt::Result {
// self.write_string(s);
// Ok(())
// }
// }
struct WrappedWriter {
value: spin::Mutex<Writer>
}
impl fmt::Write for WrappedWriter {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.value.lock().write_string(s);
Ok(())
}
}
impl Deref for WrappedWriter {
type Target = WrappedWriter;
fn deref(&self) -> &Self::Target {
return self;
}
}
impl DerefMut for WrappedWriter {
fn deref_mut(&mut self) -> &mut Self::Target {
return self;
}
}
lazy_static! {
pub static ref WRITER: WrappedWriter = {
let writerInstance = WrappedWriter {
value: spin::Mutex::new(
Writer::new(0, ColorCode::new(Color::Yellow, Color::Black))
)
};
writerInstance
};
}
#[test_case]
fn test_println_output() {
let test_str = "Some test string that fits on a single line";
println!("{}", test_str);
for (char_index, char) in test_str.chars().enumerate() {
let screen_char = WRITER.value.lock().buffer.chars[BUFFER_HEIGHT - 2][char_index].read();
assert_eq!(char::from(screen_char.ascii_character), char);
}
}
Deref + DerefMut Were implemented because I get the following error without them but then again I didn't knew on what should I deref cause I don't actually need to deref from my point of view this are needed because write_fmt gets a mut of self
error[E0596]: cannot borrow data in a dereference of `vga_buffer::writer::WRITER` as mutable
--> src\lib.rs:19:5
|
19 | crate::vga_buffer::WRITER.write_fmt(args).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `vga_buffer::writer::WRITER`
WrappedWriter currently derefs to itself, which derefs to itself, which derefs to itself, and so on, which is why you reach the recursion limit. You probably want to make it deref to the Writer inside by obtaining a lock.
I have some object that I want to split into two parts via a mutable borrow, then combine those back together into the original object when the split references go out of scope.
The simplified example below is for a Count struct that holds a single i32, which we want to split into two &mut i32s, who are both incorporated back into the original Count when the two mutable references go out of scope.
The approach I am taking below is to use an intermediate object CountSplit which holds a mutable reference to the original Count object and has the Drop trait implemented to do the re-combination logic.
This approach feels kludgy. In particular, this is awkward:
let mut ms = c.make_split();
let (x, y) = ms.split();
Doing this in one line like let (x, y) = c.make_split().split(); is not allowed because the intermediate object must have a longer lifetime. Ideally I would be able to do something like let (x, y) = c.magic_split(); and avoid exposing the intermediate object altogether.
Is there a way to do this which doesn't require doing two let's every time, or some other way to tackle this pattern that would be more idiomatic?
#[derive(Debug)]
struct Count {
val: i32,
}
trait MakeSplit<'a> {
type S: Split<'a>;
fn make_split(&'a mut self) -> Self::S;
}
impl<'a> MakeSplit<'a> for Count {
type S = CountSplit<'a>;
fn make_split(&mut self) -> CountSplit {
CountSplit {
top: self,
second: 0,
}
}
}
struct CountSplit<'a> {
top: &'a mut Count,
second: i32,
}
trait Split<'a> {
fn split(&'a mut self) -> (&'a mut i32, &'a mut i32);
}
impl<'a, 'b> Split<'a> for CountSplit<'b> {
fn split(&mut self) -> (&mut i32, &mut i32) {
(&mut self.top.val, &mut self.second)
}
}
impl<'a> Drop for CountSplit<'a> {
fn drop(&mut self) {
println!("custom drop occurs here");
self.top.val += self.second;
}
}
fn main() {
let mut c = Count { val: 2 };
println!("{:?}", c); // Count { val: 2 }
{
let mut ms = c.make_split();
let (x, y) = ms.split();
println!("split: {} {}", x, y); // split: 2 0
// each of these lines correctly gives a compile-time error
// c.make_split(); // can't borrow c as mutable
// println!("{:?}", c); // or immutable
// ms.split(); // also can't borrow ms
*x += 100;
*y += 5000;
println!("split: {} {}", x, y); // split: 102 5000
} // custom drop occurs here
println!("{:?}", c); // Count { val: 5102 }
}
playground:
I don't think a reference to a temporary value like yours can be made to work in today's Rust.
If it's any help, if you specifically want to call a function with two &mut i32 parameters like you mentioned in the comments, e.g.
fn foo(a: &mut i32, b: &mut i32) {
*a += 1;
*b += 2;
println!("split: {} {}", a, b);
}
you can already do that with the same number of lines as you'd have if your chaining worked.
With the chaining, you'd call
let (x, y) = c.make_split().split();
foo(x, y);
And if you just leave out the conversion to a tuple, it looks like this:
let mut ms = c.make_split();
foo(&mut ms.top.val, &mut ms.second);
You can make it a little prettier by e.g. storing the mutable reference to val directly in CountSplit as first, so that it becomes foo(&mut ms.first, &mut ms.second);. If you want it to feel even more like a tuple, I think you can use DerefMut to be able to write foo(&mut ms.0, &mut ms.1);.
Alternatively, you can of course formulate this as a function taking a function
impl Count {
fn as_split<F: FnMut(&mut i32, &mut i32)>(&mut self, mut f: F) {
let mut second = 0;
f(&mut self.val, &mut second);
self.val += second;
}
}
and then just call
c.as_split(foo);
Dereferencing a boxed struct and moving its field causes it to be moved, but doing it in another way works just fine. I don't understand the difference between these two pop functions. How does one fail when the other one doesn't?
pub struct Stack<T> {
head: Option<Box<Node<T>>>,
len: usize,
}
struct Node<T> {
element: T,
next: Option<Box<Node<T>>>,
}
impl<T> Stack<T> {
pub fn pop(&mut self) -> Option<T> {
self.head.take().map(|boxed_node| {
let node = *boxed_node;
self.head = node.next;
node.element
})
}
pub fn pop_causes_error(&mut self) -> Option<T> {
self.head.take().map(|boxed_node| {
self.head = (*boxed_node).next;
(*boxed_node).element
})
}
}
error[E0382]: use of moved value: `boxed_node`
--> src/main.rs:22:13
|
21 | self.head = (*boxed_node).next;
| ------------------ value moved here
22 | (*boxed_node).element
| ^^^^^^^^^^^^^^^^^^^^^ value used here after move
|
= note: move occurs because `boxed_node.next` has type `std::option::Option<std::boxed::Box<Node<T>>>`, which does not implement the `Copy` trait
You can only move out of a box once:
struct S;
fn main() {
let x = Box::new(S);
let val: S = *x;
let val2: S = *x; // <-- use of moved value: `*x`
}
In the first function, you moved the value out of the box and assigned it to the node variable. This allows you to move different fields out of it. Even if one field is moved, other fields are still available. Equivalent to this:
struct S1 {
a: S2,
b: S2,
}
struct S2;
fn main() {
let x = Box::new(S1 { a: S2, b: S2 });
let tmp: S1 = *x;
let a = tmp.a;
let b = tmp.b;
}
In the second function, you move the value to the temporary (*boxed_node) and then move a field out of it. The temporary value is destroyed immediately after the end of the expression, along with its other fields. The box doesn't have the data anymore, and you don't have a variable to take the other field from. Equivalent to this:
struct S1 {
a: S2,
b: S2,
}
struct S2;
fn main() {
let x = Box::new(S1 { a: S2, b: S2 });
let tmp: S1 = *x;
let a = tmp.a;
let tmp: S1 = *x; // <-- use of moved value: `*x`
let b = tmp.b;
}
Some good news is that non-lexical lifetimes will allow your original code to work:
pub struct Stack<T> {
head: Option<Box<Node<T>>>,
len: usize,
}
struct Node<T> {
element: T,
next: Option<Box<Node<T>>>,
}
impl<T> Stack<T> {
pub fn pop_no_longer_causes_error(&mut self) -> Option<T> {
self.head.take().map(|boxed_node| {
self.head = (*boxed_node).next;
(*boxed_node).element
})
}
}
NLL enhances the borrow checker to better track the moves of variables.