Skip to content

Instantly share code, notes, and snippets.

@Kimundi
Forked from anonymous/playground.rs
Created November 13, 2016 14:35
Show Gist options
  • Save Kimundi/2079d773d7551be4e8b0d55608786955 to your computer and use it in GitHub Desktop.
Save Kimundi/2079d773d7551be4e8b0d55608786955 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
use std::mem;
use std::cell::Cell;
fn ref_as_cell<T: Copy>(t: &mut T) -> &Cell<T> {
unsafe { mem::transmute(t) }
}
fn slice_as_cell<T: Copy>(t: &mut [T]) -> &[Cell<T>] {
unsafe { mem::transmute(t) }
}
trait AsCell {
type Cell;
fn as_cell(self) -> Self::Cell;
}
impl<'a, T: Copy> AsCell for &'a mut T {
type Cell = &'a Cell<T>;
fn as_cell(self) -> Self::Cell { ref_as_cell(self) }
}
impl<'a, T: Copy> AsCell for &'a mut [T] {
type Cell = &'a [Cell<T>];
fn as_cell(self) -> Self::Cell { slice_as_cell(self) }
}
fn use_case_1() {
// Accessing all values for each value in a slice.
let mut v = vec![1, 2, 3, 4];
{
let cell_slice = v.as_cell();
for a in cell_slice {
let mut tmp = 0;
for b in cell_slice {
tmp += b.get()
}
a.set(tmp);
}
}
println!("uc 1: {:?}\n", v);
}
fn use_case_2() {
// Offset iteration and mutation
let mut v = vec![1, 2, 3, 4];
{
let cell_slice = v.as_cell();
for (a, b) in cell_slice.iter().zip(cell_slice[1..].iter()) {
a.set(a.get() + b.get());
}
}
println!("uc 2: {:?}\n", v);
}
fn method_resolve_ergonomics() {
let mut a = 4;
let ac = a.as_cell(); // &mut i32 -> &Cell<i32>
ac.set(5);
let mut b = [1, 2, 3];
let bc = b.as_cell(); // &mut [i32; 3] -> &Cell<[i32; 3]>
bc.set([7, 8, 9]);
let mut c = [1, 2, 3];
let cc = c[..].as_cell(); // &mut [i32] -> &[Cell<i32>]
cc[0].set(5);
let mut d = vec![1, 2, 3];
let dc = d.as_cell(); // &mut [i32] -> &[Cell<i32>]
dc[0].set(5);
}
fn use_case_3() {
// Very simplified contrain solver.
// see eddyb's code @ https://github.com/eddyb/r3/blob/master/src/ui/layout.rs#L297
// for a real use case.
// Idea: initial list of objects with (left, right) coordinates of their bounding boxes
let mut objects = vec![(0.0, 1.0), (0.0, 0.0), (0.0, 0.0), (0.0, 3.0)];
println!("uc 3, initial state:");
println!("{:?}", objects);
// Solver goals:
// - objects may not overlap
// - objects may not have negative width
{
// Define a constraint. It contains:
// - a reference `x` to the element that may be changed
// to fulfill the constraint.
// - a reference to an element that gives the contraint,
// in this case the minimum value needed for `x`.
#[derive(Debug)]
struct Constr<'a> {
x: &'a Cell<f32>,
minimum_x_needed: &'a Cell<f32>
}
// helper code to convert the mutable references to the elements
// of the `objects` vector to &Cell references to both
// x coordinates in each object.
let refs: Vec<(&Cell<f32>, &Cell<f32>)> = objects
.iter_mut()
.map(|&mut (ref mut x, ref mut y)| {
(x.as_cell(), y.as_cell())
}).collect();
// Gather all constraints.
// Done manually for simplicity, but could trivially be generated by an algorithms
let constrs = vec![
// objects next to each other may not overlap
Constr { x: &refs[1].0, minimum_x_needed: &refs[0].1 },
Constr { x: &refs[2].0, minimum_x_needed: &refs[1].1 },
Constr { x: &refs[3].0, minimum_x_needed: &refs[2].1 },
// objects may not have negative width
Constr { x: &refs[0].1, minimum_x_needed: &refs[0].0 },
Constr { x: &refs[1].1, minimum_x_needed: &refs[1].0 },
Constr { x: &refs[2].1, minimum_x_needed: &refs[2].0 },
Constr { x: &refs[3].1, minimum_x_needed: &refs[3].0 },
];
println!(" {:?}", refs);
// fixpoint calculation - loop as long as a constraint is
// broken and needs to be adjusted
'outer: loop {
for constr in &constrs {
if constr.x.get() < constr.minimum_x_needed.get() {
constr.x.set(constr.minimum_x_needed.get());
println!(" > {:?}", refs);
continue 'outer;
}
}
break;
}
}
println!("{:?}\n", objects);
}
fn main() {
use_case_1();
use_case_2();
use_case_3();
method_resolve_ergonomics();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment