<commit_before>/**
Katy Williamson kcw4sn
Ben Terner bt3ze
@virginia.edu

Final Project for CS4414 - Operating Systems
A parallel MST implementation on images in Rust

*/

/*
some documentation:
Pixel object is composed of r,g,b values, a color, and an x,y index that takes the place of its adjacency list
Point is just an (x,y) value to denote a pixel's location
Edge contains two points: source and dest, along with the edge cost between them

*/

extern mod extra;
use std::{os, num, hashmap} ;
use extra::{arc,priority_queue};

struct Pixel{
    r: int,
    b: int,
    g: int,
    color: int,
    x: int,
    y: int
}

impl Pixel {
    fn new(red: int, blue: int, green: int, x: int, y: int) -> Pixel {
        Pixel{
            r: red,
            b: blue,
            g: green,
            color: -1,
            x: x,
            y: y
        }
    }
}

impl Clone for Pixel{
    fn clone(&self) -> Pixel {
        Pixel{
            r: self.r,
            b: self.b,
            g: self.g,
            color: self.color,
            x: self.x,
            y: self.y
        }
    }
}

struct Point {
    x: int,
    y: int
}

impl Point{
    fn new(x: int, y: int)-> Point {
        Point {
            x: x,
            y: y
        }
    }
}

struct Edge {
    source: Point,
    dest: Point,
    cost: float
}

impl Edge {
    fn new(s: Point, d: Point, cost: float) -> Edge {
        Edge {
            source: s,
            dest: d,
            cost: cost
        }
    }
}

impl Ord for Edge {
    fn lt(&self, other: &Edge) -> bool {
        self.cost < other.cost
    }
}

fn edgeCost(a: &Pixel, b: &Pixel) -> float {
    num::sqrt( (
            (a.r-b.r)*(a.r-b.r) + (a.g-b.g)*(a.g-b.g) + (a.b-b.b)*(a.b-b.b) ) as float)
}

fn readImage( filename: &~str) -> ~ [ ~[Pixel]] {
    let mut retval: ~[~[Pixel]] = ~[];

    let file: &str = filename.to_owned();
    let file2: ~str = file.to_owned();
    let split_filename: ~[&str] = file.split_iter('.').collect();
    let file_data: &str = split_filename[0] + ".txt";

    println(fmt!("The image name is [%?]", file));
    println(fmt!("The image data will be stored at [%?]", file_data));

    //read in the .txt associated with the file title
    let path = &PosixPath(file_data);

    match std::io::file_reader(path) {
	Ok(reader) => {
	    //run the java program to process the image
	    let program: &str = "java ImageReader";
	    let argv: ~[~str] = ~[file2];

	    let mut prog = std::run::Process::new(program, argv,
		std::run::ProcessOptions {
			env: None,
			dir: None,
			in_fd: None,
			out_fd: None,
			err_fd: None
		}
	    );
	    prog.finish();

	    //parse out the array dimensions
    	    let dimensions_str: &str = reader.read_line();
    	    println(fmt!("dimensons: %s",dimensions_str));
	    let mut h: int = 0;
	    let mut w: int = 0;
	    match dimensions_str[0] as char {
		'H' => {
		    let split_dim: ~[&str] = dimensions_str.split_iter('W').collect();
		    h = from_str(split_dim[0].slice(1,split_dim[0].len())).unwrap();
		    w = from_str(split_dim[1]).unwrap();
		    println(fmt!("Dimensions passed: H %? W %?",h,w));
		    //let retval: ~[ ~[Pixel, ..w], ..h];
		}
		_ => {println("Dimensions corrupted! Abort");}
	    }

	    //fill in the retVal array with pixel data
            //let mut rowfirst = false;
	    for row in range(0,h){
//                if(!rowfirst) {
                retval.push(~[]);
                //rowfirst = true; }
		for col in range(0,w){
	    	    if !reader.eof() {
			let line: &str = reader.read_line();
			//println(line);
			let rpos:uint = match line.find('R') { Some(n)=>n,None=>line.len() };
			let gpos:uint = match line.find('G') { Some(n)=>n,None=>line.len() };
			let bpos:uint = match line.find('B') { Some(n)=>n,None=>line.len() };

			if rpos == line.len() || gpos == line.len() || bpos == line.len() {
			    println("Pixel data corrupted! Abort");
			}

			let R:int = from_str(line.slice(rpos+1,gpos)).unwrap();
			let G:int = from_str(line.slice(gpos+1,bpos)).unwrap();
			let B:int = from_str(line.slice(bpos+1,line.len())).unwrap();

			//println(fmt!("R %? G %? B %?",R,G,B));

			//fn new(red: int, blue: int, green: int, x: int, y: int) -> Pixel {
			retval[row].push(Pixel::new(R,G,B,col,row));

		    }
		    else {
			println("Data file corrupted! Abort");
		    }
		}
	    }
	},
	Err(err)   => { fail!(err) }
    }

    retval
}

fn main(){
    let argv =  os::args();
    println(argv.to_str());

    let pixels: ~[ ~[Pixel] ] = readImage(&argv[1]);
    let height = pixels.len() as int;
    let width = pixels[0].len() as int;

    println(fmt!("Dimensions received: H %? W %?",height,width));

    let mut find_arcs: ~[ ~[arc::RWArc<Pixel>] ] =  ~[];
    for h in range(0,height){
	find_arcs.push(~[]);
        for w in range(0,width){
 //           println(fmt!("pix %?",pixels[h][w]));
	    find_arcs[h].push(arc::RWArc::new(pixels[h][w]));
	}
    }

    let arcs = find_arcs; // now we have an immutable array that can be shared

    let corners = [ (0,0),(width-1,0),(0,height-1),(width-1,height-1) ];

    for &corner in corners.iter() {
        let (a,b) = corner;
        let shared_arcs = arcs.clone();
        do spawn { // split into threads here
            let c = a;
            let d = b;
            let mut x=a;
            let mut y=b;

            let mut queue: priority_queue::PriorityQueue<Edge> =  priority_queue::PriorityQueue::new();
            let mut visited: hashmap::HashMap<(int,int),bool> = hashmap::HashMap::new();
            let mut newvisit: bool = true;

            println(fmt!("start at (%i,%i)",c,d));

            loop { // iterate through items in the queue, which contains all of the edges/vertices
                if(newvisit){
                   println(fmt!("(%i,%i) : (%i,%i)",c,d,x,y));
                    let neighbors = [ (x,y-1),(x+1,y), (x,y+1), (x-1,y)];
                    for &coord in neighbors.iter() {
                        let (w,z) = coord;
                        if w >=0 && w < width && z >=0 && z < height { // bounds checking
                            // if neighbor at coord has not been or colored
                            let mut newvertex = false;
                            let mut uncolored = false;
                            do shared_arcs[z][w].read |dest| {
                                if dest.color < 0 {
                                    uncolored = true; }
                            }
                            if uncolored {
                                do shared_arcs[z][w].write |dest| {
                                    if dest.color < 0 {
                                        do shared_arcs[y][x].read |src| {
                                            dest.color = src.color;
                                        }
                                        newvertex = true;
                                    }
                                }
                            }
                            if newvertex { // then we have a new vertex
                                do shared_arcs[y][x].read |src| {
                                    do shared_arcs[z][w].read |dest| {
                                        queue.push( Edge::new(Point::new(x,y),Point::new(w,z),edgeCost(src,dest)));
                                    }
                                }
                            }
                        }
                    }
                }

                let edge = queue.maybe_pop();
                match edge {
                    Some(e) => {
                        println(fmt!("(%i,%i) pop (%i,%i)-%f-(%i,%i)",c,d,e.source.x,e.source.y,e.cost,e.dest.x,e.dest.y));
                        // not in any tree
                        let coord = (e.dest.x,e.dest.y);
//                        println(fmt!("before runtime error? %?",coord));
                        if !visited.contains_key(&coord){
//if *visited.get(&coord) == false { // use visited hashmap to figure out if we're at a new vertex. returns false if it can't return a vertex?
                            visited.insert(coord,true);
                            x = e.dest.x;
                            y = e.dest.y;
                            newvisit = true;
//                            println(fmt!("%? %f",coord,e.cost));
                        } else {
                            newvisit = false;
                        }
                    },
                    None => { break; } // this should execute at the end when there are no more unvisited or uncolored nodes for a thread
                }
            }

        }
    }
}
<commit_msg>don't need to run image-to-file processor within the mst code.<commit_after>/**
Katy Williamson kcw4sn
Ben Terner bt3ze
@virginia.edu

Final Project for CS4414 - Operating Systems
A parallel MST implementation on images in Rust

*/

/*
some documentation:
Pixel object is composed of r,g,b values, a color, and an x,y index that takes the place of its adjacency list
Point is just an (x,y) value to denote a pixel's location
Edge contains two points: source and dest, along with the edge cost between them

*/

extern mod extra;
use std::{os, num, hashmap} ;
use extra::{arc,priority_queue};

struct Pixel{
    r: int,
    b: int,
    g: int,
    color: int,
    x: int,
    y: int
}

impl Pixel {
    fn new(red: int, blue: int, green: int, x: int, y: int) -> Pixel {
        Pixel{
            r: red,
            b: blue,
            g: green,
            color: -1,
            x: x,
            y: y
        }
    }
}

impl Clone for Pixel{
    fn clone(&self) -> Pixel {
        Pixel{
            r: self.r,
            b: self.b,
            g: self.g,
            color: self.color,
            x: self.x,
            y: self.y
        }
    }
}

struct Point {
    x: int,
    y: int
}

impl Point{
    fn new(x: int, y: int)-> Point {
        Point {
            x: x,
            y: y
        }
    }
}

struct Edge {
    source: Point,
    dest: Point,
    cost: float
}

impl Edge {
    fn new(s: Point, d: Point, cost: float) -> Edge {
        Edge {
            source: s,
            dest: d,
            cost: cost
        }
    }
}

impl Ord for Edge {
    fn lt(&self, other: &Edge) -> bool {
        self.cost < other.cost
    }
}

fn edgeCost(a: &Pixel, b: &Pixel) -> float {
    num::sqrt( (
            (a.r-b.r)*(a.r-b.r) + (a.g-b.g)*(a.g-b.g) + (a.b-b.b)*(a.b-b.b) ) as float)
}

fn readImage( filename: &~str) -> ~ [ ~[Pixel]] {
    let mut retval: ~[~[Pixel]] = ~[];

    let file: &str = filename.to_owned();
    let file2: ~str = file.to_owned();
    let split_filename: ~[&str] = file.split_iter('.').collect();
    let file_data: &str = split_filename[0] + ".txt";

    println(fmt!("The image name is [%?]", file));
    println(fmt!("The image data will be stored at [%?]", file_data));

    //read in the .txt associated with the file title
    let path = &PosixPath(file_data);

    match std::io::file_reader(path) {
	Ok(reader) => {
	    //run the java program to process the image
/*	    let program: &str = "java ImageReader";
	    let argv: ~[~str] = ~[file2];
	    let mut prog = std::run::Process::new(program, argv,
		std::run::ProcessOptions {
			env: None,
			dir: None,
			in_fd: None,
			out_fd: None,
			err_fd: None
		}
	    );
	    prog.finish();
*/
	    //parse out the array dimensions
    	    let dimensions_str: &str = reader.read_line();
    	    println(fmt!("dimensons: %s",dimensions_str));
	    let mut h: int = 0;
	    let mut w: int = 0;
	    match dimensions_str[0] as char {
		'H' => {
		    let split_dim: ~[&str] = dimensions_str.split_iter('W').collect();
		    h = from_str(split_dim[0].slice(1,split_dim[0].len())).unwrap();
		    w = from_str(split_dim[1]).unwrap();
		    println(fmt!("Dimensions passed: H %? W %?",h,w));
		    //let retval: ~[ ~[Pixel, ..w], ..h];
		}
		_ => {println("Dimensions corrupted! Abort");}
	    }

	    //fill in the retVal array with pixel data
            //let mut rowfirst = false;
	    for row in range(0,h){
//                if(!rowfirst) {
                retval.push(~[]);
                //rowfirst = true; }
		for col in range(0,w){
	    	    if !reader.eof() {
			let line: &str = reader.read_line();
			//println(line);
			let rpos:uint = match line.find('R') { Some(n)=>n,None=>line.len() };
			let gpos:uint = match line.find('G') { Some(n)=>n,None=>line.len() };
			let bpos:uint = match line.find('B') { Some(n)=>n,None=>line.len() };

			if rpos == line.len() || gpos == line.len() || bpos == line.len() {
			    println("Pixel data corrupted! Abort");
			}

			let R:int = from_str(line.slice(rpos+1,gpos)).unwrap();
			let G:int = from_str(line.slice(gpos+1,bpos)).unwrap();
			let B:int = from_str(line.slice(bpos+1,line.len())).unwrap();

			//println(fmt!("R %? G %? B %?",R,G,B));

			//fn new(red: int, blue: int, green: int, x: int, y: int) -> Pixel {
			retval[row].push(Pixel::new(R,G,B,col,row));

		    }
		    else {
			println("Data file corrupted! Abort");
		    }
		}
	    }
	},
	Err(err)   => { fail!(err) }
    }

    retval
}

fn main(){
    let argv =  os::args();
    println(argv.to_str());

    let pixels: ~[ ~[Pixel] ] = readImage(&argv[1]);
    let height = pixels.len() as int;
    let width = pixels[0].len() as int;

    println(fmt!("Dimensions received: H %? W %?",height,width));

    let mut find_arcs: ~[ ~[arc::RWArc<Pixel>] ] =  ~[];
    for h in range(0,height){
	find_arcs.push(~[]);
        for w in range(0,width){
 //           println(fmt!("pix %?",pixels[h][w]));
	    find_arcs[h].push(arc::RWArc::new(pixels[h][w]));
	}
    }

    let arcs = find_arcs; // now we have an immutable array that can be shared

    let corners = [ (0,0),(width-1,0),(0,height-1),(width-1,height-1) ];

    for &corner in corners.iter() {
        let (a,b) = corner;
        let shared_arcs = arcs.clone();
        do spawn { // split into threads here
            let c = a;
            let d = b;
            let mut x=a;
            let mut y=b;

            let mut queue: priority_queue::PriorityQueue<Edge> =  priority_queue::PriorityQueue::new();
            let mut visited: hashmap::HashMap<(int,int),bool> = hashmap::HashMap::new();
            let mut newvisit: bool = true;

            println(fmt!("start at (%i,%i)",c,d));

            loop { // iterate through items in the queue, which contains all of the edges/vertices
                if(newvisit){
                   println(fmt!("(%i,%i) : (%i,%i)",c,d,x,y));
                    let neighbors = [ (x,y-1),(x+1,y), (x,y+1), (x-1,y)];
                    for &coord in neighbors.iter() {
                        let (w,z) = coord;
                        if w >=0 && w < width && z >=0 && z < height { // bounds checking
                            // if neighbor at coord has not been or colored
                            let mut newvertex = false;
                            let mut uncolored = false;
                            do shared_arcs[z][w].read |dest| {
                                if dest.color < 0 {
                                    uncolored = true; }
                            }
                            if uncolored {
                                do shared_arcs[z][w].write |dest| {
                                    if dest.color < 0 {
                                        do shared_arcs[y][x].read |src| {
                                            dest.color = src.color;
                                        }
                                        newvertex = true;
                                    }
                                }
                            }
                            if newvertex { // then we have a new vertex
                                do shared_arcs[y][x].read |src| {
                                    do shared_arcs[z][w].read |dest| {
                                        queue.push( Edge::new(Point::new(x,y),Point::new(w,z),edgeCost(src,dest)));
                                    }
                                }
                            }
                        }
                    }
                }

                let edge = queue.maybe_pop();
                match edge {
                    Some(e) => {
                        println(fmt!("(%i,%i) pop (%i,%i)-%f-(%i,%i)",c,d,e.source.x,e.source.y,e.cost,e.dest.x,e.dest.y));
                        // not in any tree
                        let coord = (e.dest.x,e.dest.y);
//                        println(fmt!("before runtime error? %?",coord));
                        if !visited.contains_key(&coord){
 // use visited hashmap to figure out if we're at a new vertex.
                            visited.insert(coord,true);
                            x = e.dest.x;
                            y = e.dest.y;
                            newvisit = true;
//                            println(fmt!("%? %f",coord,e.cost));
                        } else {
                            newvisit = false;
                        }
                    },
                    None => { break; } // this should execute at the end when there are no more unvisited or uncolored nodes for a thread
                }
            }

        }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::*;
use std::mem;
use std::slice;
use std::thread;
use std::to_num::ToNum;

use super::Event;
use super::Color;

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: i32,
    /// The y coordinate of the window
    y: i32,
    /// The width of the window
    w: u32,
    /// The height of the window
    h: u32,
    /// The title of the window
    t: String,
    /// The input scheme
    file: File,
    /// Font file
    font: Vec<u8>,
    /// Window data
    data: Box<[Color]>,
}

impl Window {
    /// Create a new window
    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Box<Self>> {
        let mut font = Vec::new();
        if let Ok(mut font_file) = File::open("file:/ui/unifont.font") {
            let _ = font_file.read_to_end(&mut font);
        }

        match File::open(&format!("orbital:{}/{}/{}/{}/{}", x, y, w, h, title)) {
            Ok(file) => {
                Some(box Window {
                    x: x,
                    y: y,
                    w: w,
                    h: h,
                    t: title.to_string(),
                    file: file,
                    font: font,
                    data: vec![Color::rgb(0, 0, 0); (w * h * 4) as usize].into_boxed_slice(),
                })
            }
            Err(_) => None,
        }
    }

    // TODO: Replace with smarter mechanism, maybe a move event?
    pub fn sync_path(&mut self) {
        if let Ok(path) = self.file.path() {
            // orbital://x/y/w/h/t
            if let Some(path_str) = path.to_str() {
                let parts: Vec<&str> = path_str.split('/').collect();
                if let Some(x) = parts.get(3) {
                    self.x = x.to_num_signed();
                }
                if let Some(y) = parts.get(4) {
                    self.y = y.to_num_signed();
                }
                if let Some(w) = parts.get(5) {
                    self.w = w.to_num();
                }
                if let Some(h) = parts.get(6) {
                    self.h = h.to_num();
                }
            }
        }
    }

    /// Get x
    // TODO: Sync with window movements
    pub fn x(&self) -> i32 {
        self.x
    }

    /// Get y
    // TODO: Sync with window movements
    pub fn y(&self) -> i32 {
        self.y
    }

    /// Get width
    pub fn width(&self) -> u32 {
        self.w
    }

    /// Get height
    pub fn height(&self) -> u32 {
        self.h
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set title
    pub fn set_title(&mut self, _: &str) {
        // TODO
    }

    /// Draw a pixel
    pub fn pixel(&mut self, x: i32, y: i32, color: Color) {
        if x >= 0 && y >= 0 && x < self.w as i32 && y < self.h as i32 {
            let new = color.data;

            let alpha = (new >> 24) & 0xFF;
            if alpha > 0 {
                let old = &mut self.data[y as usize * self.w as usize + x as usize].data;
                if alpha >= 255 {
                    *old = new;
                } else {
                    let n_r = (((new >> 16) & 0xFF) * alpha) >> 8;
                    let n_g = (((new >> 8) & 0xFF) * alpha) >> 8;
                    let n_b = ((new & 0xFF) * alpha) >> 8;

                    let n_alpha = 255 - alpha;
                    let o_a = (((*old >> 24) & 0xFF) * n_alpha) >> 8;
                    let o_r = (((*old >> 16) & 0xFF) * n_alpha) >> 8;
                    let o_g = (((*old >> 8) & 0xFF) * n_alpha) >> 8;
                    let o_b = ((*old & 0xFF) * n_alpha) >> 8;

                    *old = ((o_a << 24) | (o_r << 16) | (o_g << 8) | o_b) + ((alpha << 24) | (n_r << 16) | (n_g << 8) | n_b);
                }
            }
        }
    }

    /// Draw a character, using the loaded font
    pub fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
        let mut offset = (c as usize) * 16;
        for row in 0..16 {
            let row_data;
            if offset < self.font.len() {
                row_data = self.font[offset];
            } else {
                row_data = 0;
            }

            for col in 0..8 {
                let pixel = (row_data >> (7 - col)) & 1;
                if pixel > 0 {
                    self.pixel(x + col as i32, y + row as i32, color);
                }
            }
            offset += 1;
        }
    }

    // TODO move, resize, set_title

    /// Set entire window to a color
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn set(&mut self, color: Color) {
        for mut d in self.data.iter_mut() {
            *d = color;
        }
    }

    /// Draw rectangle
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn rect(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, color: Color) {
        for y in start_y..start_y + h as i32 {
            for x in start_x..start_x + w as i32 {
                self.pixel(x, y, color);
            }
        }
    }

    /// Display an image
    // TODO: Improve speed
    pub fn image(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, data: &[Color]) {
        let mut i = 0;
        for y in start_y..start_y + h as i32 {
            for x in start_x..start_x + w as i32 {
                if i < data.len() {
                    self.pixel(x, y, data[i])
                }
                i += 1;
            }
        }
    }

    /// Poll for an event
    // TODO: clean this up
    pub fn poll(&mut self) -> Option<Event> {
        loop {
            let mut event = Event::new();
            match self.file.read(&mut event) {
                Ok(0) => thread::yield_now(),
                Ok(_) => {
                    println!("{:?}", event);
                    return Some(event);
                },
                Err(_) => return None,
            }
        }
    }

    /// Flip the window buffer
    pub fn sync(&mut self) -> bool {
        self.file.write(unsafe {
            slice::from_raw_parts(self.data.as_ptr() as *const u8,
                                  self.data.len() * mem::size_of::<Color>())
        }).is_ok()
    }

    /// Return a iterator over events
    pub fn event_iter<'a>(&'a mut self) -> EventIter<'a> {
        EventIter { window: self }
    }
}

/// Event iterator
pub struct EventIter<'a> {
    window: &'a mut Window,
}

impl<'a> Iterator for EventIter<'a> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.window.poll()
    }
}
<commit_msg>Remove unnecessary intexes<commit_after>use std::fs::File;
use std::io::*;
use std::mem;
use std::slice;
use std::thread;
use std::to_num::ToNum;

use super::Event;
use super::Color;

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: i32,
    /// The y coordinate of the window
    y: i32,
    /// The width of the window
    w: u32,
    /// The height of the window
    h: u32,
    /// The title of the window
    t: String,
    /// The input scheme
    file: File,
    /// Font file
    font: Vec<u8>,
    /// Window data
    data: Box<[Color]>,
}

impl Window {
    /// Create a new window
    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Box<Self>> {
        let mut font = Vec::new();
        if let Ok(mut font_file) = File::open("file:/ui/unifont.font") {
            let _ = font_file.read_to_end(&mut font);
        }

        match File::open(&format!("orbital:{}/{}/{}/{}/{}", x, y, w, h, title)) {
            Ok(file) => {
                Some(box Window {
                    x: x,
                    y: y,
                    w: w,
                    h: h,
                    t: title.to_string(),
                    file: file,
                    font: font,
                    data: vec![Color::rgb(0, 0, 0); (w * h * 4) as usize].into_boxed_slice(),
                })
            }
            Err(_) => None,
        }
    }

    // TODO: Replace with smarter mechanism, maybe a move event?
    pub fn sync_path(&mut self) {
        if let Ok(path) = self.file.path() {
            // orbital://x/y/w/h/t
            if let Some(path_str) = path.to_str() {
                let parts: Vec<&str> = path_str.split('/').collect();
                if let Some(x) = parts.get(3) {
                    self.x = x.to_num_signed();
                }
                if let Some(y) = parts.get(4) {
                    self.y = y.to_num_signed();
                }
                if let Some(w) = parts.get(5) {
                    self.w = w.to_num();
                }
                if let Some(h) = parts.get(6) {
                    self.h = h.to_num();
                }
            }
        }
    }

    /// Get x
    // TODO: Sync with window movements
    pub fn x(&self) -> i32 {
        self.x
    }

    /// Get y
    // TODO: Sync with window movements
    pub fn y(&self) -> i32 {
        self.y
    }

    /// Get width
    pub fn width(&self) -> u32 {
        self.w
    }

    /// Get height
    pub fn height(&self) -> u32 {
        self.h
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set title
    pub fn set_title(&mut self, _: &str) {
        // TODO
    }

    /// Draw a pixel
    pub fn pixel(&mut self, x: i32, y: i32, color: Color) {
        if x >= 0 && y >= 0 && x < self.w as i32 && y < self.h as i32 {
            let new = color.data;

            let alpha = (new >> 24) & 0xFF;
            if alpha > 0 {
                let old = &mut self.data[y as usize * self.w as usize + x as usize].data;
                if alpha >= 255 {
                    *old = new;
                } else {
                    let n_r = (((new >> 16) & 0xFF) * alpha) >> 8;
                    let n_g = (((new >> 8) & 0xFF) * alpha) >> 8;
                    let n_b = ((new & 0xFF) * alpha) >> 8;

                    let n_alpha = 255 - alpha;
                    let o_a = (((*old >> 24) & 0xFF) * n_alpha) >> 8;
                    let o_r = (((*old >> 16) & 0xFF) * n_alpha) >> 8;
                    let o_g = (((*old >> 8) & 0xFF) * n_alpha) >> 8;
                    let o_b = ((*old & 0xFF) * n_alpha) >> 8;

                    *old = ((o_a << 24) | (o_r << 16) | (o_g << 8) | o_b) + ((alpha << 24) | (n_r << 16) | (n_g << 8) | n_b);
                }
            }
        }
    }

    /// Draw a character, using the loaded font
    pub fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
        let mut offset = (c as usize) * 16;
        for row in 0..16 {
            let row_data;
            if offset < self.font.len() {
                row_data = self.font[offset];
            } else {
                row_data = 0;
            }

            for col in 0..8 {
                let pixel = (row_data >> (7 - col)) & 1;
                if pixel > 0 {
                    self.pixel(x + col as i32, y + row as i32, color);
                }
            }
            offset += 1;
        }
    }

    // TODO move, resize, set_title

    /// Set entire window to a color
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn set(&mut self, color: Color) {
        for mut d in self.data.iter_mut() {
            *d = color;
        }
    }

    /// Draw rectangle
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn rect(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, color: Color) {
        for y in start_y..start_y + h as i32 {
            for x in start_x..start_x + w as i32 {
                self.pixel(x, y, color);
            }
        }
    }

    /// Display an image
    // TODO: Improve speed
    pub fn image(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, data: &[Color]) {
        let mut i = 0;
        for y in start_y..start_y + h as i32 {
            for x in start_x..start_x + w as i32 {
                if i < data.len() {
                    self.pixel(x, y, data[i])
                }
                i += 1;
            }
        }
    }

    /// Poll for an event
    // TODO: clean this up
    pub fn poll(&mut self) -> Option<Event> {
        loop {
            let mut event = Event::new();
            match self.file.read(&mut event) {
                Ok(0) => thread::yield_now(),
                Ok(_) => return Some(event),
                Err(_) => return None,
            }
        }
    }

    /// Flip the window buffer
    pub fn sync(&mut self) -> bool {
        self.file.write(unsafe {
            slice::from_raw_parts(self.data.as_ptr() as *const u8,
                                  self.data.len() * mem::size_of::<Color>())
        }).is_ok()
    }

    /// Return a iterator over events
    pub fn event_iter<'a>(&'a mut self) -> EventIter<'a> {
        EventIter { window: self }
    }
}

/// Event iterator
pub struct EventIter<'a> {
    window: &'a mut Window,
}

impl<'a> Iterator for EventIter<'a> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.window.poll()
    }
}
<|endoftext|>


<commit_before>// Copyright ⓒ 2015-2018 Kevin B. Knapp
//
// `clap_generate` is distributed under the terms of both the MIT license and the Apache License
// (Version 2.0).
// See the [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) files in this repository
// for more information.

//! Generates stuff for [`clap`](https://github.com/clap-rs/clap) based CLIs

#![doc(html_logo_url = "https://clap.rs/images/media/clap.png")]
#![doc(html_root_url = "https://docs.rs/clap_generate/3.0.0-beta.2")]
#![deny(
    missing_docs,
    trivial_casts,
    unused_import_braces,
    unused_allocation,
    trivial_numeric_casts
)]
#![forbid(unsafe_code)]
#![allow(clippy::needless_doctest_main)]

const INTERNAL_ERROR_MSG: &str = "Fatal internal error. Please consider filing a bug \
                                  report at https://github.com/clap-rs/clap/issues";

#[macro_use]
#[allow(missing_docs)]
mod macros;

/// Contains some popular generators
pub mod generators;
/// Contains supported shells for auto-completion scripts
pub mod shell;

use std::ffi::OsString;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

#[doc(inline)]
pub use generators::Generator;
#[doc(inline)]
pub use shell::Shell;

/// Generate a file for a specified generator at compile time.
///
/// **NOTE:** to generate the file at compile time you must use a `build.rs` "Build Script"
///
/// # Examples
///
/// The following example generates a bash completion script via a `build.rs` script. In this
/// simple example, we'll demo a very small application with only a single subcommand and two
/// args. Real applications could be many multiple levels deep in subcommands, and have tens or
/// potentially hundreds of arguments.
///
/// First, it helps if we separate out our `App` definition into a separate file. Whether you
/// do this as a function, or bare App definition is a matter of personal preference.
///
/// ```
/// // src/cli.rs
///
/// use clap::{App, Arg};
///
/// pub fn build_cli() -> App<'static> {
///     App::new("compl")
///         .about("Tests completions")
///         .arg(Arg::new("file")
///             .about("some input file"))
///         .subcommand(App::new("test")
///             .about("tests things")
///             .arg(Arg::new("case")
///                 .long("case")
///                 .takes_value(true)
///                 .about("the case to test")))
/// }
/// ```
///
/// In our regular code, we can simply call this `build_cli()` function, then call
/// `get_matches()`, or any of the other normal methods directly after. For example:
///
/// ```ignore
/// // src/main.rs
///
/// mod cli;
///
/// fn main() {
///     let m = cli::build_cli().get_matches();
///
///     // normal logic continues...
/// }
/// ```
///
/// Next, we set up our `Cargo.toml` to use a `build.rs` build script.
///
/// ```toml
/// # Cargo.toml
/// build = "build.rs"
///
/// [build-dependencies]
/// clap = "*"
/// ```
///
/// Next, we place a `build.rs` in our project root.
///
/// ```ignore
/// use clap_generate::{generate_to, generators::Bash};
///
/// include!("src/cli.rs");
///
/// fn main() {
///     let outdir = match env::var_os("OUT_DIR") {
///         None => return,
///         Some(outdir) => outdir,
///     };
///
///     let mut app = build_cli();
///     generate_to::<Bash, _, _>(
///         &mut app,     // We need to specify what generator to use
///         "myapp",      // We need to specify the bin name manually
///         outdir,       // We need to specify where to write to
///     );
/// }
/// ```
///
/// Now, once we compile there will be a `{bin_name}.bash` file in the directory.
/// Assuming we compiled with debug mode, it would be somewhere similar to
/// `<project>/target/debug/build/myapp-<hash>/out/myapp.bash`.
///
/// **NOTE:** Please look at the individual [generators](./generators/index.html)
/// to see the name of the files generated.
pub fn generate_to<G, S, T>(app: &mut clap::App, bin_name: S, out_dir: T)
where
    G: Generator,
    S: Into<String>,
    T: Into<OsString>,
{
    let out_dir = PathBuf::from(out_dir.into());
    let file_name = G::file_name(app.get_bin_name().unwrap());

    let mut file = match File::create(out_dir.join(file_name)) {
        Err(why) => panic!("couldn't create completion file: {}", why),
        Ok(file) => file,
    };

    generate::<G, S>(app, bin_name, &mut file)
}

/// Generate a completions file for a specified shell at runtime.
///
/// Until `cargo install` can install extra files like a completion script, this may be
/// used e.g. in a command that outputs the contents of the completion script, to be
/// redirected into a file by the user.
///
/// # Examples
///
/// Assuming a separate `cli.rs` like the [example above](./fn.generate_to.html),
/// we can let users generate a completion script using a command:
///
/// ```ignore
/// // src/main.rs
///
/// mod cli;
/// use std::io;
/// use clap_generate::{generate, generators::Bash};
///
/// fn main() {
///     let matches = cli::build_cli().get_matches();
///
///     if matches.is_present("generate-bash-completions") {
///         generate::<Bash, _>(&mut cli::build_cli(), "myapp", &mut io::stdout());
///     }
///
///     // normal logic continues...
/// }
///
/// ```
///
/// Usage:
///
/// ```shell
/// $ myapp generate-bash-completions > /usr/share/bash-completion/completions/myapp.bash
/// ```
pub fn generate<G, S>(app: &mut clap::App, bin_name: S, buf: &mut dyn Write)
where
    G: Generator,
    S: Into<String>,
{
    app.set_bin_name(bin_name);

    // TODO: All the subcommands need to be built instead of just the top one
    app._build();
    app._build_bin_names();

    G::generate(app, buf)
}
<commit_msg>Make clap_generate::shell mod private<commit_after>// Copyright ⓒ 2015-2018 Kevin B. Knapp
//
// `clap_generate` is distributed under the terms of both the MIT license and the Apache License
// (Version 2.0).
// See the [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) files in this repository
// for more information.

//! Generates stuff for [`clap`](https://github.com/clap-rs/clap) based CLIs

#![doc(html_logo_url = "https://clap.rs/images/media/clap.png")]
#![doc(html_root_url = "https://docs.rs/clap_generate/3.0.0-beta.2")]
#![deny(
    missing_docs,
    trivial_casts,
    unused_import_braces,
    unused_allocation,
    trivial_numeric_casts
)]
#![forbid(unsafe_code)]
#![allow(clippy::needless_doctest_main)]

const INTERNAL_ERROR_MSG: &str = "Fatal internal error. Please consider filing a bug \
                                  report at https://github.com/clap-rs/clap/issues";

#[macro_use]
#[allow(missing_docs)]
mod macros;

/// Contains some popular generators
pub mod generators;
/// Contains supported shells for auto-completion scripts
mod shell;

use std::ffi::OsString;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

#[doc(inline)]
pub use generators::Generator;
#[doc(inline)]
pub use shell::Shell;

/// Generate a file for a specified generator at compile time.
///
/// **NOTE:** to generate the file at compile time you must use a `build.rs` "Build Script"
///
/// # Examples
///
/// The following example generates a bash completion script via a `build.rs` script. In this
/// simple example, we'll demo a very small application with only a single subcommand and two
/// args. Real applications could be many multiple levels deep in subcommands, and have tens or
/// potentially hundreds of arguments.
///
/// First, it helps if we separate out our `App` definition into a separate file. Whether you
/// do this as a function, or bare App definition is a matter of personal preference.
///
/// ```
/// // src/cli.rs
///
/// use clap::{App, Arg};
///
/// pub fn build_cli() -> App<'static> {
///     App::new("compl")
///         .about("Tests completions")
///         .arg(Arg::new("file")
///             .about("some input file"))
///         .subcommand(App::new("test")
///             .about("tests things")
///             .arg(Arg::new("case")
///                 .long("case")
///                 .takes_value(true)
///                 .about("the case to test")))
/// }
/// ```
///
/// In our regular code, we can simply call this `build_cli()` function, then call
/// `get_matches()`, or any of the other normal methods directly after. For example:
///
/// ```ignore
/// // src/main.rs
///
/// mod cli;
///
/// fn main() {
///     let m = cli::build_cli().get_matches();
///
///     // normal logic continues...
/// }
/// ```
///
/// Next, we set up our `Cargo.toml` to use a `build.rs` build script.
///
/// ```toml
/// # Cargo.toml
/// build = "build.rs"
///
/// [build-dependencies]
/// clap = "*"
/// ```
///
/// Next, we place a `build.rs` in our project root.
///
/// ```ignore
/// use clap_generate::{generate_to, generators::Bash};
///
/// include!("src/cli.rs");
///
/// fn main() {
///     let outdir = match env::var_os("OUT_DIR") {
///         None => return,
///         Some(outdir) => outdir,
///     };
///
///     let mut app = build_cli();
///     generate_to::<Bash, _, _>(
///         &mut app,     // We need to specify what generator to use
///         "myapp",      // We need to specify the bin name manually
///         outdir,       // We need to specify where to write to
///     );
/// }
/// ```
///
/// Now, once we compile there will be a `{bin_name}.bash` file in the directory.
/// Assuming we compiled with debug mode, it would be somewhere similar to
/// `<project>/target/debug/build/myapp-<hash>/out/myapp.bash`.
///
/// **NOTE:** Please look at the individual [generators](./generators/index.html)
/// to see the name of the files generated.
pub fn generate_to<G, S, T>(app: &mut clap::App, bin_name: S, out_dir: T)
where
    G: Generator,
    S: Into<String>,
    T: Into<OsString>,
{
    let out_dir = PathBuf::from(out_dir.into());
    let file_name = G::file_name(app.get_bin_name().unwrap());

    let mut file = match File::create(out_dir.join(file_name)) {
        Err(why) => panic!("couldn't create completion file: {}", why),
        Ok(file) => file,
    };

    generate::<G, S>(app, bin_name, &mut file)
}

/// Generate a completions file for a specified shell at runtime.
///
/// Until `cargo install` can install extra files like a completion script, this may be
/// used e.g. in a command that outputs the contents of the completion script, to be
/// redirected into a file by the user.
///
/// # Examples
///
/// Assuming a separate `cli.rs` like the [example above](./fn.generate_to.html),
/// we can let users generate a completion script using a command:
///
/// ```ignore
/// // src/main.rs
///
/// mod cli;
/// use std::io;
/// use clap_generate::{generate, generators::Bash};
///
/// fn main() {
///     let matches = cli::build_cli().get_matches();
///
///     if matches.is_present("generate-bash-completions") {
///         generate::<Bash, _>(&mut cli::build_cli(), "myapp", &mut io::stdout());
///     }
///
///     // normal logic continues...
/// }
///
/// ```
///
/// Usage:
///
/// ```shell
/// $ myapp generate-bash-completions > /usr/share/bash-completion/completions/myapp.bash
/// ```
pub fn generate<G, S>(app: &mut clap::App, bin_name: S, buf: &mut dyn Write)
where
    G: Generator,
    S: Into<String>,
{
    app.set_bin_name(bin_name);

    // TODO: All the subcommands need to be built instead of just the top one
    app._build();
    app._build_bin_names();

    G::generate(app, buf)
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! This crates provides Faucet service for creating Testnet with simplified on-chain account creation
//! and minting coins.
//!
//! THIS SERVICE SHOULD NEVER BE DEPLOYED TO MAINNET.
//!
//! ## Launch service
//!
//! Launch faucet service local and connect to Testnet:
//!
//! ```bash
//! cargo run -p diem-faucet -- -a 127.0.0.1 -p 8080 -c TESTNET \
//!     -m <treasury-compliance-private-key-path> -s https://testnet.diem.com/v1
//! ```
//!
//! Check help doc for options details:
//!
//! ```bash
//! cargo run -p diem-faucet -- -h
//! ```
//!
//! ## Development
//!
//! Test with diem-swarm by add -m option:
//!
//! ```bash
//! cargo run -p diem-swarm -- -s -l -n 1 -m
//! ```
//!

use anyhow::Result;
use diem_logger::info;
use diem_sdk::{
    client::{Client, SignedTransaction},
    transaction_builder::TransactionFactory,
    types::{chain_id::ChainId, LocalAccount},
};
use std::{
    fmt,
    sync::{Arc, Mutex},
};
use warp::{Filter, Rejection, Reply};

pub mod mint;

pub struct Service {
    treasury_compliance_account: Mutex<LocalAccount>,
    designated_dealer_account: Mutex<LocalAccount>,
    transaction_factory: TransactionFactory,
    client: Client,
}

impl Service {
    pub fn new(
        jsonrpc_endpoint: String,
        chain_id: ChainId,
        treasury_compliance_account: LocalAccount,
        designated_dealer_account: LocalAccount,
    ) -> Self {
        let client = Client::new(jsonrpc_endpoint);
        Service {
            treasury_compliance_account: Mutex::new(treasury_compliance_account),
            designated_dealer_account: Mutex::new(designated_dealer_account),
            transaction_factory: TransactionFactory::new(chain_id)
                .with_transaction_expiration_time(30),
            client,
        }
    }
}

pub fn routes(
    service: Arc<Service>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
    let mint = mint::mint_routes(service.clone());
    let health = warp::path!("-" / "healthy").map(|| "diem-faucet:ok");

    health
        .or(mint)
        .with(warp::log::custom(|info| {
            info!(
                "{} \"{} {} {:?}\" {} \"{}\" \"{}\" {:?}",
                OptFmt(info.remote_addr()),
                info.method(),
                info.path(),
                info.version(),
                info.status().as_u16(),
                OptFmt(info.referer()),
                OptFmt(info.user_agent()),
                info.elapsed(),
            )
        }))
        .with(warp::cors().allow_any_origin().allow_methods(vec!["POST"]))
}

//
// Common Types
//

struct OptFmt<T>(Option<T>);

impl<T: fmt::Display> fmt::Display for OptFmt<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(t) = &self.0 {
            fmt::Display::fmt(t, f)
        } else {
            f.write_str("-")
        }
    }
}
<commit_msg>faucet: add create-account route<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! This crates provides Faucet service for creating Testnet with simplified on-chain account creation
//! and minting coins.
//!
//! THIS SERVICE SHOULD NEVER BE DEPLOYED TO MAINNET.
//!
//! ## Launch service
//!
//! Launch faucet service local and connect to Testnet:
//!
//! ```bash
//! cargo run -p diem-faucet -- -a 127.0.0.1 -p 8080 -c TESTNET \
//!     -m <treasury-compliance-private-key-path> -s https://testnet.diem.com/v1
//! ```
//!
//! Check help doc for options details:
//!
//! ```bash
//! cargo run -p diem-faucet -- -h
//! ```
//!
//! ## Development
//!
//! Test with diem-swarm by add -m option:
//!
//! ```bash
//! cargo run -p diem-swarm -- -s -l -n 1 -m
//! ```
//!

use anyhow::{anyhow, Result};
use diem_logger::info;
use diem_sdk::{
    client::{Client, SignedTransaction},
    transaction_builder::{Currency, TransactionFactory},
    types::{chain_id::ChainId, transaction::authenticator::AuthenticationKey, LocalAccount},
};
use reqwest::StatusCode;
use serde::Deserialize;
use std::{
    convert::Infallible,
    fmt,
    sync::{Arc, Mutex},
};
use warp::{Filter, Rejection, Reply};

pub mod mint;

pub struct Service {
    treasury_compliance_account: Mutex<LocalAccount>,
    designated_dealer_account: Mutex<LocalAccount>,
    transaction_factory: TransactionFactory,
    client: Client,
}

impl Service {
    pub fn new(
        jsonrpc_endpoint: String,
        chain_id: ChainId,
        treasury_compliance_account: LocalAccount,
        designated_dealer_account: LocalAccount,
    ) -> Self {
        let client = Client::new(jsonrpc_endpoint);
        Service {
            treasury_compliance_account: Mutex::new(treasury_compliance_account),
            designated_dealer_account: Mutex::new(designated_dealer_account),
            transaction_factory: TransactionFactory::new(chain_id)
                .with_transaction_expiration_time(30),
            client,
        }
    }
}

pub fn routes(
    service: Arc<Service>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
    let mint = mint::mint_routes(service.clone());
    let create_account = create_account_route(service);
    let health = warp::path!("-" / "healthy").map(|| "diem-faucet:ok");

    health
        .or(mint)
        .or(create_account)
        .with(warp::log::custom(|info| {
            info!(
                "{} \"{} {} {:?}\" {} \"{}\" \"{}\" {:?}",
                OptFmt(info.remote_addr()),
                info.method(),
                info.path(),
                info.version(),
                info.status().as_u16(),
                OptFmt(info.referer()),
                OptFmt(info.user_agent()),
                info.elapsed(),
            )
        }))
        .with(warp::cors().allow_any_origin().allow_methods(vec!["POST"]))
}

#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
struct CreateAccountParams {
    authentication_key: AuthenticationKey,
}

fn create_account_route(
    service: Arc<Service>,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
    warp::path::path("accounts")
        .and(warp::post())
        .and(warp::any().map(move || service.clone()))
        .and(warp::query().map(move |params: CreateAccountParams| params))
        .and_then(handle_create_account)
}

async fn handle_create_account(
    service: Arc<Service>,
    params: CreateAccountParams,
) -> Result<Box<dyn warp::Reply>, Infallible> {
    match create_account(service, params).await {
        Ok(txn) => Ok(Box::new(hex::encode(bcs::to_bytes(&txn).unwrap()))),
        Err(err) => Ok(Box::new(warp::reply::with_status(
            err.to_string(),
            StatusCode::INTERNAL_SERVER_ERROR,
        ))),
    }
}

async fn create_account(
    service: Arc<Service>,
    params: CreateAccountParams,
) -> Result<SignedTransaction> {
    // Check to ensure the account hasn't already been created
    if service
        .client
        .get_account(params.authentication_key.derived_address())
        .await?
        .into_inner()
        .is_some()
    {
        return Err(anyhow!("account already exists"));
    }

    // get TC account's sequence number
    let tc_account_address = service
        .treasury_compliance_account
        .lock()
        .unwrap()
        .address();
    let tc_sequence_number = service
        .client
        .get_account(tc_account_address)
        .await?
        .into_inner()
        .ok_or_else(|| anyhow::format_err!("treasury compliance account not found"))?
        .sequence_number;

    let txn = {
        let mut treasury_account = service.treasury_compliance_account.lock().unwrap();
        if tc_sequence_number > treasury_account.sequence_number() {
            *treasury_account.sequence_number_mut() = tc_sequence_number;
        }

        let builder = service.transaction_factory.create_parent_vasp_account(
            Currency::XUS,
            0, // sliding_nonce
            params.authentication_key,
            &format!("No. {}", treasury_account.sequence_number()),
            false, // add all currencies
        );

        treasury_account.sign_with_transaction_builder(builder)
    };

    service.client.submit(&txn).await?;
    Ok(txn)
}

//
// Common Types
//

struct OptFmt<T>(Option<T>);

impl<T: fmt::Display> fmt::Display for OptFmt<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(t) = &self.0 {
            fmt::Display::fmt(t, f)
        } else {
            f.write_str("-")
        }
    }
}
<|endoftext|>


<commit_before>use ruma_identifiers::{RoomAliasId, RoomId};

#[allow(unused)]
#[derive(Copy, Clone, Debug, ruma_api::Outgoing, serde::Serialize)]
pub struct OtherThing<'t> {
    some: &'t str,
    t: &'t [u8],
}

mod empty_response {
    use super::*;

    ruma_api::ruma_api! {
        metadata: {
            description: "Add an alias to a room.",
            method: PUT,
            name: "create_alias",
            path: "/_matrix/client/r0/directory/room/:room_alias",
            rate_limited: false,
            requires_authentication: true,
        }

        request: {
            /// The room alias to set.
            #[ruma_api(path)]
            pub room_alias: &'a RoomAliasId,

            /// The room ID to set.
            pub room_id: &'a RoomId,
        }

        response: {}
    }
}

mod nested_types {
    use super::*;

    ruma_api::ruma_api! {
        metadata: {
            description: "Add an alias to a room.",
            method: PUT,
            name: "create_alias",
            path: "/_matrix/client/r0/directory/room/:room_alias",
            rate_limited: false,
            requires_authentication: true,
        }

        request: {
            /// The room alias to set.
            pub room_alias: &'a [Option<&'a RoomAliasId>],

            /// The room ID to set.
            pub room_id: &'b [Option<Option<&'a ruma_identifiers::DeviceId>>],
        }

        response: {}
    }
}

mod full_request_response {
    use super::*;

    ruma_api::ruma_api! {
        metadata: {
            description: "Does something.",
            method: POST,
            name: "no_fields",
            path: "/_matrix/my/endpoint/:thing",
            rate_limited: false,
            requires_authentication: false,
        }

        request: {
            #[ruma_api(query)]
            pub abc: &'a str,
            #[ruma_api(path)]
            pub thing: &'a str,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
            pub more: OtherThing<'t>,
        }

        response: {
            #[ruma_api(body)]
            pub thing: OtherThing<'a>,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }
    }
}

mod full_request_response_with_query_map {
    use super::*;

    ruma_api::ruma_api! {
        metadata: {
            description: "Does something.",
            method: GET,
            name: "no_fields",
            path: "/_matrix/my/endpoint/:thing",
            rate_limited: false,
            requires_authentication: false,
        }

        request: {
            #[ruma_api(query_map)]
            // pub abc: &'a [(&'a str, &'a str)], // TODO handle this use case
            pub abc: Vec<(String, String)>,
            #[ruma_api(path)]
            pub thing: &'a str,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }

        response: {
            #[ruma_api(body)]
            pub thing: OtherThing<'a>,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }
    }
}

mod query_fields {
    ruma_api::ruma_api! {
        metadata: {
            description: "Get the list of rooms in this homeserver's public directory.",
            method: GET,
            name: "get_public_rooms",
            path: "/_matrix/client/r0/publicRooms",
            rate_limited: false,
            requires_authentication: false,
        }

        request: {
            /// Limit for the number of results to return.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub limit: Option<usize>,

            /// Pagination token from a previous request.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub since: Option<&'a str>,

            /// The server to fetch the public room lists from.
            ///
            /// `None` means the server this request is sent to.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub server: Option<&'a str>,
        }

        response: { }
    }
}
<commit_msg>Don't use * imports in ruma_api_lifetime test<commit_after>#[allow(unused)]
#[derive(Copy, Clone, Debug, ruma_api::Outgoing, serde::Serialize)]
pub struct OtherThing<'t> {
    some: &'t str,
    t: &'t [u8],
}

mod empty_response {
    use ruma_api::ruma_api;
    use ruma_identifiers::{RoomAliasId, RoomId};

    ruma_api! {
        metadata: {
            description: "Add an alias to a room.",
            method: PUT,
            name: "create_alias",
            path: "/_matrix/client/r0/directory/room/:room_alias",
            rate_limited: false,
            requires_authentication: true,
        }

        request: {
            /// The room alias to set.
            #[ruma_api(path)]
            pub room_alias: &'a RoomAliasId,

            /// The room ID to set.
            pub room_id: &'a RoomId,
        }

        response: {}
    }
}

mod nested_types {
    use ruma_api::ruma_api;
    use ruma_identifiers::RoomAliasId;

    ruma_api! {
        metadata: {
            description: "Add an alias to a room.",
            method: PUT,
            name: "create_alias",
            path: "/_matrix/client/r0/directory/room/:room_alias",
            rate_limited: false,
            requires_authentication: true,
        }

        request: {
            /// The room alias to set.
            pub room_alias: &'a [Option<&'a RoomAliasId>],

            /// The room ID to set.
            pub room_id: &'b [Option<Option<&'a ruma_identifiers::DeviceId>>],
        }

        response: {}
    }
}

mod full_request_response {
    use ruma_api::ruma_api;

    use super::{IncomingOtherThing, OtherThing};

    ruma_api! {
        metadata: {
            description: "Does something.",
            method: POST,
            name: "no_fields",
            path: "/_matrix/my/endpoint/:thing",
            rate_limited: false,
            requires_authentication: false,
        }

        request: {
            #[ruma_api(query)]
            pub abc: &'a str,
            #[ruma_api(path)]
            pub thing: &'a str,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
            pub more: OtherThing<'t>,
        }

        response: {
            #[ruma_api(body)]
            pub thing: OtherThing<'a>,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }
    }
}

mod full_request_response_with_query_map {
    use ruma_api::ruma_api;

    use super::{IncomingOtherThing, OtherThing};

    ruma_api! {
        metadata: {
            description: "Does something.",
            method: GET,
            name: "no_fields",
            path: "/_matrix/my/endpoint/:thing",
            rate_limited: false,
            requires_authentication: false,
        }

        request: {
            #[ruma_api(query_map)]
            // pub abc: &'a [(&'a str, &'a str)], // TODO handle this use case
            pub abc: Vec<(String, String)>,
            #[ruma_api(path)]
            pub thing: &'a str,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }

        response: {
            #[ruma_api(body)]
            pub thing: OtherThing<'a>,
            #[ruma_api(header = CONTENT_TYPE)]
            pub stuff: &'a str,
        }
    }
}

mod query_fields {
    use ruma_api::ruma_api;

    ruma_api! {
        metadata: {
            description: "Get the list of rooms in this homeserver's public directory.",
            method: GET,
            name: "get_public_rooms",
            path: "/_matrix/client/r0/publicRooms",
            rate_limited: false,
            requires_authentication: false,
        }

        request: {
            /// Limit for the number of results to return.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub limit: Option<usize>,

            /// Pagination token from a previous request.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub since: Option<&'a str>,

            /// The server to fetch the public room lists from.
            ///
            /// `None` means the server this request is sent to.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub server: Option<&'a str>,
        }

        response: { }
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate tempfile;
#[macro_use]
extern crate wayland_client;
#[macro_use]
extern crate wlroots;

use std::thread;
use std::time::Duration;

use wlroots::{matrix_mul, matrix_rotate, matrix_scale, matrix_translate, Area, Compositor,
              CompositorBuilder, CursorBuilder, InputManagerHandler, Keyboard, KeyboardHandler,
              Origin, Output, OutputBuilder, OutputBuilderResult, OutputHandler, OutputLayout,
              OutputManagerHandler, Pointer, PointerHandler, Renderer, Seat, SeatHandler, Size,
              Surface, WlShellHandler, WlShellManagerHandler, WlShellSurface,
              WlShellSurfaceHandle, XCursorTheme};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{AxisEvent, ButtonEvent, MotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

struct State {
    color: [f32; 4],
    default_color: [f32; 4],
    xcursor_theme: XCursorTheme,
    layout: OutputLayout,
    shells: Vec<WlShellSurfaceHandle>
}

impl State {
    fn new(xcursor_theme: XCursorTheme, layout: OutputLayout) -> Self {
        State { color: [0.25, 0.25, 0.25, 1.0],
                default_color: [0.25, 0.25, 0.25, 1.0],
                xcursor_theme,
                layout,
                shells: vec![] }
    }
}

compositor_data!(State);

struct SeatHandlerEx;

impl SeatHandler for SeatHandlerEx {
    // TODO
}

struct WlShellHandlerEx;
struct WlShellManager;

impl WlShellHandler for WlShellHandlerEx {}
impl WlShellManagerHandler for WlShellManager {
    fn new_surface(&mut self,
                   compositor: &mut Compositor,
                   shell: &mut WlShellSurface,
                   _: &mut Surface)
                   -> Option<Box<WlShellHandler>> {
        let state: &mut State = compositor.into();
        state.shells.push(shell.weak_reference());
        Some(Box::new(WlShellHandlerEx))
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let result = builder.build_best_mode(ExOutput);
        let state: &mut State = compositor.into();
        let xcursor = state.xcursor_theme
                           .get_cursor("left_ptr".into())
                           .expect("Could not load left_ptr cursor");
        let image = &xcursor.images()[0];
        // TODO use output config if present instead of auto
        state.layout.add_auto(result.output);
        let cursor = &mut state.layout.cursors()[0];
        cursor.set_cursor_image(image);
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self, compositor: &mut Compositor, _: &mut Keyboard, key_event: &mut KeyEvent) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor.terminate()
            }
            // TODO This is a dumb way to compare these values
            else if key_event.key_state() as u32 == 1 {
                thread::spawn(move || {
                    use byteorder::{NativeEndian, WriteBytesExt};
                    use std::cmp::min;
                    use std::io::Write;
                    use std::os::unix::io::AsRawFd;
                    use wayland_client::EnvHandler;
                    use wayland_client::protocol::{wl_compositor, wl_pointer, wl_seat, wl_shell,
                                                   wl_shell_surface, wl_shm};

                    wayland_env!(WaylandEnv,
                                 compositor: wl_compositor::WlCompositor,
                                 seat: wl_seat::WlSeat,
                                 shell: wl_shell::WlShell,
                                 shm: wl_shm::WlShm);

                    fn pointer_impl() -> wl_pointer::Implementation<()> {
                        wl_pointer::Implementation {
                            enter: |_, _, _pointer, _serial, _surface, x, y| {
                                println!("Pointer entered surface at ({},{}).", x, y);
                            },
                            leave: |_, _, _pointer, _serial, _surface| {
                                println!("Pointer left surface.");
                            },
                            motion: |_, _, _pointer, _time, x, y| {
                                println!("Pointer moved to ({},{}).", x, y);
                            },
                            button: |_, _, _pointer, _serial, _time, button, state| {
                                println!(
                                    "Button {} ({}) was {:?}.",
                                    match button {
                                        272 => "Left",
                                        273 => "Right",
                                        274 => "Middle",
                                        _ => "Unknown",
                                    },
                                    button,
                                    state
                                );
                            },
                            axis: |_, _, _, _, _, _| { /* not used in this example */ },
                            frame: |_, _, _| { /* not used in this example */ },
                            axis_source: |_, _, _, _| { /* not used in this example */ },
                            axis_discrete: |_, _, _, _, _| { /* not used in this example */ },
                            axis_stop: |_, _, _, _, _| { /* not used in this example */ },
                        }
                    }

                    fn shell_surface_impl() -> wl_shell_surface::Implementation<()> {
                        wl_shell_surface::Implementation { ping: |_, _, shell_surface, serial| {
                                                               shell_surface.pong(serial);
                                                           },
                                                           configure: |_, _, _, _, _, _| {
                                                               /* not used in this example */
                                                           },
                                                           popup_done: |_, _, _| {
                                                               /* not used in this example */
                                                           } }
                    }

                    let (display, mut event_queue) = match wayland_client::default_connect() {
                        Ok(ret) => ret,
                        Err(e) => panic!("Cannot connect to wayland server: {:?}", e)
                    };

                    let registry = display.get_registry();

                    let env_token = EnvHandler::<WaylandEnv>::init(&mut event_queue, &registry);

                    event_queue.sync_roundtrip().unwrap();

                    // buffer (and window) width and height
                    let buf_x: u32 = 320;
                    let buf_y: u32 = 240;

                    // create a tempfile to write the conents of the window on
                    let mut tmp = tempfile::tempfile().ok()
                                                      .expect("Unable to create a tempfile.");
                    // write the contents to it, lets put a nice color gradient
                    for i in 0..(buf_x * buf_y) {
                        let x = (i % buf_x) as u32;
                        let y = (i / buf_x) as u32;
                        let r: u32 =
                            min(((buf_x - x) * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let g: u32 = min((x * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let b: u32 = min(((buf_x - x) * 0xFF) / buf_x, (y * 0xFF) / buf_y);
                        let _ =
                            tmp.write_u32::<NativeEndian>((0xFF << 24) + (r << 16) + (g << 8) + b);
                    }
                    let _ = tmp.flush();

                    // retrieve the env
                    let env = event_queue.state().get(&env_token).clone_inner().unwrap();

                    // prepare the wayland surface
                    let surface = env.compositor.create_surface();
                    let shell_surface = env.shell.get_shell_surface(&surface);

                    let pool = env.shm.create_pool(tmp.as_raw_fd(), (buf_x * buf_y * 4) as i32);
                    // match a buffer on the part we wrote on
                    let buffer = pool.create_buffer(
                        0,
                        buf_x as i32,
                        buf_y as i32,
                        (buf_x * 4) as i32,
                        wl_shm::Format::Argb8888,
                    ).expect("The pool cannot be already dead");

                    // make our surface as a toplevel one
                    shell_surface.set_toplevel();
                    // attach the buffer to it
                    surface.attach(Some(&buffer), 0, 0);
                    // commit
                    surface.commit();

                    let pointer = env.seat.get_pointer()
                                     .expect("Seat cannot be already destroyed.");

                    event_queue.register(&shell_surface, shell_surface_impl(), ());
                    event_queue.register(&pointer, pointer_impl(), ());

                    loop {
                        display.flush().unwrap();
                        event_queue.dispatch().unwrap();
                    }
                });
            }
        }
    }
}

impl PointerHandler for ExPointer {
    fn on_motion(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &MotionEvent) {
        let state: &mut State = compositor.into();
        let (delta_x, delta_y) = event.delta();
        state.layout.cursors()[0].move_to(event.device(), delta_x, delta_y);
    }

    fn on_button(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &ButtonEvent) {
        let state: &mut State = compositor.into();
        if event.state() == WLR_BUTTON_RELEASED {
            state.color = state.default_color;
        } else {
            state.color = [0.25, 0.25, 0.25, 1.0];
            state.color[event.button() as usize % 3] = 1.0;
        }
    }

    fn on_axis(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &AxisEvent) {
        let state: &mut State = compositor.into();
        for color_byte in &mut state.default_color[..3] {
            *color_byte += if event.delta() > 0.0 { -0.05 } else { 0.05 };
            if *color_byte > 1.0 {
                *color_byte = 1.0
            }
            if *color_byte < 0.0 {
                *color_byte = 0.0
            }
        }
        state.color = state.default_color.clone()
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: &mut Compositor, output: &mut Output) {
        let renderer = compositor.renderer
                                 .as_mut()
                                 .expect("Compositor was not loaded with a renderer");
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        render_shells(state, &mut renderer.render(output));
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: &mut Compositor,
                     _: &mut Pointer)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut Keyboard)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let cursor = CursorBuilder::new().expect("Could not create cursor");
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let mut layout = OutputLayout::new().expect("Could not construct an output layout");

    layout.attach_cursor(cursor);
    let mut compositor = CompositorBuilder::new().gles2(true)
                                                 .build_auto(State::new(xcursor_theme, layout),
                                                             Some(Box::new(InputManager)),
                                                             Some(Box::new(OutputManager)),
                                                             Some(Box::new(WlShellManager)));
    Seat::create(&mut compositor, "Main Seat".into(), Box::new(SeatHandlerEx))
        .expect("Could not allocate the global seat");
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        shell.run(|shell| {
                      shell.surface()
                           .run(|surface| {
                                    let (width, height) = {
                                        let current_state = surface.current_state();
                                        (current_state.width() as i32,
                                        current_state.height() as i32)
                                    };
                                    let (render_width, render_height) =
                                        (width * renderer.output.scale() as i32,
                                        height * renderer.output.scale() as i32);
                                    // TODO Some value from something else?
                                    let (lx, ly) = (0.0, 0.0);
                                    let (mut ox, mut oy) = (lx, ly);
                                    state.layout
                                         .output_coords(renderer.output, &mut ox, &mut oy);
                                    ox *= renderer.output.scale() as f64;
                                    oy *= renderer.output.scale() as f64;
                                    let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                                               Size::new(render_width,
                                                                         render_height));
                                    if state.layout.intersects(renderer.output, render_box) {
                                        let mut matrix = [0.0; 16];
                                        let mut translate_center = [0.0; 16];
                                        matrix_translate(&mut translate_center,
                                                         (ox as i32 + render_width / 2) as f32,
                                                         (oy as i32 + render_height / 2) as f32,
                                                         0.0);
                                        let mut rotate = [0.0; 16];
                                        // TODO what is rotation
                                        let rotation = 0.0;
                                        matrix_rotate(&mut rotate, rotation);

                                        let mut translate_origin = [0.0; 16];
                                        matrix_translate(&mut translate_origin,
                                                         (-render_width / 2) as f32,
                                                         (-render_height / 2) as f32,
                                                         0.0);

                                        let mut scale = [0.0; 16];
                                        matrix_scale(&mut scale,
                                                     render_width as f32,
                                                     render_height as f32,
                                                     1.0);

                                        let mut transform = [0.0; 16];
                                        matrix_mul(&translate_center, &mut rotate, &mut transform);
                                        matrix_mul(&transform.clone(),
                                                   &mut translate_origin,
                                                   &mut transform);
                                        matrix_mul(&transform.clone(), &mut scale, &mut transform);

                                        // TODO Handle non transform normal on the output
                                        // if ... {}
                                        matrix_mul(&renderer.output.transform_matrix(),
                                                   &mut transform,
                                                   &mut matrix);
                                        renderer.render_with_matrix(&surface.texture(), &matrix);
                                        surface.send_frame_done(Duration::from_secs(1));
                                    }
                                })
                           .unwrap()
                  })
             .unwrap();
    }
}
<commit_msg>Only render when there's shit to render.<commit_after>extern crate byteorder;
extern crate tempfile;
#[macro_use]
extern crate wayland_client;
#[macro_use]
extern crate wlroots;

use std::thread;
use std::time::Duration;

use wlroots::{matrix_mul, matrix_rotate, matrix_scale, matrix_translate, Area, Compositor,
              CompositorBuilder, CursorBuilder, InputManagerHandler, Keyboard, KeyboardHandler,
              Origin, Output, OutputBuilder, OutputBuilderResult, OutputHandler, OutputLayout,
              OutputManagerHandler, Pointer, PointerHandler, Renderer, Seat, SeatHandler, Size,
              Surface, WlShellHandler, WlShellManagerHandler, WlShellSurface,
              WlShellSurfaceHandle, XCursorTheme};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{AxisEvent, ButtonEvent, MotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

struct State {
    color: [f32; 4],
    default_color: [f32; 4],
    xcursor_theme: XCursorTheme,
    layout: OutputLayout,
    shells: Vec<WlShellSurfaceHandle>
}

impl State {
    fn new(xcursor_theme: XCursorTheme, layout: OutputLayout) -> Self {
        State { color: [0.25, 0.25, 0.25, 1.0],
                default_color: [0.25, 0.25, 0.25, 1.0],
                xcursor_theme,
                layout,
                shells: vec![] }
    }
}

compositor_data!(State);

struct SeatHandlerEx;

impl SeatHandler for SeatHandlerEx {
    // TODO
}

struct WlShellHandlerEx;
struct WlShellManager;

impl WlShellHandler for WlShellHandlerEx {}
impl WlShellManagerHandler for WlShellManager {
    fn new_surface(&mut self,
                   compositor: &mut Compositor,
                   shell: &mut WlShellSurface,
                   _: &mut Surface)
                   -> Option<Box<WlShellHandler>> {
        let state: &mut State = compositor.into();
        state.shells.push(shell.weak_reference());
        for (mut output, _) in state.layout.outputs() {
            output.run(|output| output.schedule_frame()).unwrap();
        }
        Some(Box::new(WlShellHandlerEx))
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let result = builder.build_best_mode(ExOutput);
        let state: &mut State = compositor.into();
        let xcursor = state.xcursor_theme
                           .get_cursor("left_ptr".into())
                           .expect("Could not load left_ptr cursor");
        let image = &xcursor.images()[0];
        // TODO use output config if present instead of auto
        state.layout.add_auto(result.output);
        let cursor = &mut state.layout.cursors()[0];
        cursor.set_cursor_image(image);
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self, compositor: &mut Compositor, _: &mut Keyboard, key_event: &mut KeyEvent) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor.terminate()
            }
            // TODO This is a dumb way to compare these values
            else if key_event.key_state() as u32 == 1 {
                thread::spawn(move || {
                    use byteorder::{NativeEndian, WriteBytesExt};
                    use std::cmp::min;
                    use std::io::Write;
                    use std::os::unix::io::AsRawFd;
                    use wayland_client::EnvHandler;
                    use wayland_client::protocol::{wl_compositor, wl_pointer, wl_seat, wl_shell,
                                                   wl_shell_surface, wl_shm};

                    wayland_env!(WaylandEnv,
                                 compositor: wl_compositor::WlCompositor,
                                 seat: wl_seat::WlSeat,
                                 shell: wl_shell::WlShell,
                                 shm: wl_shm::WlShm);

                    fn pointer_impl() -> wl_pointer::Implementation<()> {
                        wl_pointer::Implementation {
                            enter: |_, _, _pointer, _serial, _surface, x, y| {
                                println!("Pointer entered surface at ({},{}).", x, y);
                            },
                            leave: |_, _, _pointer, _serial, _surface| {
                                println!("Pointer left surface.");
                            },
                            motion: |_, _, _pointer, _time, x, y| {
                                println!("Pointer moved to ({},{}).", x, y);
                            },
                            button: |_, _, _pointer, _serial, _time, button, state| {
                                println!(
                                    "Button {} ({}) was {:?}.",
                                    match button {
                                        272 => "Left",
                                        273 => "Right",
                                        274 => "Middle",
                                        _ => "Unknown",
                                    },
                                    button,
                                    state
                                );
                            },
                            axis: |_, _, _, _, _, _| { /* not used in this example */ },
                            frame: |_, _, _| { /* not used in this example */ },
                            axis_source: |_, _, _, _| { /* not used in this example */ },
                            axis_discrete: |_, _, _, _, _| { /* not used in this example */ },
                            axis_stop: |_, _, _, _, _| { /* not used in this example */ },
                        }
                    }

                    fn shell_surface_impl() -> wl_shell_surface::Implementation<()> {
                        wl_shell_surface::Implementation { ping: |_, _, shell_surface, serial| {
                                                               shell_surface.pong(serial);
                                                           },
                                                           configure: |_, _, _, _, _, _| {
                                                               /* not used in this example */
                                                           },
                                                           popup_done: |_, _, _| {
                                                               /* not used in this example */
                                                           } }
                    }

                    let (display, mut event_queue) = match wayland_client::default_connect() {
                        Ok(ret) => ret,
                        Err(e) => panic!("Cannot connect to wayland server: {:?}", e)
                    };

                    let registry = display.get_registry();

                    let env_token = EnvHandler::<WaylandEnv>::init(&mut event_queue, &registry);

                    event_queue.sync_roundtrip().unwrap();

                    // buffer (and window) width and height
                    let buf_x: u32 = 320;
                    let buf_y: u32 = 240;

                    // create a tempfile to write the conents of the window on
                    let mut tmp = tempfile::tempfile().ok()
                                                      .expect("Unable to create a tempfile.");
                    // write the contents to it, lets put a nice color gradient
                    for i in 0..(buf_x * buf_y) {
                        let x = (i % buf_x) as u32;
                        let y = (i / buf_x) as u32;
                        let r: u32 =
                            min(((buf_x - x) * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let g: u32 = min((x * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let b: u32 = min(((buf_x - x) * 0xFF) / buf_x, (y * 0xFF) / buf_y);
                        let _ =
                            tmp.write_u32::<NativeEndian>((0xFF << 24) + (r << 16) + (g << 8) + b);
                    }
                    let _ = tmp.flush();

                    // retrieve the env
                    let env = event_queue.state().get(&env_token).clone_inner().unwrap();

                    // prepare the wayland surface
                    let surface = env.compositor.create_surface();
                    let shell_surface = env.shell.get_shell_surface(&surface);

                    let pool = env.shm.create_pool(tmp.as_raw_fd(), (buf_x * buf_y * 4) as i32);
                    // match a buffer on the part we wrote on
                    let buffer = pool.create_buffer(
                        0,
                        buf_x as i32,
                        buf_y as i32,
                        (buf_x * 4) as i32,
                        wl_shm::Format::Argb8888,
                    ).expect("The pool cannot be already dead");

                    // make our surface as a toplevel one
                    shell_surface.set_toplevel();
                    // attach the buffer to it
                    surface.attach(Some(&buffer), 0, 0);
                    // commit
                    surface.commit();

                    let pointer = env.seat.get_pointer()
                                     .expect("Seat cannot be already destroyed.");

                    event_queue.register(&shell_surface, shell_surface_impl(), ());
                    event_queue.register(&pointer, pointer_impl(), ());

                    loop {
                        display.flush().unwrap();
                        event_queue.dispatch().unwrap();
                    }
                });
            }
        }
    }
}

impl PointerHandler for ExPointer {
    fn on_motion(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &MotionEvent) {
        let state: &mut State = compositor.into();
        let (delta_x, delta_y) = event.delta();
        state.layout.cursors()[0].move_to(event.device(), delta_x, delta_y);
    }

    fn on_button(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &ButtonEvent) {
        let state: &mut State = compositor.into();
        if event.state() == WLR_BUTTON_RELEASED {
            state.color = state.default_color;
        } else {
            state.color = [0.25, 0.25, 0.25, 1.0];
            state.color[event.button() as usize % 3] = 1.0;
        }
    }

    fn on_axis(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &AxisEvent) {
        let state: &mut State = compositor.into();
        for color_byte in &mut state.default_color[..3] {
            *color_byte += if event.delta() > 0.0 { -0.05 } else { 0.05 };
            if *color_byte > 1.0 {
                *color_byte = 1.0
            }
            if *color_byte < 0.0 {
                *color_byte = 0.0
            }
        }
        state.color = state.default_color.clone()
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: &mut Compositor, output: &mut Output) {
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        if state.shells.len() < 1 {
            return
        }
        let renderer = compositor.renderer
            .as_mut()
            .expect("Compositor was not loaded with a renderer");
        render_shells(state, &mut renderer.render(output));
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: &mut Compositor,
                     _: &mut Pointer)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut Keyboard)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let cursor = CursorBuilder::new().expect("Could not create cursor");
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let mut layout = OutputLayout::new().expect("Could not construct an output layout");

    layout.attach_cursor(cursor);
    let mut compositor = CompositorBuilder::new().gles2(true)
                                                 .build_auto(State::new(xcursor_theme, layout),
                                                             Some(Box::new(InputManager)),
                                                             Some(Box::new(OutputManager)),
                                                             Some(Box::new(WlShellManager)));
    Seat::create(&mut compositor, "Main Seat".into(), Box::new(SeatHandlerEx))
        .expect("Could not allocate the global seat");
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        shell.run(|shell| {
                      shell.surface()
                           .run(|surface| {
                                    let (width, height) = {
                                        let current_state = surface.current_state();
                                        (current_state.width() as i32,
                                        current_state.height() as i32)
                                    };
                                    let (render_width, render_height) =
                                        (width * renderer.output.scale() as i32,
                                        height * renderer.output.scale() as i32);
                                    // TODO Some value from something else?
                                    let (lx, ly) = (0.0, 0.0);
                                    let (mut ox, mut oy) = (lx, ly);
                                    state.layout
                                         .output_coords(renderer.output, &mut ox, &mut oy);
                                    ox *= renderer.output.scale() as f64;
                                    oy *= renderer.output.scale() as f64;
                                    let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                                               Size::new(render_width,
                                                                         render_height));
                                    if state.layout.intersects(renderer.output, render_box) {
                                        let mut matrix = [0.0; 16];
                                        let mut translate_center = [0.0; 16];
                                        matrix_translate(&mut translate_center,
                                                         (ox as i32 + render_width / 2) as f32,
                                                         (oy as i32 + render_height / 2) as f32,
                                                         0.0);
                                        let mut rotate = [0.0; 16];
                                        // TODO what is rotation
                                        let rotation = 0.0;
                                        matrix_rotate(&mut rotate, rotation);

                                        let mut translate_origin = [0.0; 16];
                                        matrix_translate(&mut translate_origin,
                                                         (-render_width / 2) as f32,
                                                         (-render_height / 2) as f32,
                                                         0.0);

                                        let mut scale = [0.0; 16];
                                        matrix_scale(&mut scale,
                                                     render_width as f32,
                                                     render_height as f32,
                                                     1.0);

                                        let mut transform = [0.0; 16];
                                        matrix_mul(&translate_center, &mut rotate, &mut transform);
                                        matrix_mul(&transform.clone(),
                                                   &mut translate_origin,
                                                   &mut transform);
                                        matrix_mul(&transform.clone(), &mut scale, &mut transform);

                                        // TODO Handle non transform normal on the output
                                        // if ... {}
                                        matrix_mul(&renderer.output.transform_matrix(),
                                                   &mut transform,
                                                   &mut matrix);
                                        renderer.render_with_matrix(&surface.texture(), &matrix);
                                        surface.send_frame_done(Duration::from_secs(1));
                                    }
                                })
                           .unwrap()
                  })
             .unwrap();
    }
}
<|endoftext|>


<commit_before>pub fn reverse(input: &str) -> String {
    let mut output = String::with_capacity(input.len());
    output.extend(input.chars().rev());
    output
}
<commit_msg>reverse-string: Use a shorter example (#807)<commit_after>pub fn reverse(input: &str) -> String {
    input.chars().rev().collect()
}
<|endoftext|>


<commit_before>//@compile-flags: -Zmiri-retag-fields
fn main() {
    let array = [(); usize::MAX];
    drop(array); // Pass the array to a function, retagging its fields
}
<commit_msg>clarify test purpose<commit_after>//@compile-flags: -Zmiri-retag-fields
// Checks that the test does not run forever (which relies on a fast path).
fn main() {
    let array = [(); usize::MAX];
    drop(array); // Pass the array to a function, retagging its fields
}
<|endoftext|>