Skip to content

Instantly share code, notes, and snippets.

@rust-play
Created November 11, 2019 19:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rust-play/1ec5ae521858a1dd171faeafa3ac4fb4 to your computer and use it in GitHub Desktop.
Save rust-play/1ec5ae521858a1dd171faeafa3ac4fb4 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
#![feature(const_generics)]
use std::cell::{Cell, UnsafeCell};
fn main() {
let mut arr = [""];
let view = MutView::new(&mut arr);
let a = "undefined".to_string();
*view.get_mut(0).unwrap() = a.as_str();
println!("{:?}", arr); // use after free
let mut arr = [10,20,30,40,50];
let view = MutView::new(&mut arr);
let a = view.get_mut(0).unwrap();
let b = view.get_mut(1).unwrap();
let c = view.get_mut(2).unwrap();
//panic! 4 variables was borrowed
//let c = view.get_mut(4).unwrap();
//panic! borrowing same key twice
//let c = view.get_mut(2).unwrap();
*a += *b + *c;
*b += 2;
*c += 3;
println!("{:?}", &arr[..]);
}
struct MutView<'a, K, V, const N: usize> {
keys: [Cell<K>; N],
len: Cell<usize>,
view: &'a [UnsafeCell<V>],
}
impl<'a, V> MutView<'a, usize, V, 3> {
fn new(slice: &'a mut [V]) -> Self {
MutView {
view: unsafe { std::mem::transmute(slice) },
keys: [Cell::new(0), Cell::new(0), Cell::new(0)],
len: Cell::new(0),
}
}
fn get_mut(&self, key: usize) -> Option<&mut V> {
let len = self.len.get();
if self.keys[..len]
.iter()
.find(|&i| i.get() == key)
.is_some()
{
panic!("borrowing mut more than once is not allowed")
}
if len >= self.keys.len() {
panic!("reached max borrows, you can increase the size of N if needed")
}
self.keys[len].set(key);
self.len.set(len + 1);
let item = self.view.get(key)?;
unsafe {
Some(&mut *item.get())
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment