<commit_before>#![feature(io, std_misc, path)]
#![cfg_attr(test, feature(fs))]

extern crate libc;

use std::ffi::AsOsStr;
use std::mem;
use std::path::AsPath;
use std::os::unix::{Fd, OsStrExt, AsRawFd};
use std::io;
use std::num::Int;
use std::cmp;

struct Inner(Fd);

impl Drop for Inner {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.0);
        }
    }
}

impl Inner {
    unsafe fn new() -> io::Result<Inner> {
        let fd = libc::socket(libc::AF_UNIX, libc::SOCK_STREAM, 0);
        if fd < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(Inner(fd))
        }
    }

}

unsafe fn sockaddr_un<P: AsPath + ?Sized>(path: &P) -> io::Result<libc::sockaddr_un> {
    let mut addr: libc::sockaddr_un = mem::zeroed();
    addr.sun_family = libc::AF_UNIX as libc::sa_family_t;

    let bytes = path.as_path().as_os_str().as_bytes();
    if bytes.len() > addr.sun_path.len() - 1 {
        return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                  "path must be smaller than SUN_LEN",
                                  None));
    }
    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
        *dst = *src as libc::c_char;
    }
    // null byte's already there because we zeroed the struct

    Ok(addr)
}

pub struct UnixStream {
    inner: Inner,
}

impl UnixStream {
    pub fn connect<P: AsPath + ?Sized>(path: &P) -> io::Result<UnixStream> {
        unsafe {
            let inner = try!(Inner::new());
            let addr = try!(sockaddr_un(path));

            let ret = libc::connect(inner.0,
                                    &addr as *const _ as *const _,
                                    mem::size_of::<libc::sockaddr_un>() as libc::socklen_t);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixStream {
                    inner: inner,
                })
            }
        }
    }
}

fn calc_len(buf: &[u8]) -> libc::size_t {
    cmp::min(<libc::size_t as Int>::max_value() as usize, buf.len()) as libc::size_t
}

impl io::Read for UnixStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = unsafe {
            libc::recv(self.inner.0, buf.as_mut_ptr() as *mut _, calc_len(buf), 0)
        };

        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret as usize)
        }
    }
}

impl io::Write for UnixStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let ret = unsafe {
            libc::send(self.inner.0, buf.as_ptr() as *const _, calc_len(buf), 0)
        };

        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret as usize)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl AsRawFd for UnixStream {
    fn as_raw_fd(&self) -> Fd {
        self.inner.0
    }
}

pub struct UnixListener {
    inner: Inner,
}

impl UnixListener {
    pub fn bind<P: AsPath + ?Sized>(path: &P) -> io::Result<UnixListener> {
        unsafe {
            let inner = try!(Inner::new());
            let addr = try!(sockaddr_un(path));

            let ret = libc::bind(inner.0,
                                 &addr as *const _ as *const _,
                                 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t);
            if ret < 0 {
                return Err(io::Error::last_os_error());
            }

            let ret = libc::listen(inner.0, 128);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixListener {
                    inner: inner,
                })
            }
        }
    }

    pub fn accept(&self) -> io::Result<UnixStream> {
        unsafe {
            let ret = libc::accept(self.inner.0, 0 as *mut _, 0 as *mut _);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixStream {
                    inner: Inner(ret)
                })
            }
        }
    }
}

impl AsRawFd for UnixListener {
    fn as_raw_fd(&self) -> Fd {
        self.inner.0
    }
}

#[cfg(test)]
mod test {
    use std::fs;
    use std::thread;
    use std::path::Path;
    use std::io::prelude::*;

    use {UnixListener, UnixStream};

    macro_rules! or_panic {
        ($e:expr) => {
            match $e {
                Ok(e) => e,
                Err(e) => panic!("{}", e),
            }
        }
    }

    #[test]
    fn test_basic() {
        let socket_path = "unix_socket_test_basic";
        let msg1 = b"hello";
        let msg2 = b"world!";
        if Path::new(socket_path).exists() {
            or_panic!(fs::remove_file(socket_path));
        }

        let listener = or_panic!(UnixListener::bind(socket_path));
        let thread = thread::scoped(|| {
            let mut stream = or_panic!(listener.accept());
            let mut buf = [0; 5];
            or_panic!(stream.read(&mut buf));
            assert_eq!(msg1, buf);
            or_panic!(stream.write_all(msg2));
        });

        let mut stream = or_panic!(UnixStream::connect(socket_path));
        or_panic!(stream.write_all(msg1));
        let mut buf = vec![];
        or_panic!(stream.read_to_end(&mut buf));
        assert_eq!(msg2, buf);
        drop(stream);

        thread.join();

        or_panic!(fs::remove_file(socket_path));
    }
}
<commit_msg>Add an iterator to UnixListener<commit_after>#![feature(io, std_misc, path, core)]
#![cfg_attr(test, feature(fs))]

extern crate libc;

use std::cmp;
use std::ffi::AsOsStr;
use std::io;
use std::iter::IntoIterator;
use std::mem;
use std::num::Int;
use std::os::unix::{Fd, OsStrExt, AsRawFd};
use std::path::AsPath;

struct Inner(Fd);

impl Drop for Inner {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.0);
        }
    }
}

impl Inner {
    unsafe fn new() -> io::Result<Inner> {
        let fd = libc::socket(libc::AF_UNIX, libc::SOCK_STREAM, 0);
        if fd < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(Inner(fd))
        }
    }

}

unsafe fn sockaddr_un<P: AsPath + ?Sized>(path: &P) -> io::Result<libc::sockaddr_un> {
    let mut addr: libc::sockaddr_un = mem::zeroed();
    addr.sun_family = libc::AF_UNIX as libc::sa_family_t;

    let bytes = path.as_path().as_os_str().as_bytes();
    if bytes.len() > addr.sun_path.len() - 1 {
        return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                  "path must be smaller than SUN_LEN",
                                  None));
    }
    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
        *dst = *src as libc::c_char;
    }
    // null byte's already there because we zeroed the struct

    Ok(addr)
}

pub struct UnixStream {
    inner: Inner,
}

impl UnixStream {
    pub fn connect<P: AsPath + ?Sized>(path: &P) -> io::Result<UnixStream> {
        unsafe {
            let inner = try!(Inner::new());
            let addr = try!(sockaddr_un(path));

            let ret = libc::connect(inner.0,
                                    &addr as *const _ as *const _,
                                    mem::size_of::<libc::sockaddr_un>() as libc::socklen_t);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixStream {
                    inner: inner,
                })
            }
        }
    }
}

fn calc_len(buf: &[u8]) -> libc::size_t {
    cmp::min(<libc::size_t as Int>::max_value() as usize, buf.len()) as libc::size_t
}

impl io::Read for UnixStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = unsafe {
            libc::recv(self.inner.0, buf.as_mut_ptr() as *mut _, calc_len(buf), 0)
        };

        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret as usize)
        }
    }
}

impl io::Write for UnixStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let ret = unsafe {
            libc::send(self.inner.0, buf.as_ptr() as *const _, calc_len(buf), 0)
        };

        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret as usize)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl AsRawFd for UnixStream {
    fn as_raw_fd(&self) -> Fd {
        self.inner.0
    }
}

pub struct UnixListener {
    inner: Inner,
}

impl UnixListener {
    pub fn bind<P: AsPath + ?Sized>(path: &P) -> io::Result<UnixListener> {
        unsafe {
            let inner = try!(Inner::new());
            let addr = try!(sockaddr_un(path));

            let ret = libc::bind(inner.0,
                                 &addr as *const _ as *const _,
                                 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t);
            if ret < 0 {
                return Err(io::Error::last_os_error());
            }

            let ret = libc::listen(inner.0, 128);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixListener {
                    inner: inner,
                })
            }
        }
    }

    pub fn accept(&self) -> io::Result<UnixStream> {
        unsafe {
            let ret = libc::accept(self.inner.0, 0 as *mut _, 0 as *mut _);
            if ret < 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(UnixStream {
                    inner: Inner(ret)
                })
            }
        }
    }

    pub fn iter<'a>(&'a self) -> Incoming<'a> {
        Incoming {
            listener: self
        }
    }
}

impl AsRawFd for UnixListener {
    fn as_raw_fd(&self) -> Fd {
        self.inner.0
    }
}

impl<'a> IntoIterator for &'a UnixListener {
    type Item = io::Result<UnixStream>;
    type IntoIter = Incoming<'a>;

    fn into_iter(self) -> Incoming<'a> {
        self.iter()
    }
}

pub struct Incoming<'a> {
    listener: &'a UnixListener,
}

impl<'a> Iterator for Incoming<'a> {
    type Item = io::Result<UnixStream>;

    fn next(&mut self) -> Option<io::Result<UnixStream>> {
        Some(self.listener.accept())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (Int::max_value(), None)
    }
}

#[cfg(test)]
mod test {
    use std::fs;
    use std::thread;
    use std::path::Path;
    use std::io::prelude::*;

    use {UnixListener, UnixStream};

    macro_rules! or_panic {
        ($e:expr) => {
            match $e {
                Ok(e) => e,
                Err(e) => panic!("{}", e),
            }
        }
    }

    #[test]
    fn basic() {
        let socket_path = "unix_socket_test_basic";
        let msg1 = b"hello";
        let msg2 = b"world!";
        if Path::new(socket_path).exists() {
            or_panic!(fs::remove_file(socket_path));
        }

        let listener = or_panic!(UnixListener::bind(socket_path));
        let thread = thread::scoped(|| {
            let mut stream = or_panic!(listener.accept());
            let mut buf = [0; 5];
            or_panic!(stream.read(&mut buf));
            assert_eq!(msg1, buf);
            or_panic!(stream.write_all(msg2));
        });

        let mut stream = or_panic!(UnixStream::connect(socket_path));
        or_panic!(stream.write_all(msg1));
        let mut buf = vec![];
        or_panic!(stream.read_to_end(&mut buf));
        assert_eq!(msg2, buf);
        drop(stream);

        thread.join();

        or_panic!(fs::remove_file(socket_path));
    }

    #[test]
    fn iter() {
        let socket_path = "unix_socket_test_iter";
        if Path::new(socket_path).exists() {
            or_panic!(fs::remove_file(socket_path));
        }

        let listener = or_panic!(UnixListener::bind(socket_path));
        let thread = thread::scoped(|| {
            for stream in listener.iter().take(2) {
                let mut stream = or_panic!(stream);
                let mut buf = [0];
                or_panic!(stream.read(&mut buf));
            }
        });

        for _ in 0..2 {
            let mut stream = or_panic!(UnixStream::connect(socket_path));
            or_panic!(stream.write_all(&[0]));
        }

        thread.join();

        or_panic!(fs::remove_file(socket_path));
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;

#[derive(Debug)]
pub struct DepthPoint {
    pub x: f64,
    pub y: f64,
    pub z: f64,
    pub x_z: f64,
    pub angle_view: f64,
}

impl DepthPoint {
    pub fn new(x: f64, y: f64, z: f64) -> DepthPoint {
        DepthPoint {
            x: x,
            y: y,
            z: z,
            x_z: 0.0,
            angle_view: 0.0,
        }
    }

    pub fn sdl_point(&self) -> sdl2::rect::Point {
        sdl2::rect::Point::new((self.x as f64/self.z) as i32, (self.y as f64/self.z) as i32)
    }

    pub fn perspect_point(&mut self, w: i32, h: i32) -> sdl2::rect::Point {
        if self.z > -0.01 && self.z < 0.0 {
            self.z = 0.001
        }

        else if self.z < 0.1 { // Prevents division by nearly 0, that cause integer overflow/underflow
            self.z = 0.11;
        }

        sdl2::rect::Point::new(
            ((w as f64 * self.x as f64/self.z) + w as f64) as i32,
            ((w as f64 * self.y as f64/self.z) + h as f64) as i32)
    }

    pub fn set_x (&mut self, x: f64) {
        self.x = x;
    }

    pub fn set_y (&mut self, y: f64) {
        self.y = y;
    }

    pub fn set_z (&mut self, z: f64) {
        self.z = z;
    }

    pub fn rotate_x_y(&mut self, cx: f64, cy: f64, angle: f64) {
        use std::f64;
        let s = f64::sin(angle);
        let c = f64::cos(angle);

        self.x -= cx;
        self.y -= cy;

        let new_x = self.x * c - self.y * s;
        let new_y = self.x * s + self.y * c;

        self.x = new_x + cx;
        self.y = new_y + cy;
    }

    pub fn rotate_x_z(&mut self, cx: f64, cz: f64, angle: f64) {
        use std::f64;
        let s = f64::sin(angle);
        let c = f64::cos(angle);

        self.x -= cx;
        self.z -= cz;

        let new_x = self.x * c - self.z * s;
        let new_z = self.x * s + self.z * c;

        self.x = new_x + cx;
        self.z = new_z + cz;
        self.x_z += angle;

        let angle_view = (f64::atan2(cx - self.x, cz - self.z) * 180.0 / f64::consts::PI);

        self.angle_view = angle_view;

    }

    pub fn rotate_y_z(&mut self, cy: f64, cz: f64, angle: f64) {
        use std::f64;
        let s = f64::sin(angle);
        let c = f64::cos(angle);

        self.y -= cy;
        self.z -= cz;

        let new_y = self.y * c - self.z * s;
        let new_z = self.y * s + self.z * c;

        self.y = new_y + cy;
        self.z = new_z + cz;
    }

    pub fn clone(&self) -> DepthPoint {
        DepthPoint {
            x: self.x,
            y: self.y,
            z: self.z,
            x_z: self.x_z,
            angle_view: self.angle_view,
        }
    }
}
#[derive(Debug)]
pub struct Square {
    pub points: Vec<DepthPoint>,
    pub x: f64,
    pub y: f64,
    pub z: f64,
    pub angle_view: f64,
}

impl Square {
    pub fn new(p1: DepthPoint, p2: DepthPoint, p3: DepthPoint, p4: DepthPoint) -> Square {
        Square {
            points: vec![p1, p2, p3, p4],
            x: 0.0,
            y: 0.0,
            z: 0.0,
            angle_view: 0.0,
        }
    }

    pub fn flat(&mut self, w: i32, h: i32, renderer: &mut sdl2::render::Renderer, cx: f64, cy: f64, cz: f64) {
        let mut return_buffer = Vec::<sdl2::rect::Point>::new();
        for point in &mut self.points {
            use std::f64;
            let point_x = point.x;
            let point_y = point.y;
            let point_z = point.z;

            point.set_x(point_x+self.x);
            point.set_y(point_y+self.y);
            point.set_z(point_z+self.z);

            let pers_point = point.perspect_point(w, h);

            if !(point.angle_view < 100.0 && point.angle_view > 0.0
            || point.angle_view < 0.0 && point.angle_view > -100.0)  {
                return_buffer.push(pers_point);
            }
            /* CAUSES A COOL BUG WHEN UNCOMMENTED! I RECOMMEND TRYING IT OUT.
            * Bug itself happens because the points position doesn't get reset when i just jump out to the next point in the loop.
            else {
                continue;
            }
            */

            point.set_x(point_x);
            point.set_y(point_y);
            point.set_z(point_z);
        }

        let point_x = self.points[0].x;
        let point_y = self.points[0].y;
        let point_z = self.points[0].z;

        self.points[0].set_x(point_x+self.x);
        self.points[0].set_y(point_y+self.y);
        self.points[0].set_z(point_z+self.z);

        return_buffer.push(self.points[0].perspect_point(w, h));
        renderer.draw_lines(&return_buffer);

        self.points[0].set_x(point_x);
        self.points[0].set_y(point_y);
        self.points[0].set_z(point_z);
    }

    pub fn set_x (&mut self, x: f64) {
        self.x = x;
    }

    pub fn set_y (&mut self, y: f64) {
        self.y = y;
    }

    pub fn set_z (&mut self, z: f64) {
        self.z = z;
    }
}

#[derive(Debug)]
pub struct Cube {
    pub faces: Vec<Square>,
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

impl Cube {
    pub fn new(p1: Square, p2: Square, p3: Square, p4: Square) -> Cube {
        Cube {
            faces: vec![p1, p2, p3, p4],
            x: 0.0,
            y: 0.0,
            z: 0.0,
        }
    }

    pub fn gen_new(x: f64, y: f64, z:f64, x_s: f64, y_s: f64, z_s:f64) -> Cube {
        let face1 = Square::new(DepthPoint::new(x_s, y_s, z_s),
                                DepthPoint::new(-x_s, y_s, z_s),
                                DepthPoint::new(-x_s, -y_s, z_s),
                                DepthPoint::new(x_s, -y_s, z_s));

        let face2 = Square::new(DepthPoint::new(x_s, y_s, -z_s),
                                DepthPoint::new(x_s, -y_s, -z_s),
                                DepthPoint::new(x_s, -y_s, z_s),
                                DepthPoint::new(x_s, y_s, z_s));

        let face3 = Square::new(DepthPoint::new(x_s, y_s, -z_s),
                                DepthPoint::new(-x_s, y_s, -z_s),
                                DepthPoint::new(-x_s, -y_s, -z_s),
                                DepthPoint::new(x_s, -y_s, -z_s));

        let face4 = Square::new(DepthPoint::new(-x_s, -y_s, -z_s),
                                DepthPoint::new(-x_s, y_s, -z_s),
                                DepthPoint::new(-x_s, y_s, z_s),
                                DepthPoint::new(-x_s, -y_s, z_s));

        Cube {
            faces: vec![face1, face2, face3, face4],
            x: x,
            y: y,
            z: z,
        }
    }

    pub fn flat(&mut self, w: i32, h: i32, renderer: &mut sdl2::render::Renderer, cx: f64, cy: f64, cz: f64, cxy: f64, cxz: f64, cyz: f64) {
        for face in &mut self.faces {
            let self_x = self.x;
            let self_y = self.y;
            let self_z = self.z;

            self.x += cx;
            self.y += cy;
            self.z += cz;

            for point in &mut face.points {
                    //let point_x = point.x;
                    //let point_y = point.y;
                    //let point_z = point.z;
                    point.rotate_y_z((-cy + -self_y), (-cz + -self_z), cyz);
                    point.rotate_x_z((-cx + -self_x), (-cz + -self_z), cxz);
                    point.rotate_x_y((-cx + -self_x), (-cy + -self_y), cxy);
            }

            let face_x = face.x;
            let face_y = face.y;
            let face_z = face.z;

            face.set_x(face_x+self.x);
            face.set_y(face_y+self.y);
            face.set_z(face_z+self.z);

            let flat = face.flat(w, h, renderer, cx, cy, cz);

            face.set_x(face_x);
            face.set_y(face_y);
            face.set_z(face_z);

            self.x = self_x;
            self.y = self_y;
            self.z = self_z;
        }
    }
}

pub struct Lines {
    pub lines: Vec<[DepthPoint; 2]>,
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

impl Lines {
    pub fn new(line_vec: Vec<[DepthPoint; 2]>) -> Lines {
        Lines {
            lines: line_vec,
            x: 0.0,
            y: 0.0,
            z: 0.0,
        }
    }

    pub fn flat(&mut self, w: i32, h: i32, renderer: &mut sdl2::render::Renderer,
                           cx: f64, cy: f64, cz: f64,
                           cxy: f64, cxz: f64, cyz: f64,
                           draw: bool) {
        for line in &mut self.lines {
            // Apply rotations
            let self_x = self.x;
            let self_y = self.y;
            let self_z = self.z;

            self.x += cx;
            self.y += cy;
            self.z += cz;

            line[0].rotate_y_z((-cy + -self_y), (-cz + -self_z), cyz);
            line[0].rotate_x_z((-cx + -self_x), (-cz + -self_z), cxz);
            line[0].rotate_x_y((-cx + -self_x), (-cy + -self_y), cxy);

            line[1].rotate_y_z((-cy + -self_y), (-cz + -self_z), cyz);
            line[1].rotate_x_z((-cx + -self_x), (-cz + -self_z), cxz);
            line[1].rotate_x_y((-cx + -self_x), (-cy + -self_y), cxy);

            if !(line[0].angle_view < 100.0 && line[0].angle_view > 0.0
            || line[0].angle_view < 0.0 && line[0].angle_view > -100.0) {
                // Grab all the positions because Rust doesn't allow for a method
                // to take its instances class variable as an argument
                let mut line_begin_x = line[0].x;
                let mut line_begin_y = line[0].y;
                let mut line_begin_z = line[0].z;

                let mut line_end_x = line[1].x;
                let mut line_end_y = line[1].y;
                let mut line_end_z = line[1].z;

                line[0].x = line_begin_x + self.x;
                line[0].y = line_begin_y + self.y;
                line[0].z = line_begin_z + self.z;

                line[1].x = line_end_x + self.x;
                line[1].y = line_end_y + self.y;
                line[1].z = line_end_z + self.z;

                // Generate 2d lines.
                let line_begin = line[0].perspect_point(w, h);
                //println!("{:?}", line_begin);
                let line_end = line[1].perspect_point(w, h);
                if draw {renderer.draw_lines(&[line_begin, line_end]);};

                line[0].x = line_begin_x;
                line[0].y = line_begin_y;
                line[0].z = line_begin_z;

                line[1].x = line_end_x;
                line[1].y = line_end_y;
                line[1].z = line_end_z;

                self.x = self_x;
                self.y = self_y;
                self.z = self_z;
            }

            // Set points' positions back to the ones they had before.
            self.x = self_x;
            self.y = self_y;
            self.z = self_z;
        }
    }
}

pub struct Triangle {
    pub points: [DepthPoint; 3],
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

impl Triangle {
    pub fn new(p1: DepthPoint, p2: DepthPoint, p3: DepthPoint) -> Triangle {
        Triangle {
            points: [p1, p2, p3],
            x: 0.0,
            y: 0.0,
            z: 0.0,
        }
    }

    pub fn flat(&mut self, w: i32, h: i32, renderer: &mut sdl2::render::Renderer,
                           cx: f64, cy: f64, cz: f64,
                           cxy: f64, cxz: f64, cyz: f64,
                           draw: bool)
    {

        //println!("{:?}", self.points[0].perspect_point(w, h).x());
        //MOST PROBABLY USELESS MEMORY REALLOCATIONS, BUT SUCH IS LIFE.
        let mut lines = Lines::new(vec![[self.points[0].clone(), self.points[1].clone()],
                                        [self.points[1].clone(), self.points[2].clone()],
                                        [self.points[2].clone(), self.points[0].clone()],]);

        lines.flat(w, h, renderer,
                   cx, cy, cz,
                   cxy, cxz, cyz,
                   draw);

        self.points = [lines.lines[0][0].clone(), lines.lines[1][0].clone(), lines.lines[2][0].clone()];
    }

    pub fn fill_bottom_flat(&mut self, w: i32, h: i32, renderer: &mut sdl2::render::Renderer,
                            cx: f64, cy: f64, cz: f64,
                            cxy: f64, cxz: f64, cyz: f64)
    {
        let mut largest_y = -2147483648; // used value from someone gave on irc because std::i32::MIN wasnt feeling like working at the moment
        let mut largest_index = 0 as usize;

        let p1 = self.points[0].clone();
        let p2 = self.points[1].clone();
        let p3 = self.points[2].clone();

        let mut iterator = 0;
        let mut sdl_points: [sdl2::rect::Point; 3] = [sdl2::rect::Point::new(0, 0); 3];

        for point in &mut [p1, p2, p3] {
            // Apply rotations
            let self_x = self.x;
            let self_y = self.y;
            let self_z = self.z;

            self.x += cx;
            self.y += cy;
            self.z += cz;

            point.rotate_y_z((-cy + -self_y), (-cz + -self_z), cyz);
            point.rotate_x_z((-cx + -self_x), (-cz + -self_z), cxz);
            point.rotate_x_y((-cx + -self_x), (-cy + -self_y), cxy);

            if !(point.angle_view < 100.0 && point.angle_view > 0.0
            || point.angle_view < 0.0 && point.angle_view > -100.0) {
                // Grab all the positions because Rust doesn't allow for a method
                // to take its instances class variable as an argument
                let mut point_x = point.x;
                let mut point_y = point.y;
                let mut point_z = point.z;

                point.x = point_x + self.x;
                point.y = point_y + self.y;
                point.z = point_z + self.z;

                // Generate 2d lines.
                let perspect_point = point.perspect_point(w, h);
                //println!("{:?}", perspect_point);
                sdl_points[iterator] = perspect_point;

                point.x = point_x;
                point.y = point_y;
                point.z = point_z;
                self.x = self_x;
                self.y = self_y;
                self.z = self_z;
            }

            // Set points' positions back to the ones they had before.
            self.x = self_x;
            self.y = self_y;
            self.z = self_z;

            iterator += 1;
        }

        //println!("{:?}", sdl_points);

        let flat_p1 = sdl_points[0];
        let flat_p2 = sdl_points[1];
        let flat_p3 = sdl_points[2];

        //println!("{:?}", self.points[0].perspect_point(w, h).x());

        let mut top: sdl2::rect::Point;
        let mut left: sdl2::rect::Point;
        let mut right: sdl2::rect::Point;

        // find top, left, and right.

        let points = [flat_p1, flat_p2, flat_p3];
        let top = points.iter().max_by_key(|p| -p.y()).unwrap().clone();
        let left = points.iter().max_by_key(|p| -p.x()).unwrap().clone();
        let right = points.iter().max_by_key(|p| p.x()).unwrap().clone();

        if (left.y() - top.y()) != 0 && (right.y() - top.y()) != 0 {
            let left_slope = -(left.x() - top.x()) as f64 / (left.y() - top.y()) as f64;
            let right_slope = -(right.x() - top.x()) as f64 / (right.y() - top.y()) as f64;

            for i in 0..left.y() - top.y() {
                renderer.draw_line(sdl2::rect::Point::new(right.x() + (right_slope * i as f64) as i32, right.y() - i),
                                   sdl2::rect::Point::new(left.x() + (left_slope * i as f64) as i32, left.y() - i));
            }
            println!("{:?} {:?}", left_slope, right_slope);
        }
    }

    pub fn fill_top_flat(&mut self, w: i32, h: i32, renderer: &mut sdl2::render::Renderer,
                            cx: f64, cy: f64, cz: f64,
                            cxy: f64, cxz: f64, cyz: f64)
    {
        let mut largest_y = -2147483648; // used value from someone gave on irc because std::i32::MIN wasnt feeling like working at the moment
        let mut largest_index = 0 as usize;

        let p1 = self.points[0].clone();
        let p2 = self.points[1].clone();
        let p3 = self.points[2].clone();

        let mut iterator = 0;
        let mut sdl_points: [sdl2::rect::Point; 3] = [sdl2::rect::Point::new(0, 0); 3];

        for point in &mut [p1, p2, p3] {
            // Apply rotations
            let self_x = self.x;
            let self_y = self.y;
            let self_z = self.z;

            self.x += cx;
            self.y += cy;
            self.z += cz;

            point.rotate_y_z((-cy + -self_y), (-cz + -self_z), cyz);
            point.rotate_x_z((-cx + -self_x), (-cz + -self_z), cxz);
            point.rotate_x_y((-cx + -self_x), (-cy + -self_y), cxy);

            if !(point.angle_view < 100.0 && point.angle_view > 0.0
            || point.angle_view < 0.0 && point.angle_view > -100.0) {
                // Grab all the positions because Rust doesn't allow for a method
                // to take its instances class variable as an argument
                let mut point_x = point.x;
                let mut point_y = point.y;
                let mut point_z = point.z;

                point.x = point_x + self.x;
                point.y = point_y + self.y;
                point.z = point_z + self.z;

                // Generate 2d lines.
                let perspect_point = point.perspect_point(w, h);
                //println!("{:?}", perspect_point);
                sdl_points[iterator] = perspect_point;

                point.x = point_x;
                point.y = point_y;
                point.z = point_z;
                self.x = self_x;
                self.y = self_y;
                self.z = self_z;
            }

            // Set points' positions back to the ones they had before.
            self.x = self_x;
            self.y = self_y;
            self.z = self_z;

            iterator += 1;
        }

        //println!("{:?}", sdl_points);

        let flat_p1 = sdl_points[0];
        let flat_p2 = sdl_points[1];
        let flat_p3 = sdl_points[2];

        //println!("{:?}", self.points[0].perspect_point(w, h).x());

        let mut top: sdl2::rect::Point;
        let mut left: sdl2::rect::Point;
        let mut right: sdl2::rect::Point;

        // find top, left, and right.

        let points = [flat_p1, flat_p2, flat_p3];
        let top = points.iter().max_by_key(|p| p.y()).unwrap().clone();
        let left = points.iter().max_by_key(|p| -p.x()).unwrap().clone();
        let right = points.iter().max_by_key(|p| p.x()).unwrap().clone();

        if (left.y() - top.y()) != 0 && (right.y() - top.y()) != 0 {
            let left_slope = -(left.x() - top.x()) as f64 / (left.y() - top.y()) as f64;
            let right_slope = -(right.x() - top.x()) as f64 / (right.y() - top.y()) as f64;

            for i in 0..top.y() - left.y() {
                renderer.draw_line(sdl2::rect::Point::new(right.x() + (right_slope * -i as f64) as i32, right.y() + i),
                                   sdl2::rect::Point::new(left.x() + (left_slope * -i as f64) as i32, left.y() + i));
            }
            println!("{:?} {:?}", left_slope, right_slope);
        }
    }
}<commit_msg>Removed everything but DepthPoints and Triangles, also using f32<commit_after>extern crate sdl2;

use super::start;

#[derive(Clone, Copy, Debug)]
pub struct FlatPoint {
    pub x: i32,
    pub y: i32,
}

impl FlatPoint {
    pub fn make_sdl(&self) -> sdl2::rect::Point {
        sdl2::rect::Point::new(self.x, self.y)
    }
}

#[derive(Clone, Copy, Debug)]
pub struct DepthPoint {
    pub x: f32,
    pub y: f32,
    pub z: f32,

    pub x_y: f32,
    pub x_z: f32,
    pub y_z: f32,

    last_x_y: f32,
    last_x_z: f32,
    last_y_z: f32,
}

impl DepthPoint {
    pub fn new(x: f32, y: f32, z: f32) -> DepthPoint {
        DepthPoint {
            x: x,
            y: y,
            z: z,

            x_y: 0.0,
            x_z: 0.0,
            y_z: 0.0,

            last_x_y: 0.0,
            last_x_z: 0.0,
            last_y_z: 0.0,
        }
    }

    pub fn flat_point(&mut self, engine_scr_x: u32, engine_scr_y: u32, offset_x: f32, offset_y: f32, offset_z: f32) -> FlatPoint {
        if self.z > -0.01 && self.z < 0.0 {
            self.z = 0.001
        }

        else if self.z < 0.1 { // Prevents division by nearly 0, that cause integer overflow/underflow
            self.z = 0.11;
        }

        FlatPoint {
            x: ((engine_scr_x as f32 * (self.x + offset_x) as f32/(self.z + offset_z)) + engine_scr_x as f32 / 2.0) as i32,
            y: ((engine_scr_x as f32 * (self.y + offset_y) as f32/(self.z + offset_z)) + engine_scr_y as f32 / 2.0) as i32,
        }
    }

    pub fn apply_camera_rotations(&mut self, engine: &start::Engine) {
        let x_y = self.x_y;
        let x_z = self.x_z;
        let y_z = self.y_z;

        let last_x_y = self.last_x_y;
        let last_x_z = self.last_x_z;
        let last_y_z = self.last_y_z;

        self.rotate_x_y(&engine, x_y - last_x_y);
        self.rotate_x_z(&engine, x_z - last_x_z);
        self.rotate_y_z(&engine, y_z - last_y_z);

        self.last_x_y = x_y;
        self.last_x_z = x_z;
        self.last_y_z = y_z;
    }

    pub fn rotate_x_y(&mut self, engine: &start::Engine, angle: f32) {
        use std::f32;
        let s = f32::sin(angle);
        let c = f32::cos(angle);

        self.x -= engine.camera_x;
        self.y -= engine.camera_y;

        let new_x = self.x * c - self.y * s;
        let new_y = self.x * s + self.y * c;

        self.x = new_x + engine.camera_x;
        self.y = new_y + engine.camera_y;
    }

    pub fn rotate_x_z(&mut self, engine: &start::Engine, angle: f32) {
        use std::f32;
        let s = f32::sin(angle);
        let c = f32::cos(angle);

        self.x -= engine.camera_x;
        self.z -= engine.camera_z;

        let new_x = self.x * c - self.z * s;
        let new_z = self.x * s + self.z * c;

        self.x = new_x + engine.camera_x;
        self.z = new_z + engine.camera_z;
    }

    pub fn rotate_y_z(&mut self, engine: &start::Engine, angle: f32) {
        use std::f32;
        let s = f32::sin(angle);
        let c = f32::cos(angle);

        self.y -= engine.camera_y;
        self.z -= engine.camera_z;

        let new_y = self.y * c - self.z * s;
        let new_z = self.y * s + self.z * c;

        self.y = new_y + engine.camera_y;
        self.z = new_z + engine.camera_z;
    }
}

#[derive(Clone, Copy, Debug)]
pub struct Triangle {
    pub p1: DepthPoint,
    pub p2: DepthPoint,
    pub p3: DepthPoint,

    pub x: f32,
    pub y: f32,
    pub z: f32,

    pub x_y: f32,
    pub x_z: f32,
    pub y_z: f32,

    last_x_y: f32,
    last_x_z: f32,
    last_y_z: f32,
}

impl Triangle {
    pub fn new(p1: DepthPoint, p2: DepthPoint, p3: DepthPoint, x: f32, y: f32, z: f32) -> Triangle {
        Triangle {
            p1: p1,
            p2: p2,
            p3: p3,

            x: x,
            y: y,
            z: z,

            x_y: 0.0,
            x_z: 0.0,
            y_z: 0.0,

            last_x_y: 0.0,
            last_x_z: 0.0,
            last_y_z: 0.0,
        }
    }
}<|endoftext|>


<commit_before><commit_msg>Add regression test for old NLL ICE<commit_after>// check-pass

#![crate_type = "lib"]

// In an older version, when NLL was still a feature, the following previously did not compile
// #![feature(nll)]

use std::ops::Index;

pub struct Test<T> {
    a: T,
}

impl<T> Index<usize> for Test<T> {
    type Output = T;

    fn index(&self, _index: usize) -> &Self::Output {
        &self.a
    }
}
<|endoftext|>


<commit_before><commit_msg>add BTree::fold{ l, r }_with_key<commit_after><|endoftext|>


<commit_before><commit_msg>Add command info table<commit_after><|endoftext|>


<commit_before><commit_msg>Add ID reporting in imag-notes<commit_after><|endoftext|>


<commit_before><commit_msg>Use register_custom_derive to remove custom_derive deprecation warning.<commit_after><|endoftext|>


<commit_before><commit_msg>RHS vector scaling<commit_after><|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Misc low level stuff

use option::{Some, None};
use cast;
use cmp::{Eq, Ord};
use gc;
use io;
use libc;
use libc::{c_void, c_char, size_t};
use repr;
use str;

pub type FreeGlue<'self> = &'self fn(*TypeDesc, *c_void);

// Corresponds to runtime type_desc type
pub struct TypeDesc {
    size: uint,
    align: uint,
    take_glue: uint,
    drop_glue: uint,
    free_glue: uint
    // Remaining fields not listed
}

/// The representation of a Rust closure
pub struct Closure {
    code: *(),
    env: *(),
}

pub mod rusti {
    #[abi = "rust-intrinsic"]
    pub extern "rust-intrinsic" {
        fn get_tydesc<T>() -> *();
        fn size_of<T>() -> uint;
        fn pref_align_of<T>() -> uint;
        fn min_align_of<T>() -> uint;
    }
}

pub mod rustrt {
    use libc::{c_char, size_t};

    pub extern {
        #[rust_stack]
        unsafe fn rust_upcall_fail(expr: *c_char,
                                   file: *c_char,
                                   line: size_t);
    }
}

/// Compares contents of two pointers using the default method.
/// Equivalent to `*x1 == *x2`.  Useful for hashtables.
pub fn shape_eq<T:Eq>(x1: &T, x2: &T) -> bool {
    *x1 == *x2
}

pub fn shape_lt<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 < *x2
}

pub fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 <= *x2
}

/**
 * Returns a pointer to a type descriptor.
 *
 * Useful for calling certain function in the Rust runtime or otherwise
 * performing dark magick.
 */
#[inline(always)]
pub fn get_type_desc<T>() -> *TypeDesc {
    unsafe { rusti::get_tydesc::<T>() as *TypeDesc }
}

/// Returns a pointer to a type descriptor.
#[inline(always)]
pub fn get_type_desc_val<T>(_val: &T) -> *TypeDesc {
    get_type_desc::<T>()
}

/// Returns the size of a type
#[inline(always)]
pub fn size_of<T>() -> uint {
    unsafe { rusti::size_of::<T>() }
}

/// Returns the size of the type that `_val` points to
#[inline(always)]
pub fn size_of_val<T>(_val: &T) -> uint {
    size_of::<T>()
}

/**
 * Returns the size of a type, or 1 if the actual size is zero.
 *
 * Useful for building structures containing variable-length arrays.
 */
#[inline(always)]
pub fn nonzero_size_of<T>() -> uint {
    let s = size_of::<T>();
    if s == 0 { 1 } else { s }
}

/// Returns the size of the type of the value that `_val` points to
#[inline(always)]
pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
    nonzero_size_of::<T>()
}

/**
 * Returns the ABI-required minimum alignment of a type
 *
 * This is the alignment used for struct fields. It may be smaller
 * than the preferred alignment.
 */
#[inline(always)]
pub fn min_align_of<T>() -> uint {
    unsafe { rusti::min_align_of::<T>() }
}

/// Returns the ABI-required minimum alignment of the type of the value that
/// `_val` points to
#[inline(always)]
pub fn min_align_of_val<T>(_val: &T) -> uint {
    min_align_of::<T>()
}

/// Returns the preferred alignment of a type
#[inline(always)]
pub fn pref_align_of<T>() -> uint {
    unsafe { rusti::pref_align_of::<T>() }
}

/// Returns the preferred alignment of the type of the value that
/// `_val` points to
#[inline(always)]
pub fn pref_align_of_val<T>(_val: &T) -> uint {
    pref_align_of::<T>()
}

/// Returns the refcount of a shared box (as just before calling this)
#[inline(always)]
pub fn refcount<T>(t: @T) -> uint {
    unsafe {
        let ref_ptr: *uint = cast::transmute_copy(&t);
        *ref_ptr - 1
    }
}

pub fn log_str<T>(t: &T) -> ~str {
    do io::with_str_writer |wr| {
        repr::write_repr(wr, t)
    }
}

/// Trait for initiating task failure.
pub trait FailWithCause {
    /// Fail the current task, taking ownership of `cause`
    fn fail_with(cause: Self, file: &'static str, line: uint) -> !;
}

impl FailWithCause for ~str {
    fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
        do str::as_buf(cause) |msg_buf, _msg_len| {
            do str::as_buf(file) |file_buf, _file_len| {
                unsafe {
                    let msg_buf = cast::transmute(msg_buf);
                    let file_buf = cast::transmute(file_buf);
                    begin_unwind_(msg_buf, file_buf, line as libc::size_t)
                }
            }
        }
    }
}

impl FailWithCause for &'static str {
    fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
        do str::as_buf(cause) |msg_buf, _msg_len| {
            do str::as_buf(file) |file_buf, _file_len| {
                unsafe {
                    let msg_buf = cast::transmute(msg_buf);
                    let file_buf = cast::transmute(file_buf);
                    begin_unwind_(msg_buf, file_buf, line as libc::size_t)
                }
            }
        }
    }
}

// NOTE: remove function after snapshot
#[cfg(stage0)]
pub fn begin_unwind(msg: ~str, file: ~str, line: uint) -> ! {

    use rt::{context, OldTaskContext};
    use rt::local_services::unsafe_borrow_local_services;

    match context() {
        OldTaskContext => {
            do str::as_buf(msg) |msg_buf, _msg_len| {
                do str::as_buf(file) |file_buf, _file_len| {
                    unsafe {
                        let msg_buf = cast::transmute(msg_buf);
                        let file_buf = cast::transmute(file_buf);
                        begin_unwind_(msg_buf, file_buf, line as libc::size_t)
                    }
                }
            }
        }
        _ => {
            gc::cleanup_stack_for_failure();
            unsafe {
                let local_services = unsafe_borrow_local_services();
                match local_services.unwinder {
                    Some(ref mut unwinder) => unwinder.begin_unwind(),
                    None => abort!("failure without unwinder. aborting process")
                }
            }
        }
    }
}

// FIXME #4427: Temporary until rt::rt_fail_ goes away
pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
    unsafe {
        gc::cleanup_stack_for_failure();
        rustrt::rust_upcall_fail(msg, file, line);
        cast::transmute(())
    }
}

// NOTE: remove function after snapshot
#[cfg(stage0)]
pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! {
    let (msg, file) = (msg.to_owned(), file.to_owned());
    begin_unwind(~"assertion failed: " + msg, file, line)
}

#[cfg(test)]
mod tests {
    use cast;
    use sys::*;

    #[test]
    fn size_of_basic() {
        assert!(size_of::<u8>() == 1u);
        assert!(size_of::<u16>() == 2u);
        assert!(size_of::<u32>() == 4u);
        assert!(size_of::<u64>() == 8u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn size_of_32() {
        assert!(size_of::<uint>() == 4u);
        assert!(size_of::<*uint>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert!(size_of::<uint>() == 8u);
        assert!(size_of::<*uint>() == 8u);
    }

    #[test]
    fn size_of_val_basic() {
        assert_eq!(size_of_val(&1u8), 1);
        assert_eq!(size_of_val(&1u16), 2);
        assert_eq!(size_of_val(&1u32), 4);
        assert_eq!(size_of_val(&1u64), 8);
    }

    #[test]
    fn nonzero_size_of_basic() {
        type Z = [i8, ..0];
        assert!(size_of::<Z>() == 0u);
        assert!(nonzero_size_of::<Z>() == 1u);
        assert!(nonzero_size_of::<uint>() == size_of::<uint>());
    }

    #[test]
    fn nonzero_size_of_val_basic() {
        let z = [0u8, ..0];
        assert_eq!(size_of_val(&z), 0u);
        assert_eq!(nonzero_size_of_val(&z), 1u);
        assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
    }

    #[test]
    fn align_of_basic() {
        assert!(pref_align_of::<u8>() == 1u);
        assert!(pref_align_of::<u16>() == 2u);
        assert!(pref_align_of::<u32>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn align_of_32() {
        assert!(pref_align_of::<uint>() == 4u);
        assert!(pref_align_of::<*uint>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert!(pref_align_of::<uint>() == 8u);
        assert!(pref_align_of::<*uint>() == 8u);
    }

    #[test]
    fn align_of_val_basic() {
        assert_eq!(pref_align_of_val(&1u8), 1u);
        assert_eq!(pref_align_of_val(&1u16), 2u);
        assert_eq!(pref_align_of_val(&1u32), 4u);
    }

    #[test]
    fn synthesize_closure() {
        unsafe {
            let x = 10;
            let f: &fn(int) -> int = |y| x + y;

            assert!(f(20) == 30);

            let original_closure: Closure = cast::transmute(f);

            let actual_function_pointer = original_closure.code;
            let environment = original_closure.env;

            let new_closure = Closure {
                code: actual_function_pointer,
                env: environment
            };

            let new_f: &fn(int) -> int = cast::transmute(new_closure);
            assert!(new_f(20) == 30);
        }
    }

    #[test]
    #[should_fail]
    fn fail_static() { FailWithCause::fail_with("cause", file!(), line!())  }

    #[test]
    #[should_fail]
    fn fail_owned() { FailWithCause::fail_with(~"cause", file!(), line!())  }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>core: Wire up the unwinder to newsched again<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Misc low level stuff

use option::{Some, None};
use cast;
use cmp::{Eq, Ord};
use gc;
use io;
use libc;
use libc::{c_void, c_char, size_t};
use repr;
use str;

pub type FreeGlue<'self> = &'self fn(*TypeDesc, *c_void);

// Corresponds to runtime type_desc type
pub struct TypeDesc {
    size: uint,
    align: uint,
    take_glue: uint,
    drop_glue: uint,
    free_glue: uint
    // Remaining fields not listed
}

/// The representation of a Rust closure
pub struct Closure {
    code: *(),
    env: *(),
}

pub mod rusti {
    #[abi = "rust-intrinsic"]
    pub extern "rust-intrinsic" {
        fn get_tydesc<T>() -> *();
        fn size_of<T>() -> uint;
        fn pref_align_of<T>() -> uint;
        fn min_align_of<T>() -> uint;
    }
}

pub mod rustrt {
    use libc::{c_char, size_t};

    pub extern {
        #[rust_stack]
        unsafe fn rust_upcall_fail(expr: *c_char,
                                   file: *c_char,
                                   line: size_t);
    }
}

/// Compares contents of two pointers using the default method.
/// Equivalent to `*x1 == *x2`.  Useful for hashtables.
pub fn shape_eq<T:Eq>(x1: &T, x2: &T) -> bool {
    *x1 == *x2
}

pub fn shape_lt<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 < *x2
}

pub fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 <= *x2
}

/**
 * Returns a pointer to a type descriptor.
 *
 * Useful for calling certain function in the Rust runtime or otherwise
 * performing dark magick.
 */
#[inline(always)]
pub fn get_type_desc<T>() -> *TypeDesc {
    unsafe { rusti::get_tydesc::<T>() as *TypeDesc }
}

/// Returns a pointer to a type descriptor.
#[inline(always)]
pub fn get_type_desc_val<T>(_val: &T) -> *TypeDesc {
    get_type_desc::<T>()
}

/// Returns the size of a type
#[inline(always)]
pub fn size_of<T>() -> uint {
    unsafe { rusti::size_of::<T>() }
}

/// Returns the size of the type that `_val` points to
#[inline(always)]
pub fn size_of_val<T>(_val: &T) -> uint {
    size_of::<T>()
}

/**
 * Returns the size of a type, or 1 if the actual size is zero.
 *
 * Useful for building structures containing variable-length arrays.
 */
#[inline(always)]
pub fn nonzero_size_of<T>() -> uint {
    let s = size_of::<T>();
    if s == 0 { 1 } else { s }
}

/// Returns the size of the type of the value that `_val` points to
#[inline(always)]
pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
    nonzero_size_of::<T>()
}

/**
 * Returns the ABI-required minimum alignment of a type
 *
 * This is the alignment used for struct fields. It may be smaller
 * than the preferred alignment.
 */
#[inline(always)]
pub fn min_align_of<T>() -> uint {
    unsafe { rusti::min_align_of::<T>() }
}

/// Returns the ABI-required minimum alignment of the type of the value that
/// `_val` points to
#[inline(always)]
pub fn min_align_of_val<T>(_val: &T) -> uint {
    min_align_of::<T>()
}

/// Returns the preferred alignment of a type
#[inline(always)]
pub fn pref_align_of<T>() -> uint {
    unsafe { rusti::pref_align_of::<T>() }
}

/// Returns the preferred alignment of the type of the value that
/// `_val` points to
#[inline(always)]
pub fn pref_align_of_val<T>(_val: &T) -> uint {
    pref_align_of::<T>()
}

/// Returns the refcount of a shared box (as just before calling this)
#[inline(always)]
pub fn refcount<T>(t: @T) -> uint {
    unsafe {
        let ref_ptr: *uint = cast::transmute_copy(&t);
        *ref_ptr - 1
    }
}

pub fn log_str<T>(t: &T) -> ~str {
    do io::with_str_writer |wr| {
        repr::write_repr(wr, t)
    }
}

/// Trait for initiating task failure.
pub trait FailWithCause {
    /// Fail the current task, taking ownership of `cause`
    fn fail_with(cause: Self, file: &'static str, line: uint) -> !;
}

impl FailWithCause for ~str {
    fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
        do str::as_buf(cause) |msg_buf, _msg_len| {
            do str::as_buf(file) |file_buf, _file_len| {
                unsafe {
                    let msg_buf = cast::transmute(msg_buf);
                    let file_buf = cast::transmute(file_buf);
                    begin_unwind_(msg_buf, file_buf, line as libc::size_t)
                }
            }
        }
    }
}

impl FailWithCause for &'static str {
    fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
        do str::as_buf(cause) |msg_buf, _msg_len| {
            do str::as_buf(file) |file_buf, _file_len| {
                unsafe {
                    let msg_buf = cast::transmute(msg_buf);
                    let file_buf = cast::transmute(file_buf);
                    begin_unwind_(msg_buf, file_buf, line as libc::size_t)
                }
            }
        }
    }
}

// NOTE: remove function after snapshot
#[cfg(stage0)]
pub fn begin_unwind(msg: ~str, file: ~str, line: uint) -> ! {

    do str::as_buf(msg) |msg_buf, _msg_len| {
        do str::as_buf(file) |file_buf, _file_len| {
            unsafe {
                let msg_buf = cast::transmute(msg_buf);
                let file_buf = cast::transmute(file_buf);
                begin_unwind_(msg_buf, file_buf, line as libc::size_t)
            }
        }
    }
}

// FIXME #4427: Temporary until rt::rt_fail_ goes away
pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
    use rt::{context, OldTaskContext};
    use rt::local_services::unsafe_borrow_local_services;

    match context() {
        OldTaskContext => {
            unsafe {
                gc::cleanup_stack_for_failure();
                rustrt::rust_upcall_fail(msg, file, line);
                cast::transmute(())
            }
        }
        _ => {
            // XXX: Need to print the failure message
            gc::cleanup_stack_for_failure();
            unsafe {
                let local_services = unsafe_borrow_local_services();
                match local_services.unwinder {
                    Some(ref mut unwinder) => unwinder.begin_unwind(),
                    None => abort!("failure without unwinder. aborting process")
                }
            }
        }
    }
}

// NOTE: remove function after snapshot
#[cfg(stage0)]
pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! {
    let (msg, file) = (msg.to_owned(), file.to_owned());
    begin_unwind(~"assertion failed: " + msg, file, line)
}

#[cfg(test)]
mod tests {
    use cast;
    use sys::*;

    #[test]
    fn size_of_basic() {
        assert!(size_of::<u8>() == 1u);
        assert!(size_of::<u16>() == 2u);
        assert!(size_of::<u32>() == 4u);
        assert!(size_of::<u64>() == 8u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn size_of_32() {
        assert!(size_of::<uint>() == 4u);
        assert!(size_of::<*uint>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert!(size_of::<uint>() == 8u);
        assert!(size_of::<*uint>() == 8u);
    }

    #[test]
    fn size_of_val_basic() {
        assert_eq!(size_of_val(&1u8), 1);
        assert_eq!(size_of_val(&1u16), 2);
        assert_eq!(size_of_val(&1u32), 4);
        assert_eq!(size_of_val(&1u64), 8);
    }

    #[test]
    fn nonzero_size_of_basic() {
        type Z = [i8, ..0];
        assert!(size_of::<Z>() == 0u);
        assert!(nonzero_size_of::<Z>() == 1u);
        assert!(nonzero_size_of::<uint>() == size_of::<uint>());
    }

    #[test]
    fn nonzero_size_of_val_basic() {
        let z = [0u8, ..0];
        assert_eq!(size_of_val(&z), 0u);
        assert_eq!(nonzero_size_of_val(&z), 1u);
        assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
    }

    #[test]
    fn align_of_basic() {
        assert!(pref_align_of::<u8>() == 1u);
        assert!(pref_align_of::<u16>() == 2u);
        assert!(pref_align_of::<u32>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn align_of_32() {
        assert!(pref_align_of::<uint>() == 4u);
        assert!(pref_align_of::<*uint>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert!(pref_align_of::<uint>() == 8u);
        assert!(pref_align_of::<*uint>() == 8u);
    }

    #[test]
    fn align_of_val_basic() {
        assert_eq!(pref_align_of_val(&1u8), 1u);
        assert_eq!(pref_align_of_val(&1u16), 2u);
        assert_eq!(pref_align_of_val(&1u32), 4u);
    }

    #[test]
    fn synthesize_closure() {
        unsafe {
            let x = 10;
            let f: &fn(int) -> int = |y| x + y;

            assert!(f(20) == 30);

            let original_closure: Closure = cast::transmute(f);

            let actual_function_pointer = original_closure.code;
            let environment = original_closure.env;

            let new_closure = Closure {
                code: actual_function_pointer,
                env: environment
            };

            let new_f: &fn(int) -> int = cast::transmute(new_closure);
            assert!(new_f(20) == 30);
        }
    }

    #[test]
    #[should_fail]
    fn fail_static() { FailWithCause::fail_with("cause", file!(), line!())  }

    #[test]
    #[should_fail]
    fn fail_owned() { FailWithCause::fail_with(~"cause", file!(), line!())  }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>/// A dynamic, mutable location.
///
/// Similar to a mutable option type, but friendlier.

struct Cell<T> {
    mut value: option<T>;
}

/// Creates a new full cell with the given value.
fn Cell<T>(+value: T) -> Cell<T> {
    Cell { value: some(move value) }
}

fn empty_cell<T>() -> Cell<T> {
    Cell { value: none }
}

impl<T> Cell<T> {
    /// Yields the value, failing if the cell is empty.
    fn take() -> T {
        if self.is_empty() {
            fail ~"attempt to take an empty cell";
        }

        let mut value = none;
        value <-> self.value;
        return option::unwrap(value);
    }

    /// Returns the value, failing if the cell is full.
    fn put_back(+value: T) {
        if !self.is_empty() {
            fail ~"attempt to put a value back into a full cell";
        }
        self.value = some(move value);
    }

    /// Returns true if the cell is empty and false if the cell is full.
    fn is_empty() -> bool {
        self.value.is_none()
    }
}

#[test]
fn test_basic() {
    let value_cell = Cell(~10);
    assert !value_cell.is_empty();
    let value = value_cell.take();
    assert value == ~10;
    assert value_cell.is_empty();
    value_cell.put_back(value);
    assert !value_cell.is_empty();
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_take_empty() {
    let value_cell = empty_cell::<~int>();
    value_cell.take();
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_put_back_non_empty() {
    let value_cell = Cell(~10);
    value_cell.put_back(~20);
}<commit_msg>libstd: Add a function to borrow a cell<commit_after>/// A dynamic, mutable location.
///
/// Similar to a mutable option type, but friendlier.

struct Cell<T> {
    mut value: option<T>;
}

/// Creates a new full cell with the given value.
fn Cell<T>(+value: T) -> Cell<T> {
    Cell { value: some(move value) }
}

fn empty_cell<T>() -> Cell<T> {
    Cell { value: none }
}

impl<T> Cell<T> {
    /// Yields the value, failing if the cell is empty.
    fn take() -> T {
        if self.is_empty() {
            fail ~"attempt to take an empty cell";
        }

        let mut value = none;
        value <-> self.value;
        return option::unwrap(value);
    }

    /// Returns the value, failing if the cell is full.
    fn put_back(+value: T) {
        if !self.is_empty() {
            fail ~"attempt to put a value back into a full cell";
        }
        self.value = some(move value);
    }

    /// Returns true if the cell is empty and false if the cell is full.
    fn is_empty() -> bool {
        self.value.is_none()
    }

    // Calls a closure with a reference to the value.
    fn with_ref(f: fn(v: &T)) {
        let val = move self.take();
        f(&val);
        self.put_back(move val);
    }
}

#[test]
fn test_basic() {
    let value_cell = Cell(~10);
    assert !value_cell.is_empty();
    let value = value_cell.take();
    assert value == ~10;
    assert value_cell.is_empty();
    value_cell.put_back(value);
    assert !value_cell.is_empty();
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_take_empty() {
    let value_cell = empty_cell::<~int>();
    value_cell.take();
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_put_back_non_empty() {
    let value_cell = Cell(~10);
    value_cell.put_back(~20);
}
<|endoftext|>


<commit_before><commit_msg>Fix test for m.room.create event<commit_after><|endoftext|>


<commit_before><commit_msg>Implement sized lang-item<commit_after><|endoftext|>


<commit_before><commit_msg>Put doctests code in a separate test<commit_after>use rav1e::prelude::*;

#[test]
fn send_frame() -> Result<(), Box<dyn std::error::Error>> {
  let cfg = Config::default();
  let mut ctx: Context<u8> = cfg.new_context().unwrap();
  let f1 = ctx.new_frame();
  let f2 = f1.clone();
  let info = FrameParameters {
    frame_type_override: FrameTypeOverride::Key,
    opaque: None,
  };

  // Send the plain frame data
  ctx.send_frame(f1)?;
  // Send the data and the per-frame parameters
  // In this case the frame is forced to be a keyframe.
  ctx.send_frame((f2, info))?;
  // Flush the encoder, it is equivalent to a call to `flush()`
  ctx.send_frame(None)?;
  Ok(())
}

#[test]
fn receive_packet() -> Result<(), Box<dyn std::error::Error>> {
  let cfg = Config::default();
  let mut ctx: Context<u8> = cfg.new_context()?;
  let frame = ctx.new_frame();

  ctx.send_frame(frame)?;
  ctx.flush();

  loop {
    match ctx.receive_packet() {
      Ok(_packet) => { /* Mux the packet. */ }
      Err(EncoderStatus::Encoded) => (),
      Err(EncoderStatus::LimitReached) => break,
      Err(err) => Err(err)?,
    }
  }
  Ok(())
}

use std::sync::Arc;

fn encode_frames(
  ctx: &mut Context<u8>, mut frames: impl Iterator<Item = Frame<u8>>,
) -> Result<(), EncoderStatus> {
  // This is a slightly contrived example, intended to showcase the
  // various statuses that can be returned from receive_packet().
  // Assume that, for example, there are a lot of frames in the
  // iterator, which are produced lazily, so you don't want to send
  // them all in at once as to not exhaust the memory.
  loop {
    match ctx.receive_packet() {
      Ok(_packet) => { /* Mux the packet. */ }
      Err(EncoderStatus::Encoded) => {
        // A frame was encoded without emitting a packet. This is
        // normal, just proceed as usual.
      }
      Err(EncoderStatus::LimitReached) => {
        // All frames have been encoded. Time to break out of the
        // loop.
        break;
      }
      Err(EncoderStatus::NeedMoreData) => {
        // The encoder has requested additional frames. Push the
        // next frame in, or flush the encoder if there are no
        // frames left (on None).
        ctx.send_frame(frames.next().map(Arc::new))?;
      }
      Err(EncoderStatus::EnoughData) => {
        // Since we aren't trying to push frames after flushing,
        // this should never happen in this example.
        unreachable!();
      }
      Err(EncoderStatus::NotReady) => {
        // We're not doing two-pass encoding, so this can never
        // occur.
        unreachable!();
      }
      Err(EncoderStatus::Failure) => {
        return Err(EncoderStatus::Failure);
      }
    }
  }

  Ok(())
}

#[test]
fn encoding() -> Result<(), Box<dyn std::error::Error>> {
  let mut enc = EncoderConfig::default();
  // So it runs faster.
  enc.width = 16;
  enc.height = 16;
  let cfg = Config::new().with_encoder_config(enc);
  let mut ctx: Context<u8> = cfg.new_context()?;

  let frames = vec![ctx.new_frame(); 4].into_iter();
  encode_frames(&mut ctx, frames)?;

  Ok(())
}
<|endoftext|>


<commit_before><commit_msg>Added nop.<commit_after><|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

struct T (&'static [isize]);
static t : T = T (&[5, 4, 3]);
pub fn main () {
    let T(ref v) = t;
    assert_eq!(v[0], 5);
}
<commit_msg>silence some style warning<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

struct T (&'static [isize]);
static STATIC : T = T (&[5, 4, 3]);
pub fn main () {
    let T(ref v) = STATIC;
    assert_eq!(v[0], 5);
}
<|endoftext|>


<commit_before><commit_msg>add `Send` bound to concurrent containers<commit_after><|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use middle::def_id::DefId;
use middle::ty::Region;
use mir::repr::*;
use rustc_data_structures::tuple_slice::TupleSlice;
use syntax::codemap::Span;

pub trait Visitor<'tcx> {
    // Override these, and call `self.super_xxx` to revert back to the
    // default behavior.

    fn visit_mir(&mut self, mir: &Mir<'tcx>) {
        self.super_mir(mir);
    }

    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
        self.super_basic_block_data(block, data);
    }

    fn visit_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>) {
        self.super_statement(block, statement);
    }

    fn visit_assign(&mut self, block: BasicBlock, lvalue: &Lvalue<'tcx>, rvalue: &Rvalue<'tcx>) {
        self.super_assign(block, lvalue, rvalue);
    }

    fn visit_terminator(&mut self, block: BasicBlock, terminator: &Terminator<'tcx>) {
        self.super_terminator(block, terminator);
    }

    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
        self.super_rvalue(rvalue);
    }

    fn visit_operand(&mut self, operand: &Operand<'tcx>) {
        self.super_operand(operand);
    }

    fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext) {
        self.super_lvalue(lvalue, context);
    }

    fn visit_branch(&mut self, source: BasicBlock, target: BasicBlock) {
        self.super_branch(source, target);
    }

    fn visit_constant(&mut self, constant: &Constant<'tcx>) {
        self.super_constant(constant);
    }

    fn visit_literal(&mut self, literal: &Literal<'tcx>) {
        self.super_literal(literal);
    }

    fn visit_def_id(&mut self, def_id: DefId) {
        self.super_def_id(def_id);
    }

    fn visit_span(&mut self, span: Span) {
        self.super_span(span);
    }

    // The `super_xxx` methods comprise the default behavior and are
    // not meant to be overidden.

    fn super_mir(&mut self, mir: &Mir<'tcx>) {
        for block in mir.all_basic_blocks() {
            let data = mir.basic_block_data(block);
            self.visit_basic_block_data(block, data);
        }
    }

    fn super_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
        for statement in &data.statements {
            self.visit_statement(block, statement);
        }
        self.visit_terminator(block, &data.terminator);
    }

    fn super_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>) {
        self.visit_span(statement.span);

        match statement.kind {
            StatementKind::Assign(ref lvalue, ref rvalue) => {
                self.visit_assign(block, lvalue, rvalue);
            }
            StatementKind::Drop(_, ref lvalue) => {
                self.visit_lvalue(lvalue, LvalueContext::Drop);
            }
        }
    }

    fn super_assign(&mut self, _block: BasicBlock, lvalue: &Lvalue<'tcx>, rvalue: &Rvalue<'tcx>) {
        self.visit_lvalue(lvalue, LvalueContext::Store);
        self.visit_rvalue(rvalue);
    }

    fn super_terminator(&mut self, block: BasicBlock, terminator: &Terminator<'tcx>) {
        match *terminator {
            Terminator::Goto { target } |
            Terminator::Panic { target } => {
                self.visit_branch(block, target);
            }

            Terminator::If { ref cond, ref targets } => {
                self.visit_operand(cond);
                for &target in targets.as_slice() {
                    self.visit_branch(block, target);
                }
            }

            Terminator::Switch { ref discr, adt_def: _, ref targets } => {
                self.visit_lvalue(discr, LvalueContext::Inspect);
                for &target in targets {
                    self.visit_branch(block, target);
                }
            }

            Terminator::SwitchInt { ref discr, switch_ty: _, values: _, ref targets } => {
                self.visit_lvalue(discr, LvalueContext::Inspect);
                for &target in targets {
                    self.visit_branch(block, target);
                }
            }

            Terminator::Diverge |
            Terminator::Return => {
            }

            Terminator::Call { ref data, ref targets } => {
                self.visit_lvalue(&data.destination, LvalueContext::Store);
                self.visit_operand(&data.func);
                for arg in &data.args {
                    self.visit_operand(arg);
                }
                for &target in targets.as_slice() {
                    self.visit_branch(block, target);
                }
            }
        }
    }

    fn super_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
        match *rvalue {
            Rvalue::Use(ref operand) => {
                self.visit_operand(operand);
            }

            Rvalue::Repeat(ref value, ref len) => {
                self.visit_operand(value);
                self.visit_constant(len);
            }

            Rvalue::Ref(r, bk, ref path) => {
                self.visit_lvalue(path, LvalueContext::Borrow {
                    region: r,
                    kind: bk
                });
            }

            Rvalue::Len(ref path) => {
                self.visit_lvalue(path, LvalueContext::Inspect);
            }

            Rvalue::Cast(_, ref operand, _) => {
                self.visit_operand(operand);
            }

            Rvalue::BinaryOp(_, ref lhs, ref rhs) => {
                self.visit_operand(lhs);
                self.visit_operand(rhs);
            }

            Rvalue::UnaryOp(_, ref op) => {
                self.visit_operand(op);
            }

            Rvalue::Box(_) => {
            }

            Rvalue::Aggregate(_, ref operands) => {
                for operand in operands {
                    self.visit_operand(operand);
                }
            }

            Rvalue::Slice { ref input, from_start, from_end } => {
                self.visit_lvalue(input, LvalueContext::Slice {
                    from_start: from_start,
                    from_end: from_end,
                });
            }

            Rvalue::InlineAsm(_) => {
            }
        }
    }

    fn super_operand(&mut self, operand: &Operand<'tcx>) {
        match *operand {
            Operand::Consume(ref lvalue) => {
                self.visit_lvalue(lvalue, LvalueContext::Consume);
            }
            Operand::Constant(ref constant) => {
                self.visit_constant(constant);
            }
        }
    }

    fn super_lvalue(&mut self, lvalue: &Lvalue<'tcx>, _context: LvalueContext) {
        match *lvalue {
            Lvalue::Var(_) |
            Lvalue::Temp(_) |
            Lvalue::Arg(_) |
            Lvalue::Static(_) |
            Lvalue::ReturnPointer => {
            }
            Lvalue::Projection(ref proj) => {
                self.visit_lvalue(&proj.base, LvalueContext::Projection);
            }
        }
    }

    fn super_branch(&mut self, _source: BasicBlock, _target: BasicBlock) {
    }

    fn super_constant(&mut self, constant: &Constant<'tcx>) {
        self.visit_span(constant.span);
        self.visit_literal(&constant.literal);
    }

    fn super_literal(&mut self, literal: &Literal<'tcx>) {
        match *literal {
            Literal::Item { def_id, .. } => {
                self.visit_def_id(def_id);
            },
            Literal::Value { .. } => {
                // Nothing to do
            }
        }
    }

    fn super_def_id(&mut self, _def_id: DefId) {
    }

    fn super_span(&mut self, _span: Span) {
    }
}

#[derive(Copy, Clone, Debug)]
pub enum LvalueContext {
    // Appears as LHS of an assignment or as dest of a call
    Store,

    // Being dropped
    Drop,

    // Being inspected in some way, like loading a len
    Inspect,

    // Being borrowed
    Borrow { region: Region, kind: BorrowKind },

    // Being sliced -- this should be same as being borrowed, probably
    Slice { from_start: usize, from_end: usize },

    // Used as base for another lvalue, e.g. `x` in `x.y`
    Projection,

    // Consumed as part of an operand
    Consume,
}
<commit_msg>Add a MIR visitor that allows to mutate the visited data<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use middle::def_id::DefId;
use middle::ty::Region;
use mir::repr::*;
use rustc_data_structures::tuple_slice::TupleSlice;
use syntax::codemap::Span;

pub trait Visitor<'tcx> {
    // Override these, and call `self.super_xxx` to revert back to the
    // default behavior.

    fn visit_mir(&mut self, mir: &Mir<'tcx>) {
        self.super_mir(mir);
    }

    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
        self.super_basic_block_data(block, data);
    }

    fn visit_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>) {
        self.super_statement(block, statement);
    }

    fn visit_assign(&mut self, block: BasicBlock, lvalue: &Lvalue<'tcx>, rvalue: &Rvalue<'tcx>) {
        self.super_assign(block, lvalue, rvalue);
    }

    fn visit_terminator(&mut self, block: BasicBlock, terminator: &Terminator<'tcx>) {
        self.super_terminator(block, terminator);
    }

    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
        self.super_rvalue(rvalue);
    }

    fn visit_operand(&mut self, operand: &Operand<'tcx>) {
        self.super_operand(operand);
    }

    fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext) {
        self.super_lvalue(lvalue, context);
    }

    fn visit_branch(&mut self, source: BasicBlock, target: BasicBlock) {
        self.super_branch(source, target);
    }

    fn visit_constant(&mut self, constant: &Constant<'tcx>) {
        self.super_constant(constant);
    }

    fn visit_literal(&mut self, literal: &Literal<'tcx>) {
        self.super_literal(literal);
    }

    fn visit_def_id(&mut self, def_id: DefId) {
        self.super_def_id(def_id);
    }

    fn visit_span(&mut self, span: Span) {
        self.super_span(span);
    }

    // The `super_xxx` methods comprise the default behavior and are
    // not meant to be overidden.

    fn super_mir(&mut self, mir: &Mir<'tcx>) {
        for block in mir.all_basic_blocks() {
            let data = mir.basic_block_data(block);
            self.visit_basic_block_data(block, data);
        }
    }

    fn super_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
        for statement in &data.statements {
            self.visit_statement(block, statement);
        }
        self.visit_terminator(block, &data.terminator);
    }

    fn super_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>) {
        self.visit_span(statement.span);

        match statement.kind {
            StatementKind::Assign(ref lvalue, ref rvalue) => {
                self.visit_assign(block, lvalue, rvalue);
            }
            StatementKind::Drop(_, ref lvalue) => {
                self.visit_lvalue(lvalue, LvalueContext::Drop);
            }
        }
    }

    fn super_assign(&mut self, _block: BasicBlock, lvalue: &Lvalue<'tcx>, rvalue: &Rvalue<'tcx>) {
        self.visit_lvalue(lvalue, LvalueContext::Store);
        self.visit_rvalue(rvalue);
    }

    fn super_terminator(&mut self, block: BasicBlock, terminator: &Terminator<'tcx>) {
        match *terminator {
            Terminator::Goto { target } |
            Terminator::Panic { target } => {
                self.visit_branch(block, target);
            }

            Terminator::If { ref cond, ref targets } => {
                self.visit_operand(cond);
                for &target in targets.as_slice() {
                    self.visit_branch(block, target);
                }
            }

            Terminator::Switch { ref discr, adt_def: _, ref targets } => {
                self.visit_lvalue(discr, LvalueContext::Inspect);
                for &target in targets {
                    self.visit_branch(block, target);
                }
            }

            Terminator::SwitchInt { ref discr, switch_ty: _, values: _, ref targets } => {
                self.visit_lvalue(discr, LvalueContext::Inspect);
                for &target in targets {
                    self.visit_branch(block, target);
                }
            }

            Terminator::Diverge |
            Terminator::Return => {
            }

            Terminator::Call { ref data, ref targets } => {
                self.visit_lvalue(&data.destination, LvalueContext::Store);
                self.visit_operand(&data.func);
                for arg in &data.args {
                    self.visit_operand(arg);
                }
                for &target in targets.as_slice() {
                    self.visit_branch(block, target);
                }
            }
        }
    }

    fn super_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
        match *rvalue {
            Rvalue::Use(ref operand) => {
                self.visit_operand(operand);
            }

            Rvalue::Repeat(ref value, ref len) => {
                self.visit_operand(value);
                self.visit_constant(len);
            }

            Rvalue::Ref(r, bk, ref path) => {
                self.visit_lvalue(path, LvalueContext::Borrow {
                    region: r,
                    kind: bk
                });
            }

            Rvalue::Len(ref path) => {
                self.visit_lvalue(path, LvalueContext::Inspect);
            }

            Rvalue::Cast(_, ref operand, _) => {
                self.visit_operand(operand);
            }

            Rvalue::BinaryOp(_, ref lhs, ref rhs) => {
                self.visit_operand(lhs);
                self.visit_operand(rhs);
            }

            Rvalue::UnaryOp(_, ref op) => {
                self.visit_operand(op);
            }

            Rvalue::Box(_) => {
            }

            Rvalue::Aggregate(_, ref operands) => {
                for operand in operands {
                    self.visit_operand(operand);
                }
            }

            Rvalue::Slice { ref input, from_start, from_end } => {
                self.visit_lvalue(input, LvalueContext::Slice {
                    from_start: from_start,
                    from_end: from_end,
                });
            }

            Rvalue::InlineAsm(_) => {
            }
        }
    }

    fn super_operand(&mut self, operand: &Operand<'tcx>) {
        match *operand {
            Operand::Consume(ref lvalue) => {
                self.visit_lvalue(lvalue, LvalueContext::Consume);
            }
            Operand::Constant(ref constant) => {
                self.visit_constant(constant);
            }
        }
    }

    fn super_lvalue(&mut self, lvalue: &Lvalue<'tcx>, _context: LvalueContext) {
        match *lvalue {
            Lvalue::Var(_) |
            Lvalue::Temp(_) |
            Lvalue::Arg(_) |
            Lvalue::Static(_) |
            Lvalue::ReturnPointer => {
            }
            Lvalue::Projection(ref proj) => {
                self.visit_lvalue(&proj.base, LvalueContext::Projection);
            }
        }
    }

    fn super_branch(&mut self, _source: BasicBlock, _target: BasicBlock) {
    }

    fn super_constant(&mut self, constant: &Constant<'tcx>) {
        self.visit_span(constant.span);
        self.visit_literal(&constant.literal);
    }

    fn super_literal(&mut self, literal: &Literal<'tcx>) {
        match *literal {
            Literal::Item { def_id, .. } => {
                self.visit_def_id(def_id);
            },
            Literal::Value { .. } => {
                // Nothing to do
            }
        }
    }

    fn super_def_id(&mut self, _def_id: DefId) {
    }

    fn super_span(&mut self, _span: Span) {
    }
}

#[derive(Copy, Clone, Debug)]
pub enum LvalueContext {
    // Appears as LHS of an assignment or as dest of a call
    Store,

    // Being dropped
    Drop,

    // Being inspected in some way, like loading a len
    Inspect,

    // Being borrowed
    Borrow { region: Region, kind: BorrowKind },

    // Being sliced -- this should be same as being borrowed, probably
    Slice { from_start: usize, from_end: usize },

    // Used as base for another lvalue, e.g. `x` in `x.y`
    Projection,

    // Consumed as part of an operand
    Consume,
}

pub trait MutVisitor<'tcx> {
    // Override these, and call `self.super_xxx` to revert back to the
    // default behavior.

    fn visit_mir(&mut self, mir: &mut Mir<'tcx>) {
        self.super_mir(mir);
    }

    fn visit_basic_block_data(&mut self,
                              block: BasicBlock,
                              data: &mut BasicBlockData<'tcx>) {
        self.super_basic_block_data(block, data);
    }

    fn visit_statement(&mut self,
                       block: BasicBlock,
                       statement: &mut Statement<'tcx>) {
        self.super_statement(block, statement);
    }

    fn visit_assign(&mut self,
                    block: BasicBlock,
                    lvalue: &mut Lvalue<'tcx>,
                    rvalue: &mut Rvalue<'tcx>) {
        self.super_assign(block, lvalue, rvalue);
    }

    fn visit_terminator(&mut self,
                        block: BasicBlock,
                        terminator: &mut Terminator<'tcx>) {
        self.super_terminator(block, terminator);
    }

    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
        self.super_rvalue(rvalue);
    }

    fn visit_operand(&mut self, operand: &mut Operand<'tcx>) {
        self.super_operand(operand);
    }

    fn visit_lvalue(&mut self,
                    lvalue: &mut Lvalue<'tcx>,
                    context: LvalueContext) {
        self.super_lvalue(lvalue, context);
    }

    fn visit_branch(&mut self, source: BasicBlock, target: BasicBlock) {
        self.super_branch(source, target);
    }

    fn visit_constant(&mut self, constant: &mut Constant<'tcx>) {
        self.super_constant(constant);
    }

    fn visit_literal(&mut self, literal: &mut Literal<'tcx>) {
        self.super_literal(literal);
    }

    fn visit_def_id(&mut self, def_id: &mut DefId) {
        self.super_def_id(def_id);
    }

    fn visit_span(&mut self, span: &mut Span) {
        self.super_span(span);
    }

    // The `super_xxx` methods comprise the default behavior and are
    // not meant to be overidden.

    fn super_mir(&mut self, mir: &mut Mir<'tcx>) {
        for block in mir.all_basic_blocks() {
            let data = mir.basic_block_data_mut(block);
            self.visit_basic_block_data(block, data);
        }
    }

    fn super_basic_block_data(&mut self,
                              block: BasicBlock,
                              data: &mut BasicBlockData<'tcx>) {
        for statement in &mut data.statements {
            self.visit_statement(block, statement);
        }
        self.visit_terminator(block, &mut data.terminator);
    }

    fn super_statement(&mut self,
                       block: BasicBlock,
                       statement: &mut Statement<'tcx>) {
        self.visit_span(&mut statement.span);

        match statement.kind {
            StatementKind::Assign(ref mut lvalue, ref mut rvalue) => {
                self.visit_assign(block, lvalue, rvalue);
            }
            StatementKind::Drop(_, ref mut lvalue) => {
                self.visit_lvalue(lvalue, LvalueContext::Drop);
            }
        }
    }

    fn super_assign(&mut self,
                    _block: BasicBlock,
                    lvalue: &mut Lvalue<'tcx>,
                    rvalue: &mut Rvalue<'tcx>) {
        self.visit_lvalue(lvalue, LvalueContext::Store);
        self.visit_rvalue(rvalue);
    }

    fn super_terminator(&mut self,
                        block: BasicBlock,
                        terminator: &mut Terminator<'tcx>) {
        match *terminator {
            Terminator::Goto { target } |
            Terminator::Panic { target } => {
                self.visit_branch(block, target);
            }

            Terminator::If { ref mut cond, ref mut targets } => {
                self.visit_operand(cond);
                for &target in targets.as_slice() {
                    self.visit_branch(block, target);
                }
            }

            Terminator::Switch { ref mut discr, adt_def: _, ref targets } => {
                self.visit_lvalue(discr, LvalueContext::Inspect);
                for &target in targets {
                    self.visit_branch(block, target);
                }
            }

            Terminator::SwitchInt { ref mut discr, switch_ty: _, values: _, ref targets } => {
                self.visit_lvalue(discr, LvalueContext::Inspect);
                for &target in targets {
                    self.visit_branch(block, target);
                }
            }

            Terminator::Diverge |
            Terminator::Return => {
            }

            Terminator::Call { ref mut data, ref mut targets } => {
                self.visit_lvalue(&mut data.destination, LvalueContext::Store);
                self.visit_operand(&mut data.func);
                for arg in &mut data.args {
                    self.visit_operand(arg);
                }
                for &target in targets.as_slice() {
                    self.visit_branch(block, target);
                }
            }
        }
    }

    fn super_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
        match *rvalue {
            Rvalue::Use(ref mut operand) => {
                self.visit_operand(operand);
            }

            Rvalue::Repeat(ref mut value, ref mut len) => {
                self.visit_operand(value);
                self.visit_constant(len);
            }

            Rvalue::Ref(r, bk, ref mut path) => {
                self.visit_lvalue(path, LvalueContext::Borrow {
                    region: r,
                    kind: bk
                });
            }

            Rvalue::Len(ref mut path) => {
                self.visit_lvalue(path, LvalueContext::Inspect);
            }

            Rvalue::Cast(_, ref mut operand, _) => {
                self.visit_operand(operand);
            }

            Rvalue::BinaryOp(_, ref mut lhs, ref mut rhs) => {
                self.visit_operand(lhs);
                self.visit_operand(rhs);
            }

            Rvalue::UnaryOp(_, ref mut op) => {
                self.visit_operand(op);
            }

            Rvalue::Box(_) => {
            }

            Rvalue::Aggregate(ref mut kind, ref mut operands) => {
                match *kind {
                    AggregateKind::Closure(ref mut def_id, _) => {
                        self.visit_def_id(def_id);
                    }
                    _ => { /* nothing to do */ }
                }

                for operand in &mut operands[..] {
                    self.visit_operand(operand);
                }
            }

            Rvalue::Slice { ref mut input, from_start, from_end } => {
                self.visit_lvalue(input, LvalueContext::Slice {
                    from_start: from_start,
                    from_end: from_end,
                });
            }

            Rvalue::InlineAsm(_) => {
            }
        }
    }

    fn super_operand(&mut self, operand: &mut Operand<'tcx>) {
        match *operand {
            Operand::Consume(ref mut lvalue) => {
                self.visit_lvalue(lvalue, LvalueContext::Consume);
            }
            Operand::Constant(ref mut constant) => {
                self.visit_constant(constant);
            }
        }
    }

    fn super_lvalue(&mut self,
                    lvalue: &mut Lvalue<'tcx>,
                    _context: LvalueContext) {
        match *lvalue {
            Lvalue::Var(_) |
            Lvalue::Temp(_) |
            Lvalue::Arg(_) |
            Lvalue::ReturnPointer => {
            }
            Lvalue::Static(ref mut def_id) => {
                self.visit_def_id(def_id);
            }
            Lvalue::Projection(ref mut proj) => {
                self.visit_lvalue(&mut proj.base, LvalueContext::Projection);
            }
        }
    }

    fn super_branch(&mut self, _source: BasicBlock, _target: BasicBlock) {
    }

    fn super_constant(&mut self, constant: &mut Constant<'tcx>) {
        self.visit_span(&mut constant.span);
        self.visit_literal(&mut constant.literal);
    }

    fn super_literal(&mut self, literal: &mut Literal<'tcx>) {
        match *literal {
            Literal::Item { ref mut def_id, .. } => {
                self.visit_def_id(def_id);
            },
            Literal::Value { .. } => {
                // Nothing to do
            }
        }
    }

    fn super_def_id(&mut self, _def_id: &mut DefId) {
    }

    fn super_span(&mut self, _span: &mut Span) {
    }
}
<|endoftext|>