<commit_before>/// Implements the actual raytracer which produces the final image
use std::num::Float;
use std::old_io;
use std::old_io::stdio;
use std::ops::{Drop, Deref};
use std::sync::{TaskPool, Arc};
use std::default::Default;
use std::iter::range_step;
use std::sync::mpsc::sync_channel;
use super::vec::{Vector, RFloat};
use super::group::SphericalGroup;
use super::primitive::{Intersectable, Ray, Hit};

pub trait RGBABufferWriter {
    /// To be called before writing the first pixel
    /// x and y are the total image resolution
    fn begin(&mut self, x: u16, y: u16);

    /// Write the given RGBA buffer - it's image region might be anywhere within
    /// our confines of total x and y resolution.
    /// This must be assured by the caller
    /// Color range is 0.0 to 1.0, everything higher is truncated
    fn write_rgba_buffer(&mut self, buffer: &RGBABuffer);
}

#[derive(Copy)]
pub struct RenderOptions {
    pub width: u16,
    pub height: u16,
    pub samples_per_pixel: u16,
}

pub struct Renderer;

#[derive(Copy, PartialEq)]
pub struct ImageRegion {
    l: u16,
    t: u16,
    r: u16,
    b: u16,
}

impl ImageRegion {
    pub fn width(&self) -> u16 {
        self.r - self.l
    }

    pub fn height(&self) -> u16 {
        self.t - self.b
    }

    pub fn area(&self) -> usize {
        self.width() as usize * self.height() as usize
    }

    pub fn contains(&self, o: &ImageRegion) -> bool {
        return  o.l >= self.l &&
                o.b >= self.b &&
                o.t <= self.t &&
                o.r <= self.r
    }

    /// x and y absolute to our rectangle ! Returns offset relative to our buffer
    #[inline]
    pub fn buffer_offset(&self, x: u16, y: u16) -> usize {
        (y - self.b) as usize * self.width() as usize + (x - self.l) as usize
    }
}

pub struct RGBABuffer {
    buf: Vec<u8>,
    reg: ImageRegion,
}

impl RGBABuffer {
    fn new(r: &ImageRegion) -> RGBABuffer {
        let mut v = Vec::with_capacity(r.area() * 4);
        let l = v.capacity();
        unsafe {v.set_len(l)};
        RGBABuffer {
            buf: v,
            reg: *r,
        }
    }

    fn components() -> usize {
        4
    }

    /// x and y must be absolute to our recangle !
    fn set_pixel_from_vector(&mut self, x: u16, y: u16, p: &Vector, alpha: RFloat) {
        let ofs = self.reg.buffer_offset(x, y) * RGBABuffer::components();
        let c = &mut self.buf[ofs .. ofs + RGBABuffer::components()];

        let scale = |v| -> u8 {

            let r = 0.5 + 255.0 * v;
            if r > 255.0 {
                return 255;
            }
            r as u8
        };

        c[0] = scale(p.x);
        c[1] = scale(p.y);
        c[2] = scale(p.z);
        c[3] = scale(alpha);
    }

    /// buffer must be contained in our rectangle
    fn set_pixels_from_buffer(&mut self, b: &RGBABuffer) {
        assert!(self.reg.contains(&b.reg));
        let w = b.reg.width() as usize * RGBABuffer::components();

        if self.reg == b.reg {
            self.buf = b.buf.clone();
            return;
        }

        for y in range(b.reg.b, b.reg.t) {
            let bl = self.reg.buffer_offset(b.reg.l, y) * RGBABuffer::components(); // bottom_left
            let their_bl = b.reg.buffer_offset(b.reg.l, y) * RGBABuffer::components();
            self.buf[bl .. bl + w].clone_from_slice(&b.buf[their_bl .. their_bl + w]);
        }
    }

    fn buffer(&self) -> &Vec<u8> {
        &self.buf
    }

    fn region(&self) -> &ImageRegion {
        &self.reg
    }
}

pub struct Scene {
    pub group: SphericalGroup,
    pub directional_light: Vector,
    pub eye: Vector,
}

impl Default for Scene {
    fn default() -> Scene {
        Scene {
            group: SphericalGroup::pyramid(8, &Vector { x: 0.0,
                                                        y: -1.0,
                                                        z: 0.0 }, 1.0),
            directional_light: Vector { x: -1.0, y: -3.0, z: 2.0 }.normalized(),
            eye: Vector { x: 0.0, y: 0.0, z: -4.0 }
        }
    }
}

impl Renderer {

    #[inline]
    fn raytrace(s: &Scene, r: &Ray, c: &mut Vector) -> RFloat {
        let mut h = Hit::missed();
        s.group.intersect(&mut h, r);
        if h.has_missed() {
            return 0.0;
        }
        let g = h.pos.dot(&s.directional_light);
        if g >= 0.0 {
            return 0.0;
        }
        let p = r.pos +
                    (r.dir.mulfed(h.distance)) +
                    *h.pos.mulf(h.distance * <RFloat as Float>::epsilon().sqrt());

        // if there is something between us and the light, we are in shadow
        h.set_missed();
        s.group.intersect(&mut h,
                          &Ray { pos: p,
                                  dir: s.directional_light.mulfed(-1.0) });
        if h.has_missed() {
            c.x = c.x - g;
            c.y = c.y - g;
            c.z = c.z - g;
            return 1.0;
        }

        0.0
    }

    // Render region is inherently single-threaded
    pub fn render_region(samples_per_pixel: u16, width: RFloat, height: RFloat,
                         scene: &Scene, buf: &mut RGBABuffer) {
        let ssf = samples_per_pixel as RFloat;
        let total_samples_per_pixel_recip = (ssf * ssf).recip();
        let region = *buf.region();

        let mut ray = Ray { pos: scene.eye,
                            dir: Default::default() };

        for y in range(region.b, region.t) {
            for x in range(region.l, region.r) {
                let mut g: Vector = Default::default();
                let mut alpha: RFloat = 0.0;

                for ssx in range(0, samples_per_pixel) {
                    for ssy in range(0, samples_per_pixel) {
                        let xres = x as RFloat + ssx as RFloat / ssf;
                        let yres = y as RFloat + ssy as RFloat / ssf;
                        ray.dir.x = xres - width / 2.0;
                        ray.dir.y = (height - yres) - height / 2.0;
                        ray.dir.z = width;
                        ray.dir.normalize();
                        alpha += Renderer::raytrace(scene, &ray, &mut g);

                    }//for each ss y
                }// for each ss x

                g.mulf(total_samples_per_pixel_recip);
                alpha *= total_samples_per_pixel_recip;

                buf.set_pixel_from_vector(x, y, &g, alpha);
            }// for each x
        }// for each y
    }

    // Use runtime dispatching for the image writer to remain flexible
    // (And to test this ;))
    // sets up multi-threading accordingly
    pub fn render(o: &RenderOptions, scene: Arc<Scene>, writer: &mut RGBABufferWriter,
                  pool: &TaskPool) {
        const CHUNK_SIZE: u16 = 64;
        assert!(o.width % CHUNK_SIZE == 0, "TODO: handle chunk sizes");
        assert!(o.height % CHUNK_SIZE == 0, "TODO: handle chunk sizes");

        writer.begin(o.width, o.height);

        // Push all tasks
        let (tx, rx) = sync_channel::<RGBABuffer>(4);
        let mut count = 0us;
        for y in range_step(0u16, o.height, CHUNK_SIZE)  {
            for x in range_step(0u16, o.width, CHUNK_SIZE) {

                let tx = tx.clone();
                let ss = o.samples_per_pixel;
                let w = o.width as RFloat;
                let h = o.height as RFloat;
                let tscene = scene.clone();
                count += 1;

                pool.execute(move|| {
                    let mut b = RGBABuffer::new(&ImageRegion { l: x, r: x + CHUNK_SIZE,
                                                           b: y, t: y + CHUNK_SIZE });

                    Renderer::render_region(ss, w, h, tscene.deref(), &mut b);

                    tx.send(b).ok();
                });
            }
        }

        // Read the results and pass them to the writer
        for b in rx.iter() {
            writer.write_rgba_buffer(&b);
            count -= 1;
            if count == 0 {
                break;
            }
        }
    }
}

pub struct PPMStdoutRGBABufferWriter {
    out: old_io::LineBufferedWriter<stdio::StdWriter>,
    image: Option<RGBABuffer>,
    rgb: bool,
}

impl Drop for PPMStdoutRGBABufferWriter {
    fn drop(&mut self) {
        // We always write our entire buffer - it will just be zero initially
        // That way, we can see the buckets being written in preview :) ... .
        // Can't write entire buffer :( thanks to alpha channel
        let buf = self.image.as_ref().unwrap().buffer();
        for po in range_step(0, buf.len(), RGBABuffer::components()) {
            let b = &buf[po .. po + 3];

            if self.rgb {
                self.out.write_all(b).unwrap();
            } else {
                let avg = ((b[0] as f32 + b[1] as f32 + b[2] as f32) / 3.0f32) as u8;
                self.out.write_u8(avg).unwrap();
            }
        }
    }
}

impl PPMStdoutRGBABufferWriter {
    pub fn new(write_rgb: bool) -> PPMStdoutRGBABufferWriter {
        PPMStdoutRGBABufferWriter { out: old_io::stdout(),
                               image: None,
                               rgb: write_rgb }
    }
}

impl RGBABufferWriter for PPMStdoutRGBABufferWriter {
    fn begin(&mut self, x: u16, y: u16) {
        let mut ptype: &str = "P5";
        if self.rgb {
            ptype = "P6"
        }
        self.out.write_line(ptype).unwrap();
        self.out.write_line(&format!("{} {}", x, y)[]).unwrap();
        self.out.write_line("255").unwrap();

        self.image = Some(RGBABuffer::new(&ImageRegion { l: 0, r: x, b: 0, t: y }));
    }

    fn write_rgba_buffer(&mut self, buffer: &RGBABuffer) {
        self.image.as_mut().unwrap().set_pixels_from_buffer(buffer);
    }
}

#[cfg(test)]
mod tests {
    extern crate test;

    use super::*;
    use std::sync::{TaskPool, Arc};
    use std::default::Default;

    #[derive(Default)]
    struct DummyWriter {
        begin_called: bool,
        write_count: usize,
    }

    impl RGBABufferWriter for DummyWriter {
        fn begin(&mut self, _: u16, _: u16) {
            self.begin_called = true;
        }
        fn write_rgba_buffer(&mut self, _: &RGBABuffer) {
            self.write_count += 1;
        }
    }

    const W: usize = 64;
    const H: usize = 128;

    #[test]
    fn basic_rendering() {
        let s: Arc<Scene> = Arc::new(Default::default());
        let pool = TaskPool::new(1);
        let options = RenderOptions { width: W as u16, height: H as u16, samples_per_pixel: 2 };

        let mut dw: DummyWriter = Default::default();
        Renderer::render(&options, s.clone(), &mut dw, &pool);

        assert!(dw.begin_called);
        assert_eq!(dw.write_count, 2);
    }

    #[test]
    fn image_region() {
        let r = ImageRegion { l: 2, t: 18, r: 34, b: 2 };
        assert_eq!(r.width(), 32);
        assert_eq!(r.height(), 16);
        assert_eq!(r.area(), 16*32);
        assert!(r.contains(&r));
        let mut l = r;
        l.l = 1;
        assert!(l.contains(&r));
        assert!(!r.contains(&l));
    }

    #[bench]
    fn bench_rendering(b: &mut test::Bencher) {
        const SPP: usize = 1;
        let pool = TaskPool::new(4);
        let s: Arc<Scene> = Arc::new(Default::default());
        let options = RenderOptions { width: H as u16, height: H as u16, samples_per_pixel: SPP as u16 };

        let mut dw: DummyWriter = Default::default();
        b.iter(|| {
            Renderer::render(&options, s.clone(), &mut dw, &pool);
        });
        b.bytes += (H * H * SPP * SPP) as u64;
    }
}<commit_msg>Minor cleanup<commit_after>/// Implements the actual raytracer which produces the final image
use std::num::Float;
use std::old_io;
use std::old_io::stdio;
use std::ops::{Drop, Deref};
use std::sync::{TaskPool, Arc};
use std::default::Default;
use std::iter::range_step;
use std::sync::mpsc::sync_channel;
use super::vec::{Vector, RFloat};
use super::group::SphericalGroup;
use super::primitive::{Intersectable, Ray, Hit};

pub trait RGBABufferWriter {
    /// To be called before writing the first pixel
    /// x and y are the total image resolution
    fn begin(&mut self, x: u16, y: u16);

    /// Write the given RGBA buffer - it's image region might be anywhere within
    /// our confines of total x and y resolution.
    /// This must be assured by the caller
    /// Color range is 0.0 to 1.0, everything higher is truncated
    fn write_rgba_buffer(&mut self, buffer: &RGBABuffer);
}

#[derive(Copy)]
pub struct RenderOptions {
    pub width: u16,
    pub height: u16,
    pub samples_per_pixel: u16,
}

pub struct Renderer;

#[derive(Copy, PartialEq)]
pub struct ImageRegion {
    l: u16,
    t: u16,
    r: u16,
    b: u16,
}

impl ImageRegion {
    pub fn width(&self) -> u16 {
        self.r - self.l
    }

    pub fn height(&self) -> u16 {
        self.t - self.b
    }

    pub fn area(&self) -> usize {
        self.width() as usize * self.height() as usize
    }

    pub fn contains(&self, o: &ImageRegion) -> bool {
        return  o.l >= self.l &&
                o.b >= self.b &&
                o.t <= self.t &&
                o.r <= self.r
    }

    /// x and y absolute to our rectangle ! Returns offset relative to our buffer
    #[inline]
    pub fn buffer_offset(&self, x: u16, y: u16) -> usize {
        (y - self.b) as usize * self.width() as usize + (x - self.l) as usize
    }
}

pub struct RGBABuffer {
    buf: Vec<u8>,
    reg: ImageRegion,
}

impl RGBABuffer {
    fn new(r: &ImageRegion) -> RGBABuffer {
        let mut v = Vec::with_capacity(r.area() * 4);
        let l = v.capacity();
        unsafe {v.set_len(l)};
        RGBABuffer {
            buf: v,
            reg: *r,
        }
    }

    fn components() -> usize {
        4
    }

    /// x and y must be absolute to our recangle !
    fn set_pixel_from_vector(&mut self, x: u16, y: u16, p: &Vector, alpha: RFloat) {
        let ofs = self.reg.buffer_offset(x, y) * RGBABuffer::components();
        let c = &mut self.buf[ofs .. ofs + RGBABuffer::components()];

        let scale = |v| -> u8 {

            let r = 0.5 + 255.0 * v;
            if r > 255.0 {
                return 255;
            }
            r as u8
        };

        c[0] = scale(p.x);
        c[1] = scale(p.y);
        c[2] = scale(p.z);
        c[3] = scale(alpha);
    }

    /// buffer must be contained in our rectangle
    fn set_pixels_from_buffer(&mut self, b: &RGBABuffer) {
        assert!(self.reg.contains(&b.reg));
        let w = b.reg.width() as usize * RGBABuffer::components();

        if self.reg == b.reg {
            self.buf = b.buf.clone();
            return;
        }

        for y in range(b.reg.b, b.reg.t) {
            let bl = self.reg.buffer_offset(b.reg.l, y) * RGBABuffer::components(); // bottom_left
            let their_bl = b.reg.buffer_offset(b.reg.l, y) * RGBABuffer::components();
            self.buf[bl .. bl + w].clone_from_slice(&b.buf[their_bl .. their_bl + w]);
        }
    }

    fn buffer(&self) -> &Vec<u8> {
        &self.buf
    }

    fn region(&self) -> &ImageRegion {
        &self.reg
    }
}

pub struct Scene {
    pub group: SphericalGroup,
    pub directional_light: Vector,
    pub eye: Vector,
}

impl Default for Scene {
    fn default() -> Scene {
        Scene {
            group: SphericalGroup::pyramid(8, &Vector { x: 0.0,
                                                        y: -1.0,
                                                        z: 0.0 }, 1.0),
            directional_light: Vector { x: -1.0, y: -3.0, z: 2.0 }.normalized(),
            eye: Vector { x: 0.0, y: 0.0, z: -4.0 }
        }
    }
}

impl Renderer {

    #[inline]
    fn raytrace(s: &Scene, r: &Ray, c: &mut Vector) -> RFloat {
        let mut h = Hit::missed();
        s.group.intersect(&mut h, r);
        if h.has_missed() {
            return 0.0;
        }
        let g = h.pos.dot(&s.directional_light);
        if g >= 0.0 {
            return 0.0;
        }
        let p = r.pos +
                    (r.dir.mulfed(h.distance)) +
                    *h.pos.mulf(h.distance * <RFloat as Float>::epsilon().sqrt());

        // if there is something between us and the light, we are in shadow
        h.set_missed();
        s.group.intersect(&mut h,
                          &Ray { pos: p,
                                  dir: s.directional_light.mulfed(-1.0) });
        if h.has_missed() {
            c.x = c.x - g;
            c.y = c.y - g;
            c.z = c.z - g;
            return 1.0;
        }

        0.0
    }

    // Render region is inherently single-threaded
    pub fn render_region(o: &RenderOptions, scene: &Scene, buf: &mut RGBABuffer) {
        let ssf = o.samples_per_pixel as RFloat;
        let total_samples_per_pixel_recip = (ssf * ssf).recip();
        let region = *buf.region();

        let width = o.width as RFloat;
        let height = o.height as RFloat;

        let mut ray = Ray { pos: scene.eye,
                            dir: Default::default() };

        for y in range(region.b, region.t) {
            for x in range(region.l, region.r) {
                let mut g: Vector = Default::default();
                let mut alpha: RFloat = 0.0;

                for ssx in range(0, o.samples_per_pixel) {
                    for ssy in range(0, o.samples_per_pixel) {
                        let xres = x as RFloat + ssx as RFloat / ssf;
                        let yres = y as RFloat + ssy as RFloat / ssf;
                        ray.dir.x = xres - width / 2.0;
                        ray.dir.y = (height - yres) - height / 2.0;
                        ray.dir.z = width;
                        ray.dir.normalize();
                        alpha += Renderer::raytrace(scene, &ray, &mut g);

                    }//for each ss y
                }// for each ss x

                g.mulf(total_samples_per_pixel_recip);
                alpha *= total_samples_per_pixel_recip;

                buf.set_pixel_from_vector(x, y, &g, alpha);
            }// for each x
        }// for each y
    }

    // Use runtime dispatching for the image writer to remain flexible
    // (And to test this ;))
    // sets up multi-threading accordingly
    pub fn render(o: &RenderOptions, scene: Arc<Scene>, writer: &mut RGBABufferWriter,
                  pool: &TaskPool) {
        const CHUNK_SIZE: u16 = 64;
        assert!(o.width % CHUNK_SIZE == 0, "TODO: handle chunk sizes");
        assert!(o.height % CHUNK_SIZE == 0, "TODO: handle chunk sizes");

        writer.begin(o.width, o.height);

        // Push all tasks
        let (tx, rx) = sync_channel::<RGBABuffer>(4);
        let mut count = 0us;
        for y in range_step(0u16, o.height, CHUNK_SIZE)  {
            for x in range_step(0u16, o.width, CHUNK_SIZE) {

                let tx = tx.clone();
                let opts = *o;
                let tscene = scene.clone();

                count += 1;

                pool.execute(move|| {
                    let mut b = RGBABuffer::new(&ImageRegion { l: x, r: x + CHUNK_SIZE,
                                                           b: y, t: y + CHUNK_SIZE });

                    Renderer::render_region(&opts, tscene.deref(), &mut b);

                    tx.send(b).ok();
                });
            }
        }

        // Read the results and pass them to the writer
        for b in rx.iter() {
            writer.write_rgba_buffer(&b);
            count -= 1;
            if count == 0 {
                break;
            }
        }
    }
}

pub struct PPMStdoutRGBABufferWriter {
    out: old_io::LineBufferedWriter<stdio::StdWriter>,
    image: Option<RGBABuffer>,
    rgb: bool,
}

impl Drop for PPMStdoutRGBABufferWriter {
    fn drop(&mut self) {
        // We always write our entire buffer - it will just be zero initially
        // Can't write entire buffer :( thanks to alpha channel
        let buf = self.image.as_ref().unwrap().buffer();
        for po in range_step(0, buf.len(), RGBABuffer::components()) {
            let b = &buf[po .. po + 3];

            if self.rgb {
                self.out.write_all(b).unwrap();
            } else {
                let avg = ((b[0] as f32 + b[1] as f32 + b[2] as f32) / 3.0f32) as u8;
                self.out.write_u8(avg).unwrap();
            }
        }
    }
}

impl PPMStdoutRGBABufferWriter {
    pub fn new(write_rgb: bool) -> PPMStdoutRGBABufferWriter {
        PPMStdoutRGBABufferWriter { out: old_io::stdout(),
                               image: None,
                               rgb: write_rgb }
    }
}

impl RGBABufferWriter for PPMStdoutRGBABufferWriter {
    fn begin(&mut self, x: u16, y: u16) {
        let mut ptype: &str = "P5";
        if self.rgb {
            ptype = "P6"
        }
        self.out.write_line(ptype).unwrap();
        self.out.write_line(&format!("{} {}", x, y)[]).unwrap();
        self.out.write_line("255").unwrap();

        self.image = Some(RGBABuffer::new(&ImageRegion { l: 0, r: x, b: 0, t: y }));
    }

    fn write_rgba_buffer(&mut self, buffer: &RGBABuffer) {
        self.image.as_mut().unwrap().set_pixels_from_buffer(buffer);
    }
}

#[cfg(test)]
mod tests {
    extern crate test;

    use super::*;
    use std::sync::{TaskPool, Arc};
    use std::default::Default;

    #[derive(Default)]
    struct DummyWriter {
        begin_called: bool,
        write_count: usize,
    }

    impl RGBABufferWriter for DummyWriter {
        fn begin(&mut self, _: u16, _: u16) {
            self.begin_called = true;
        }
        fn write_rgba_buffer(&mut self, _: &RGBABuffer) {
            self.write_count += 1;
        }
    }

    const W: usize = 64;
    const H: usize = 128;

    #[test]
    fn basic_rendering() {
        let s: Arc<Scene> = Arc::new(Default::default());
        let pool = TaskPool::new(1);
        let options = RenderOptions { width: W as u16, height: H as u16, samples_per_pixel: 2 };

        let mut dw: DummyWriter = Default::default();
        Renderer::render(&options, s.clone(), &mut dw, &pool);

        assert!(dw.begin_called);
        assert_eq!(dw.write_count, 2);
    }

    #[test]
    fn image_region() {
        let r = ImageRegion { l: 2, t: 18, r: 34, b: 2 };
        assert_eq!(r.width(), 32);
        assert_eq!(r.height(), 16);
        assert_eq!(r.area(), 16*32);
        assert!(r.contains(&r));
        let mut l = r;
        l.l = 1;
        assert!(l.contains(&r));
        assert!(!r.contains(&l));
    }

    #[bench]
    fn bench_rendering(b: &mut test::Bencher) {
        const SPP: usize = 1;
        let pool = TaskPool::new(4);
        let s: Arc<Scene> = Arc::new(Default::default());
        let options = RenderOptions { width: H as u16, height: H as u16, samples_per_pixel: SPP as u16 };

        let mut dw: DummyWriter = Default::default();
        b.iter(|| {
            Renderer::render(&options, s.clone(), &mut dw, &pool);
        });
        b.bytes += (H * H * SPP * SPP) as u64;
    }
}<|endoftext|>


<commit_before>use alloc::string::String;
use core::mem;

#[repr(C)]
pub struct RustString {
    repr: String,
}

impl RustString {
    pub fn from(s: String) -> Self {
        RustString { repr: s }
    }

    pub fn from_ref(s: &String) -> &Self {
        unsafe { &*(s as *const String as *const RustString) }
    }

    pub fn from_mut(s: &mut String) -> &mut Self {
        unsafe { &mut *(s as *mut String as *mut RustString) }
    }

    pub fn into_string(self) -> String {
        self.repr
    }

    pub fn as_string(&self) -> &String {
        &self.repr
    }

    pub fn as_mut_string(&mut self) -> &mut String {
        &mut self.repr
    }
}

const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<String>());
const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<String>());
<commit_msg>Resolve improper ctype lint affecting RustString<commit_after>use alloc::string::String;
use core::mem::{self, MaybeUninit};

// ABI compatible with C++ rust::String (not necessarily alloc::string::String).
#[repr(C)]
pub struct RustString {
    repr: [MaybeUninit<usize>; mem::size_of::<String>() / mem::size_of::<usize>()],
}

impl RustString {
    pub fn from(s: String) -> Self {
        unsafe { mem::transmute::<String, RustString>(s) }
    }

    pub fn from_ref(s: &String) -> &Self {
        unsafe { &*(s as *const String as *const RustString) }
    }

    pub fn from_mut(s: &mut String) -> &mut Self {
        unsafe { &mut *(s as *mut String as *mut RustString) }
    }

    pub fn into_string(self) -> String {
        unsafe { mem::transmute::<RustString, String>(self) }
    }

    pub fn as_string(&self) -> &String {
        unsafe { &*(self as *const RustString as *const String) }
    }

    pub fn as_mut_string(&mut self) -> &mut String {
        unsafe { &mut *(self as *mut RustString as *mut String) }
    }
}

const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<RustString>());
const_assert_eq!(mem::size_of::<String>(), mem::size_of::<RustString>());
const_assert_eq!(mem::align_of::<String>(), mem::align_of::<RustString>());
<|endoftext|>


<commit_before>#[allow(dead_code)]
mod util;

use std::io;

use termion::event::Key;
use termion::input::MouseTerminal;
use termion::raw::IntoRawMode;
use termion::screen::AlternateScreen;
use tui::backend::TermionBackend;
use tui::style::{Color, Modifier, Style};
use tui::widgets::{Axis, Block, Borders, Chart, Dataset, Marker, Widget};
use tui::Terminal;

use crate::util::event::{Event, Events};
use crate::util::SinSignal;

struct App {
    signal1: SinSignal,
    data1: Vec<(f64, f64)>,
    signal2: SinSignal,
    data2: Vec<(f64, f64)>,
    window: [f64; 2],
}

impl App {
    fn new() -> App {
        let mut signal1 = SinSignal::new(0.2, 3.0, 18.0);
        let mut signal2 = SinSignal::new(0.1, 2.0, 10.0);
        let data1 = signal1.by_ref().take(200).collect::<Vec<(f64, f64)>>();
        let data2 = signal2.by_ref().take(200).collect::<Vec<(f64, f64)>>();
        App {
            signal1,
            data1,
            signal2,
            data2,
            window: [0.0, 20.0],
        }
    }

    fn update(&mut self) {
        for _ in 0..5 {
            self.data1.remove(0);
        }
        self.data1.extend(self.signal1.by_ref().take(5));
        for _ in 0..10 {
            self.data2.remove(0);
        }
        self.data2.extend(self.signal2.by_ref().take(10));
        self.window[0] += 1.0;
        self.window[1] += 1.0;
    }
}

fn main() -> Result<(), failure::Error> {
    // Terminal initialization
    let stdout = io::stdout().into_raw_mode()?;
    let stdout = MouseTerminal::from(stdout);
    let stdout = AlternateScreen::from(stdout);
    let backend = TermionBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;
    terminal.hide_cursor()?;

    let events = Events::new();

    // App
    let mut app = App::new();

    loop {
        terminal.draw(|mut f| {
            let size = f.size();
            Chart::default()
                .block(
                    Block::default()
                        .title("Chart")
                        .title_style(Style::default().fg(Color::Cyan).modifier(Modifier::BOLD))
                        .borders(Borders::ALL),
                )
                .x_axis(
                    Axis::default()
                        .title("X Axis")
                        .style(Style::default().fg(Color::White))
                        .labels_style(Style::default().modifier(Modifier::ITALIC))
                        .bounds(app.window)
                        .labels(&[
                            &format!("{}", app.window[0]),
                            &format!("{}", (app.window[0] + app.window[1]) / 2.0),
                            &format!("{}", app.window[1]),
                        ]),
                )
                .y_axis(
                    Axis::default()
                        .title("Y Axis")
                        .style(Style::default().fg(Color::White))
                        .labels_style(Style::default().modifier(Modifier::ITALIC))
                        .bounds([-20.0, 20.0])
                        .labels(&["-20", "0", "20"]),
                )
                .datasets(&[
                    Dataset::default()
                        .name("data2")
                        .marker(Marker::Dot)
                        .style(Style::default().fg(Color::Cyan))
                        .data(&app.data1),
                    Dataset::default()
                        .name("data3")
                        .marker(Marker::Braille)
                        .style(Style::default().fg(Color::Yellow))
                        .data(&app.data2),
                ])
                .render(&mut f, size);
        })?;

        match events.next()? {
            Event::Input(input) => {
                if input == Key::Char('q') {
                    break;
                }
            }
            Event::Tick => {
                app.update();
            }
        }
    }

    Ok(())
}
<commit_msg>Fix some examples that accidentally changed color<commit_after>#[allow(dead_code)]
mod util;

use std::io;

use termion::event::Key;
use termion::input::MouseTerminal;
use termion::raw::IntoRawMode;
use termion::screen::AlternateScreen;
use tui::backend::TermionBackend;
use tui::style::{Color, Modifier, Style};
use tui::widgets::{Axis, Block, Borders, Chart, Dataset, Marker, Widget};
use tui::Terminal;

use crate::util::event::{Event, Events};
use crate::util::SinSignal;

struct App {
    signal1: SinSignal,
    data1: Vec<(f64, f64)>,
    signal2: SinSignal,
    data2: Vec<(f64, f64)>,
    window: [f64; 2],
}

impl App {
    fn new() -> App {
        let mut signal1 = SinSignal::new(0.2, 3.0, 18.0);
        let mut signal2 = SinSignal::new(0.1, 2.0, 10.0);
        let data1 = signal1.by_ref().take(200).collect::<Vec<(f64, f64)>>();
        let data2 = signal2.by_ref().take(200).collect::<Vec<(f64, f64)>>();
        App {
            signal1,
            data1,
            signal2,
            data2,
            window: [0.0, 20.0],
        }
    }

    fn update(&mut self) {
        for _ in 0..5 {
            self.data1.remove(0);
        }
        self.data1.extend(self.signal1.by_ref().take(5));
        for _ in 0..10 {
            self.data2.remove(0);
        }
        self.data2.extend(self.signal2.by_ref().take(10));
        self.window[0] += 1.0;
        self.window[1] += 1.0;
    }
}

fn main() -> Result<(), failure::Error> {
    // Terminal initialization
    let stdout = io::stdout().into_raw_mode()?;
    let stdout = MouseTerminal::from(stdout);
    let stdout = AlternateScreen::from(stdout);
    let backend = TermionBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;
    terminal.hide_cursor()?;

    let events = Events::new();

    // App
    let mut app = App::new();

    loop {
        terminal.draw(|mut f| {
            let size = f.size();
            Chart::default()
                .block(
                    Block::default()
                        .title("Chart")
                        .title_style(Style::default().fg(Color::Cyan).modifier(Modifier::BOLD))
                        .borders(Borders::ALL),
                )
                .x_axis(
                    Axis::default()
                        .title("X Axis")
                        .style(Style::default().fg(Color::Gray))
                        .labels_style(Style::default().modifier(Modifier::ITALIC))
                        .bounds(app.window)
                        .labels(&[
                            &format!("{}", app.window[0]),
                            &format!("{}", (app.window[0] + app.window[1]) / 2.0),
                            &format!("{}", app.window[1]),
                        ]),
                )
                .y_axis(
                    Axis::default()
                        .title("Y Axis")
                        .style(Style::default().fg(Color::Gray))
                        .labels_style(Style::default().modifier(Modifier::ITALIC))
                        .bounds([-20.0, 20.0])
                        .labels(&["-20", "0", "20"]),
                )
                .datasets(&[
                    Dataset::default()
                        .name("data2")
                        .marker(Marker::Dot)
                        .style(Style::default().fg(Color::Cyan))
                        .data(&app.data1),
                    Dataset::default()
                        .name("data3")
                        .marker(Marker::Braille)
                        .style(Style::default().fg(Color::Yellow))
                        .data(&app.data2),
                ])
                .render(&mut f, size);
        })?;

        match events.next()? {
            Event::Input(input) => {
                if input == Key::Char('q') {
                    break;
                }
            }
            Event::Tick => {
                app.update();
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>#[feature(globs)];

extern mod glfw;
extern mod gl;

use std::cast;
use std::ptr;
use std::str;
use std::vec;
use std::libc;

use gl::types::*;

static vertex_shader_src : &'static str = r"
#version 110

attribute vec4 position;

varying vec2 texcoord;

void main() {
    gl_Position = position;
    texcoord = position.xy;
}
";

static fragment_shader_src : &'static str = r"
#version 110

varying vec2 texcoord;

void main() {
    gl_FragColor = vec4(texcoord, 1.0, 1.0);
}
";

#[start]
fn start(argc: int, argv: **u8) -> int {
    std::rt::start_on_main_thread(argc, argv, main)
}

fn main() {
   glfw::set_error_callback(~ErrorContext);

   let window_width = 800;
   let window_height = 600;

    do glfw::start {
        let window = glfw::Window::create(window_width, window_height, "Hello, I am a window.", glfw::Windowed)
            .expect("Failed to create GLFW window.");

        //window.set_cursor_mode(glfw::CursorDisabled);
        window.make_context_current();

        gl::load_with(glfw::get_proc_address);

        let vs = compile_shader(vertex_shader_src.as_bytes(), gl::VERTEX_SHADER);
        let fs = compile_shader(fragment_shader_src.as_bytes(), gl::FRAGMENT_SHADER);
        let program = link_program(vs, fs);

        let mut vao = 0;
        let mut vbo = 0;

        let VERTEX_DATA : ~[GLfloat] = ~[
            -1.0, -1.0, 0.0, 1.0,
            1.0, -1.0, 0.0, 1.0,
            -1.0, 1.0, 0.0, 1.0,
            1.0, 1.0, 0.0, 1.0,
        ];

        unsafe {
            // Create Vertex Array Object
            gl::GenVertexArrays(1, &mut vao);
            gl::BindVertexArray(vao);

            // Create a Vertex Buffer Object and copy the vertex data to it
            gl::GenBuffers(1, &mut vbo);
            gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
            gl::BufferData(gl::ARRAY_BUFFER,
                           (VERTEX_DATA.len() * std::mem::size_of::<GLfloat>()) as GLsizeiptr,
                           cast::transmute(&VERTEX_DATA[0]),
                           gl::STATIC_DRAW);

            // Use shader program
            gl::UseProgram(program);

            // Specify the layout of the vertex data
            let vert_attr = "position".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
            gl::EnableVertexAttribArray(vert_attr as GLuint);
            gl::VertexAttribPointer(vert_attr as GLuint, 4, gl::FLOAT,
                                    gl::FALSE as GLboolean, 0, ptr::null());
        }

        check_gl();

        window.set_cursor_pos_callback(~CursorPosContext);
        window.set_key_callback(~KeyContext);

        while !window.should_close() {
            glfw::poll_events();

            gl::Viewport(0,0, window_width as GLint, window_height as GLint);

            gl::ClearColor(0.8, 0.3, 0.3, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
            gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4);

            window.swap_buffers();

            check_gl();
        }
    }
}

fn check_gl() {
    let err = gl::GetError();
    if (err != gl::NO_ERROR) {
        fail!("GL error");
    }
}

fn compile_shader(src: &[u8], ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
        // Attempt to compile the shader
        //transmute is used here because `as` causes ICE
        //wait a sec, is `src` null-terminated properly?
        gl::ShaderSource(shader, 1, std::cast::transmute(std::ptr::to_unsafe_ptr(&src.as_ptr())), ptr::null());
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!(str::raw::from_utf8(buf).to_owned());
        }
    }
    shader
}

fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vs);
    gl::AttachShader(program, fs);
    gl::LinkProgram(program);
    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!(str::raw::from_utf8(buf).to_owned());
        }
    }
    program
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
    fn call(&self, _: glfw::Error, description: ~str) {
        fail!("GLFW Error: {:s}", description);
    }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
    fn call(&self, _: &glfw::Window, _: f64, _: f64) {
    }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
    fn call(&self, window: &glfw::Window, key: glfw::Key, _: libc::c_int, action: glfw::Action, _: glfw::Modifiers) {
        match (action, key) {
            (glfw::Press, glfw::KeyEscape) => window.set_should_close(true),
            _ => println!("unexpected key callback for action {:?} key {:?}", action, key)
        }
    }
}
<commit_msg>rotating cube<commit_after>#[feature(globs)];

extern mod extra;
extern mod glfw;
extern mod gl;
extern mod cgmath;

use std::cast;
use std::ptr;
use std::str;
use std::vec;
use std::libc;
use extra::time;

use gl::types::*;

use cgmath::matrix::Matrix;
use cgmath::matrix::Mat3;
use cgmath::matrix::Mat4;
use cgmath::matrix::ToMat4;
use cgmath::vector::Vec4;
use cgmath::angle::rad;
use cgmath::projection;

#[link(name="GLU")]
extern {}

static vertex_shader_src : &'static str = r"
#version 110

uniform mat4 transform;

attribute vec4 position;

varying vec3 color;

void main() {
    gl_Position = transform * position;
    color = (position.xyz + vec3(1.0, 1.0, 1.0)) * 0.5;
}
";

static fragment_shader_src : &'static str = r"
#version 110

varying vec3 color;

void main() {
    gl_FragColor = vec4(color, 1.0);
}
";

#[start]
fn start(argc: int, argv: **u8) -> int {
    std::rt::start_on_main_thread(argc, argv, main)
}

fn main() {
   glfw::set_error_callback(~ErrorContext);

   let window_width = 800;
   let window_height = 600;

    do glfw::start {
        let window = glfw::Window::create(window_width, window_height, "Hello, I am a window.", glfw::Windowed)
            .expect("Failed to create GLFW window.");

        //window.set_cursor_mode(glfw::CursorDisabled);
        window.make_context_current();

        gl::load_with(glfw::get_proc_address);

        let vs = compile_shader(vertex_shader_src.as_bytes(), gl::VERTEX_SHADER);
        let fs = compile_shader(fragment_shader_src.as_bytes(), gl::FRAGMENT_SHADER);
        let program = link_program(vs, fs);

        check_gl("after link");

        let mut uniform_transform;

        unsafe {
            uniform_transform = "transform".with_c_str(|ptr| gl::GetUniformLocation(program, ptr));
        }

        check_gl("after uniform transform location");

        let mut vao = 0;
        let mut vbo = 0;
        let mut ebo = 0;

        let vertices : ~[GLfloat] = ~[
            -1.0, -1.0,  1.0, 1.0,
            1.0, -1.0,  1.0, 1.0,
            -1.0,  1.0,  1.0, 1.0,
            1.0,  1.0,  1.0, 1.0,
            -1.0, -1.0, -1.0, 1.0,
            1.0, -1.0, -1.0, 1.0,
            -1.0,  1.0, -1.0, 1.0,
            1.0,  1.0, -1.0, 1.0,
        ];

        let elements : ~[GLshort] = ~[
            0, 1, 2, 3, 7, 1, 5, 4, 7, 6, 2, 4, 0, 1
        ];

        unsafe {
            gl::Enable(gl::DEPTH_TEST);
            gl::Enable(gl::CULL_FACE);

            glfw::set_swap_interval(1);

            // Create Vertex Array Object
            gl::GenVertexArrays(1, &mut vao);
            gl::BindVertexArray(vao);

            // Create a Vertex Buffer Object and copy the vertex data to it
            gl::GenBuffers(1, &mut vbo);
            gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
            gl::BufferData(gl::ARRAY_BUFFER,
                           (vertices.len() * std::mem::size_of::<GLfloat>()) as GLsizeiptr,
                           cast::transmute(&vertices[0]),
                           gl::STATIC_DRAW);

            check_gl("after vertex buffer");

            // Create a Vertex Buffer Object and copy the element data to it
            gl::GenBuffers(1, &mut ebo);
            gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
            gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,
                           (elements.len() * std::mem::size_of::<GLshort>()) as GLsizeiptr,
                           cast::transmute(&elements[0]),
                           gl::STATIC_DRAW);

            check_gl("after element buffer");

            // Use shader program
            gl::UseProgram(program);

            // Specify the layout of the vertex data
            let vert_attr = "position".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
            gl::EnableVertexAttribArray(vert_attr as GLuint);
            gl::VertexAttribPointer(vert_attr as GLuint, 4, gl::FLOAT,
                                    gl::FALSE as GLboolean, 0, ptr::null());

            check_gl("after vertex attrib pointer");
        }

        check_gl("after buffers");

        window.set_cursor_pos_callback(~CursorPosContext);
        window.set_key_callback(~KeyContext);

        let start_time = extra::time::precise_time_ns();
        let mut last_frame_time = start_time;
        let mut num_frames = 0;

        while !window.should_close() {
            glfw::poll_events();

            gl::Viewport(0,0, window_width as GLint, window_height as GLint);

            gl::ClearColor(0.0, 0.0, 0.0, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            let elapsed : u64 = extra::time::precise_time_ns() - start_time;
            let angle : f32 = elapsed as f32 / (1000*1000*1000) as f32;

            let translation = Mat4::<f32>::from_cols(
                Vec4::<f32>::unit_x(),
                Vec4::<f32>::unit_y(),
                Vec4::<f32>::unit_z(),
                Vec4::<f32>::new(0.0f32, 0.0f32, -5.0f32, 1.0f32));
            let rotation = Mat3::<f32>::from_angle_y(rad(angle)).to_mat4();
            let projection = cgmath::projection::perspective(rad(1.57 as f32), (4.0/3.0) as f32, 0.1 as f32, 10.0 as f32);
            let transform = projection.mul_m(&translation).mul_m(&rotation);

            unsafe {
                gl::UniformMatrix4fv(uniform_transform, 1, gl::FALSE, cast::transmute(&transform));

                check_gl("after uniform transform");

                gl::DrawElements(gl::TRIANGLE_STRIP, elements.len() as i32, gl::UNSIGNED_SHORT, ptr::null());
            }

            window.swap_buffers();

            check_gl("main loop");

            let cur_time = extra::time::precise_time_ns();
            num_frames += 1;
            if (cur_time - last_frame_time) > (1000*1000*1000) {
                println!("{} frames per second", num_frames);
                num_frames = 0;
                last_frame_time = cur_time;
            }
        }
    }
}

extern "C" {
    fn gluErrorString(error: GLenum) -> *GLubyte;
}

fn check_gl(message : &str) {
    let err = gl::GetError();
    if (err != gl::NO_ERROR) {
        unsafe {
            let err = std::str::raw::from_c_str(gluErrorString(err) as *i8);
            fail!("GL error {} at {}", err, message);
        }
    }
}

fn compile_shader(src: &[u8], ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
        // Attempt to compile the shader
        //transmute is used here because `as` causes ICE
        //wait a sec, is `src` null-terminated properly?
        gl::ShaderSource(shader, 1, std::cast::transmute(std::ptr::to_unsafe_ptr(&src.as_ptr())), ptr::null());
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!(str::raw::from_utf8(buf).to_owned());
        }
    }
    shader
}

fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vs);
    gl::AttachShader(program, fs);
    gl::LinkProgram(program);
    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!(str::raw::from_utf8(buf).to_owned());
        }
    }
    program
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
    fn call(&self, _: glfw::Error, description: ~str) {
        fail!("GLFW Error: {:s}", description);
    }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
    fn call(&self, _: &glfw::Window, _: f64, _: f64) {
    }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
    fn call(&self, window: &glfw::Window, key: glfw::Key, _: libc::c_int, action: glfw::Action, _: glfw::Modifiers) {
        match (action, key) {
            (glfw::Press, glfw::KeyEscape) => window.set_should_close(true),
            _ => println!("unexpected key callback for action {:?} key {:?}", action, key)
        }
    }
}
<|endoftext|>


<commit_before>//! [GET /_matrix/client/r0/sync](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-sync)

use std::{collections::HashMap, time::Duration};

use js_int::UInt;
use ruma_api::{ruma_api, Outgoing};
use ruma_events::{
    collections::{
        all::{RoomEvent, StateEvent},
        only::Event as NonRoomEvent,
    },
    presence::PresenceEvent,
    stripped::AnyStrippedStateEvent,
    to_device::AnyToDeviceEvent,
    EventResult,
};
use ruma_identifiers::RoomId;
use serde::{Deserialize, Serialize};

use crate::{
    r0::{filter::FilterDefinition, keys::KeyAlgorithm},
    serde::is_default,
};

ruma_api! {
    metadata {
        description: "Get all new events from all rooms since the last sync or a given point of time.",
        method: GET,
        name: "sync",
        path: "/_matrix/client/r0/sync",
        rate_limited: false,
        requires_authentication: true,
    }

    request {
        /// A filter represented either as its full JSON definition or the ID of a saved filter.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub filter: Option<Filter>,
        /// A point in time to continue a sync from.
        ///
        /// Should be a token from the `next_batch` field of a previous `/sync`
        /// request.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub since: Option<String>,
        /// Controls whether to include the full state for all rooms the user is a member of.
        #[serde(default, skip_serializing_if = "is_default")]
        #[ruma_api(query)]
        pub full_state: bool,
        /// Controls whether the client is automatically marked as online by polling this API.
        #[serde(default, skip_serializing_if = "is_default")]
        #[ruma_api(query)]
        pub set_presence: SetPresence,
        /// The maximum time to poll in milliseconds before returning this request.
        #[serde(with = "crate::serde::duration::opt_ms", skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub timeout: Option<Duration>,
    }

    response {
        /// The batch token to supply in the `since` param of the next `/sync` request.
        pub next_batch: String,
        /// Updates to rooms.
        #[wrap_incoming]
        pub rooms: Rooms,
        /// Updates to the presence status of other users.
        #[wrap_incoming]
        pub presence: Presence,
        /// Messages sent dirrectly between devices.
        #[serde(default, skip_serializing_if = "ToDevice::is_empty")]
        #[wrap_incoming]
        pub to_device: ToDevice,
        /// Information on E2E device updates.
        ///
        /// Only present on an incremental sync.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub device_lists: Option<DeviceLists>,
        /// For each key algorithm, the number of unclaimed one-time keys
        /// currently held on the server for a device.
        #[serde(skip_serializing_if = "HashMap::is_empty")]
        pub device_one_time_keys_count: HashMap<KeyAlgorithm, UInt>,
    }

    error: crate::Error
}

/// Whether to set presence or not during sync.
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum SetPresence {
    /// Do not set the presence of the user calling this API.
    Offline,
    /// Mark client as online explicitly. Assumed by default.
    Online,
    /// Mark client as being idle.
    Unavailable,
}

impl Default for SetPresence {
    fn default() -> Self {
        Self::Online
    }
}

/// A filter represented either as its full JSON definition or the ID of a saved filter.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::large_enum_variant)]
#[serde(untagged)]
pub enum Filter {
    // The filter definition needs to be (de)serialized twice because it is a URL-encoded JSON
    // string. Since #[ruma_api(query)] only does the latter and this is a very uncommon
    // setup, we implement it through custom serde logic for this specific enum variant rather than
    // adding another ruma_api attribute.
    //
    // On the deserialization side, because this is an enum with #[serde(untagged)], serde will
    // try the variants in order (https://serde.rs/enum-representations.html). That means because
    // FilterDefinition is the first variant, JSON decoding is attempted first which is almost
    // functionally equivalent to looking at whether the first symbol is a '{' as the spec says.
    // (there are probably some corner cases like leading whitespace)
    #[serde(with = "filter_def_serde")]
    /// A complete filter definition serialized to JSON.
    FilterDefinition(FilterDefinition),
    /// The ID of a filter saved on the server.
    FilterId(String),
}

/// Serialization and deserialization logic for filter definitions.
mod filter_def_serde {
    use serde::{de::Error as _, ser::Error as _, Deserialize, Deserializer, Serializer};

    use crate::r0::filter::FilterDefinition;

    /// Serialization logic for filter definitions.
    pub fn serialize<S>(filter_def: &FilterDefinition, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let string = serde_json::to_string(filter_def).map_err(S::Error::custom)?;
        serializer.serialize_str(&string)
    }

    /// Deserialization logic for filter definitions.
    pub fn deserialize<'de, D>(deserializer: D) -> Result<FilterDefinition, D::Error>
    where
        D: Deserializer<'de>,
    {
        let filter_str = <&str>::deserialize(deserializer)?;

        serde_json::from_str(filter_str).map_err(D::Error::custom)
    }
}

/// Updates to rooms.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct Rooms {
    /// The rooms that the user has left or been banned from.
    #[wrap_incoming(LeftRoom)]
    pub leave: HashMap<RoomId, LeftRoom>,
    /// The rooms that the user has joined.
    #[wrap_incoming(JoinedRoom)]
    pub join: HashMap<RoomId, JoinedRoom>,
    /// The rooms that the user has been invited to.
    #[wrap_incoming(InvitedRoom)]
    pub invite: HashMap<RoomId, InvitedRoom>,
}

/// Historical updates to left rooms.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct LeftRoom {
    /// The timeline of messages and state changes in the room up to the point when the user
    /// left.
    #[wrap_incoming]
    pub timeline: Timeline,
    /// The state updates for the room up to the start of the timeline.
    #[wrap_incoming]
    pub state: State,
    /// The private data that this user has attached to this room.
    #[wrap_incoming]
    pub account_data: AccountData,
}

/// Updates to joined rooms.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct JoinedRoom {
    /// Information about the room which clients may need to correctly render it
    /// to users.
    pub summary: RoomSummary,
    /// Counts of unread notifications for this room.
    pub unread_notifications: UnreadNotificationsCount,
    /// The timeline of messages and state changes in the room.
    #[wrap_incoming]
    pub timeline: Timeline,
    /// Updates to the state, between the time indicated by the `since` parameter, and the start
    /// of the `timeline` (or all state up to the start of the `timeline`, if `since` is not
    /// given, or `full_state` is true).
    #[wrap_incoming]
    pub state: State,
    /// The private data that this user has attached to this room.
    #[wrap_incoming]
    pub account_data: AccountData,
    /// The ephemeral events in the room that aren't recorded in the timeline or state of the
    /// room. e.g. typing.
    #[wrap_incoming]
    pub ephemeral: Ephemeral,
}

/// unread notifications count
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct UnreadNotificationsCount {
    /// The number of unread notifications for this room with the highlight flag set.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub highlight_count: Option<UInt>,
    /// The total number of unread notifications for this room.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub notification_count: Option<UInt>,
}

/// Events in the room.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct Timeline {
    /// True if the number of events returned was limited by the `limit` on the filter.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limited: Option<bool>,
    /// A token that can be supplied to to the `from` parameter of the
    /// `/rooms/{roomId}/messages` endpoint.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub prev_batch: Option<String>,
    /// A list of events.
    #[wrap_incoming(RoomEvent with EventResult)]
    pub events: Vec<RoomEvent>,
}

/// State events in the room.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct State {
    /// A list of state events.
    #[wrap_incoming(StateEvent with EventResult)]
    pub events: Vec<StateEvent>,
}

/// The private data that this user has attached to this room.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct AccountData {
    /// A list of events.
    #[wrap_incoming(NonRoomEvent with EventResult)]
    pub events: Vec<NonRoomEvent>,
}

/// Ephemeral events not recorded in the timeline or state of the room.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct Ephemeral {
    /// A list of events.
    #[wrap_incoming(NonRoomEvent with EventResult)]
    pub events: Vec<NonRoomEvent>,
}

/// Information about room for rendering to clients.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RoomSummary {
    /// Users which can be used to generate a room name if the room does not have
    /// one. Required if room name or canonical aliases are not set or empty.
    #[serde(skip_serializing_if = "Vec::is_empty")]
    pub heroes: Vec<String>,
    /// Number of users whose membership status is `join`.
    /// Required if field has changed since last sync; otherwise, it may be
    /// omitted.
    pub joined_member_count: Option<UInt>,
    /// Number of users whose membership status is `invite`.
    /// Required if field has changed since last sync; otherwise, it may be
    /// omitted.
    pub invited_member_count: Option<UInt>,
}

/// Updates to the rooms that the user has been invited to.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct InvitedRoom {
    /// The state of a room that the user has been invited to.
    #[wrap_incoming]
    pub invite_state: InviteState,
}

/// The state of a room that the user has been invited to.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct InviteState {
    /// A list of state events.
    #[wrap_incoming(AnyStrippedStateEvent with EventResult)]
    pub events: Vec<AnyStrippedStateEvent>,
}

/// Updates to the presence status of other users.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct Presence {
    /// A list of events.
    #[wrap_incoming(PresenceEvent with EventResult)]
    pub events: Vec<PresenceEvent>,
}

/// Messages sent dirrectly between devices.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct ToDevice {
    /// A list of to-device events.
    #[wrap_incoming(AnyToDeviceEvent with EventResult)]
    pub events: Vec<AnyToDeviceEvent>,
}

impl ToDevice {
    fn is_empty(&self) -> bool {
        self.events.is_empty()
    }
}

impl Default for IncomingToDevice {
    fn default() -> Self {
        Self { events: Vec::new() }
    }
}

/// Information on E2E device udpates.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeviceLists {
    /// List of users who have updated their device identity keys or who now
    /// share an encrypted room with the client since the previous sync
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub changed: Vec<String>,
    /// List of users who no longer share encrypted rooms since the previous sync
    /// response.
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub left: Vec<String>,
}

#[cfg(test)]
mod tests {
    use std::{convert::TryInto, time::Duration};

    use super::{Filter, Request, SetPresence};

    #[test]
    fn serialize_sync_request() {
        let req: http::Request<Vec<u8>> = Request {
            filter: Some(Filter::FilterId("66696p746572".into())),
            since: Some("s72594_4483_1934".into()),
            full_state: true,
            set_presence: SetPresence::Offline,
            timeout: Some(Duration::from_millis(30000)),
        }
        .try_into()
        .unwrap();

        let uri = req.uri();
        let query = uri.query().unwrap();

        assert_eq!(uri.path(), "/_matrix/client/r0/sync");
        assert!(query.contains("filter=66696p746572"));
        assert!(query.contains("since=s72594_4483_1934"));
        assert!(query.contains("full_state=true"));
        assert!(query.contains("set_presence=offline"));
        assert!(query.contains("timeout=30000"))
    }
}
<commit_msg>sync_events: Fix RoomSummary serde attributes<commit_after>//! [GET /_matrix/client/r0/sync](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-sync)

use std::{collections::HashMap, time::Duration};

use js_int::UInt;
use ruma_api::{ruma_api, Outgoing};
use ruma_events::{
    collections::{
        all::{RoomEvent, StateEvent},
        only::Event as NonRoomEvent,
    },
    presence::PresenceEvent,
    stripped::AnyStrippedStateEvent,
    to_device::AnyToDeviceEvent,
    EventResult,
};
use ruma_identifiers::RoomId;
use serde::{Deserialize, Serialize};

use crate::{
    r0::{filter::FilterDefinition, keys::KeyAlgorithm},
    serde::is_default,
};

ruma_api! {
    metadata {
        description: "Get all new events from all rooms since the last sync or a given point of time.",
        method: GET,
        name: "sync",
        path: "/_matrix/client/r0/sync",
        rate_limited: false,
        requires_authentication: true,
    }

    request {
        /// A filter represented either as its full JSON definition or the ID of a saved filter.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub filter: Option<Filter>,
        /// A point in time to continue a sync from.
        ///
        /// Should be a token from the `next_batch` field of a previous `/sync`
        /// request.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub since: Option<String>,
        /// Controls whether to include the full state for all rooms the user is a member of.
        #[serde(default, skip_serializing_if = "is_default")]
        #[ruma_api(query)]
        pub full_state: bool,
        /// Controls whether the client is automatically marked as online by polling this API.
        #[serde(default, skip_serializing_if = "is_default")]
        #[ruma_api(query)]
        pub set_presence: SetPresence,
        /// The maximum time to poll in milliseconds before returning this request.
        #[serde(with = "crate::serde::duration::opt_ms", skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub timeout: Option<Duration>,
    }

    response {
        /// The batch token to supply in the `since` param of the next `/sync` request.
        pub next_batch: String,
        /// Updates to rooms.
        #[wrap_incoming]
        pub rooms: Rooms,
        /// Updates to the presence status of other users.
        #[wrap_incoming]
        pub presence: Presence,
        /// Messages sent dirrectly between devices.
        #[serde(default, skip_serializing_if = "ToDevice::is_empty")]
        #[wrap_incoming]
        pub to_device: ToDevice,
        /// Information on E2E device updates.
        ///
        /// Only present on an incremental sync.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub device_lists: Option<DeviceLists>,
        /// For each key algorithm, the number of unclaimed one-time keys
        /// currently held on the server for a device.
        #[serde(skip_serializing_if = "HashMap::is_empty")]
        pub device_one_time_keys_count: HashMap<KeyAlgorithm, UInt>,
    }

    error: crate::Error
}

/// Whether to set presence or not during sync.
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum SetPresence {
    /// Do not set the presence of the user calling this API.
    Offline,
    /// Mark client as online explicitly. Assumed by default.
    Online,
    /// Mark client as being idle.
    Unavailable,
}

impl Default for SetPresence {
    fn default() -> Self {
        Self::Online
    }
}

/// A filter represented either as its full JSON definition or the ID of a saved filter.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::large_enum_variant)]
#[serde(untagged)]
pub enum Filter {
    // The filter definition needs to be (de)serialized twice because it is a URL-encoded JSON
    // string. Since #[ruma_api(query)] only does the latter and this is a very uncommon
    // setup, we implement it through custom serde logic for this specific enum variant rather than
    // adding another ruma_api attribute.
    //
    // On the deserialization side, because this is an enum with #[serde(untagged)], serde will
    // try the variants in order (https://serde.rs/enum-representations.html). That means because
    // FilterDefinition is the first variant, JSON decoding is attempted first which is almost
    // functionally equivalent to looking at whether the first symbol is a '{' as the spec says.
    // (there are probably some corner cases like leading whitespace)
    #[serde(with = "filter_def_serde")]
    /// A complete filter definition serialized to JSON.
    FilterDefinition(FilterDefinition),
    /// The ID of a filter saved on the server.
    FilterId(String),
}

/// Serialization and deserialization logic for filter definitions.
mod filter_def_serde {
    use serde::{de::Error as _, ser::Error as _, Deserialize, Deserializer, Serializer};

    use crate::r0::filter::FilterDefinition;

    /// Serialization logic for filter definitions.
    pub fn serialize<S>(filter_def: &FilterDefinition, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let string = serde_json::to_string(filter_def).map_err(S::Error::custom)?;
        serializer.serialize_str(&string)
    }

    /// Deserialization logic for filter definitions.
    pub fn deserialize<'de, D>(deserializer: D) -> Result<FilterDefinition, D::Error>
    where
        D: Deserializer<'de>,
    {
        let filter_str = <&str>::deserialize(deserializer)?;

        serde_json::from_str(filter_str).map_err(D::Error::custom)
    }
}

/// Updates to rooms.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct Rooms {
    /// The rooms that the user has left or been banned from.
    #[wrap_incoming(LeftRoom)]
    pub leave: HashMap<RoomId, LeftRoom>,
    /// The rooms that the user has joined.
    #[wrap_incoming(JoinedRoom)]
    pub join: HashMap<RoomId, JoinedRoom>,
    /// The rooms that the user has been invited to.
    #[wrap_incoming(InvitedRoom)]
    pub invite: HashMap<RoomId, InvitedRoom>,
}

/// Historical updates to left rooms.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct LeftRoom {
    /// The timeline of messages and state changes in the room up to the point when the user
    /// left.
    #[wrap_incoming]
    pub timeline: Timeline,
    /// The state updates for the room up to the start of the timeline.
    #[wrap_incoming]
    pub state: State,
    /// The private data that this user has attached to this room.
    #[wrap_incoming]
    pub account_data: AccountData,
}

/// Updates to joined rooms.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct JoinedRoom {
    /// Information about the room which clients may need to correctly render it
    /// to users.
    pub summary: RoomSummary,
    /// Counts of unread notifications for this room.
    pub unread_notifications: UnreadNotificationsCount,
    /// The timeline of messages and state changes in the room.
    #[wrap_incoming]
    pub timeline: Timeline,
    /// Updates to the state, between the time indicated by the `since` parameter, and the start
    /// of the `timeline` (or all state up to the start of the `timeline`, if `since` is not
    /// given, or `full_state` is true).
    #[wrap_incoming]
    pub state: State,
    /// The private data that this user has attached to this room.
    #[wrap_incoming]
    pub account_data: AccountData,
    /// The ephemeral events in the room that aren't recorded in the timeline or state of the
    /// room. e.g. typing.
    #[wrap_incoming]
    pub ephemeral: Ephemeral,
}

/// unread notifications count
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct UnreadNotificationsCount {
    /// The number of unread notifications for this room with the highlight flag set.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub highlight_count: Option<UInt>,
    /// The total number of unread notifications for this room.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub notification_count: Option<UInt>,
}

/// Events in the room.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct Timeline {
    /// True if the number of events returned was limited by the `limit` on the filter.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limited: Option<bool>,
    /// A token that can be supplied to to the `from` parameter of the
    /// `/rooms/{roomId}/messages` endpoint.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub prev_batch: Option<String>,
    /// A list of events.
    #[wrap_incoming(RoomEvent with EventResult)]
    pub events: Vec<RoomEvent>,
}

/// State events in the room.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct State {
    /// A list of state events.
    #[wrap_incoming(StateEvent with EventResult)]
    pub events: Vec<StateEvent>,
}

/// The private data that this user has attached to this room.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct AccountData {
    /// A list of events.
    #[wrap_incoming(NonRoomEvent with EventResult)]
    pub events: Vec<NonRoomEvent>,
}

/// Ephemeral events not recorded in the timeline or state of the room.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct Ephemeral {
    /// A list of events.
    #[wrap_incoming(NonRoomEvent with EventResult)]
    pub events: Vec<NonRoomEvent>,
}

/// Information about room for rendering to clients.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RoomSummary {
    /// Users which can be used to generate a room name if the room does not have
    /// one. Required if room name or canonical aliases are not set or empty.
    #[serde(rename = "m.heroes", default, skip_serializing_if = "Vec::is_empty")]
    pub heroes: Vec<String>,
    /// Number of users whose membership status is `join`.
    /// Required if field has changed since last sync; otherwise, it may be
    /// omitted.
    #[serde(rename = "m.joined_member_count")]
    pub joined_member_count: Option<UInt>,
    /// Number of users whose membership status is `invite`.
    /// Required if field has changed since last sync; otherwise, it may be
    /// omitted.
    #[serde(rename = "m.invited_member_count")]
    pub invited_member_count: Option<UInt>,
}

/// Updates to the rooms that the user has been invited to.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct InvitedRoom {
    /// The state of a room that the user has been invited to.
    #[wrap_incoming]
    pub invite_state: InviteState,
}

/// The state of a room that the user has been invited to.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct InviteState {
    /// A list of state events.
    #[wrap_incoming(AnyStrippedStateEvent with EventResult)]
    pub events: Vec<AnyStrippedStateEvent>,
}

/// Updates to the presence status of other users.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct Presence {
    /// A list of events.
    #[wrap_incoming(PresenceEvent with EventResult)]
    pub events: Vec<PresenceEvent>,
}

/// Messages sent dirrectly between devices.
#[derive(Clone, Debug, Serialize, Outgoing)]
pub struct ToDevice {
    /// A list of to-device events.
    #[wrap_incoming(AnyToDeviceEvent with EventResult)]
    pub events: Vec<AnyToDeviceEvent>,
}

impl ToDevice {
    fn is_empty(&self) -> bool {
        self.events.is_empty()
    }
}

impl Default for IncomingToDevice {
    fn default() -> Self {
        Self { events: Vec::new() }
    }
}

/// Information on E2E device udpates.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeviceLists {
    /// List of users who have updated their device identity keys or who now
    /// share an encrypted room with the client since the previous sync
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub changed: Vec<String>,
    /// List of users who no longer share encrypted rooms since the previous sync
    /// response.
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub left: Vec<String>,
}

#[cfg(test)]
mod tests {
    use std::{convert::TryInto, time::Duration};

    use super::{Filter, Request, SetPresence};

    #[test]
    fn serialize_sync_request() {
        let req: http::Request<Vec<u8>> = Request {
            filter: Some(Filter::FilterId("66696p746572".into())),
            since: Some("s72594_4483_1934".into()),
            full_state: true,
            set_presence: SetPresence::Offline,
            timeout: Some(Duration::from_millis(30000)),
        }
        .try_into()
        .unwrap();

        let uri = req.uri();
        let query = uri.query().unwrap();

        assert_eq!(uri.path(), "/_matrix/client/r0/sync");
        assert!(query.contains("filter=66696p746572"));
        assert!(query.contains("since=s72594_4483_1934"));
        assert!(query.contains("full_state=true"));
        assert!(query.contains("set_presence=offline"));
        assert!(query.contains("timeout=30000"))
    }
}
<|endoftext|>


<commit_before>/// An iterator that knows its exact length.
///
/// Many [`Iterator`]s don't know how many times they will iterate, but some do.
/// If an iterator knows how many times it can iterate, providing access to
/// that information can be useful. For example, if you want to iterate
/// backwards, a good start is to know where the end is.
///
/// When implementing an `ExactSizeIterator`, you must also implement
/// [`Iterator`]. When doing so, the implementation of [`Iterator::size_hint`]
/// *must* return the exact size of the iterator.
///
/// The [`len`] method has a default implementation, so you usually shouldn't
/// implement it. However, you may be able to provide a more performant
/// implementation than the default, so overriding it in this case makes sense.
///
/// [`len`]: ExactSizeIterator::len
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// // a finite range knows exactly how many times it will iterate
/// let five = 0..5;
///
/// assert_eq!(5, five.len());
/// ```
///
/// In the [module-level docs], we implemented an [`Iterator`], `Counter`.
/// Let's implement `ExactSizeIterator` for it as well:
///
/// [module-level docs]: crate::iter
///
/// ```
/// # struct Counter {
/// #     count: usize,
/// # }
/// # impl Counter {
/// #     fn new() -> Counter {
/// #         Counter { count: 0 }
/// #     }
/// # }
/// # impl Iterator for Counter {
/// #     type Item = usize;
/// #     fn next(&mut self) -> Option<Self::Item> {
/// #         self.count += 1;
/// #         if self.count < 6 {
/// #             Some(self.count)
/// #         } else {
/// #             None
/// #         }
/// #     }
/// # }
/// impl ExactSizeIterator for Counter {
///     // We can easily calculate the remaining number of iterations.
///     fn len(&self) -> usize {
///         5 - self.count
///     }
/// }
///
/// // And now we can use it!
///
/// let counter = Counter::new();
///
/// assert_eq!(5, counter.len());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ExactSizeIterator: Iterator {
    /// Returns the exact length of the iterator.
    ///
    /// The implementation ensures that the iterator will return exactly `len()`
    /// more times a [`Some(T)`] value, before returning [`None`].
    /// This method has a default implementation, so you usually should not
    /// implement it directly. However, if you can provide a more efficient
    /// implementation, you can do so. See the [trait-level] docs for an
    /// example.
    ///
    /// This function has the same safety guarantees as the
    /// [`Iterator::size_hint`] function.
    ///
    /// [trait-level]: ExactSizeIterator
    /// [`Some(T)`]: Some
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// // a finite range knows exactly how many times it will iterate
    /// let five = 0..5;
    ///
    /// assert_eq!(5, five.len());
    /// ```
    #[doc(alias = "length")]
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn len(&self) -> usize {
        let (lower, upper) = self.size_hint();
        // Note: This assertion is overly defensive, but it checks the invariant
        // guaranteed by the trait. If this trait were rust-internal,
        // we could use debug_assert!; assert_eq! will check all Rust user
        // implementations too.
        assert_eq!(upper, Some(lower));
        lower
    }

    /// Returns `true` if the iterator is empty.
    ///
    /// This method has a default implementation using
    /// [`ExactSizeIterator::len()`], so you don't need to implement it yourself.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// #![feature(exact_size_is_empty)]
    ///
    /// let mut one_element = std::iter::once(0);
    /// assert!(!one_element.is_empty());
    ///
    /// assert_eq!(one_element.next(), Some(0));
    /// assert!(one_element.is_empty());
    ///
    /// assert_eq!(one_element.next(), None);
    /// ```
    #[inline]
    #[unstable(feature = "exact_size_is_empty", issue = "35428")]
    fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for &mut I {
    fn len(&self) -> usize {
        (**self).len()
    }
    fn is_empty(&self) -> bool {
        (**self).is_empty()
    }
}
<commit_msg>Add a note about the correctness and the effect on unsafe code to the `ExactSizeIterator` docs<commit_after>/// An iterator that knows its exact length.
///
/// Many [`Iterator`]s don't know how many times they will iterate, but some do.
/// If an iterator knows how many times it can iterate, providing access to
/// that information can be useful. For example, if you want to iterate
/// backwards, a good start is to know where the end is.
///
/// When implementing an `ExactSizeIterator`, you must also implement
/// [`Iterator`]. When doing so, the implementation of [`Iterator::size_hint`]
/// *must* return the exact size of the iterator.
///
/// The [`len`] method has a default implementation, so you usually shouldn't
/// implement it. However, you may be able to provide a more performant
/// implementation than the default, so overriding it in this case makes sense.
///
/// Note that this trait is a safe trait and as such does *not* and *cannot*
/// guarantee that the returned length is correct. This means that `unsafe`
/// code **must not** rely on the correctness of [`Iterator::size_hint`]. The
/// unstable and unsafe [`TrustedLen`](super::marker::TrustedLen) trait gives
/// this additional guarantee.
///
/// [`len`]: ExactSizeIterator::len
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// // a finite range knows exactly how many times it will iterate
/// let five = 0..5;
///
/// assert_eq!(5, five.len());
/// ```
///
/// In the [module-level docs], we implemented an [`Iterator`], `Counter`.
/// Let's implement `ExactSizeIterator` for it as well:
///
/// [module-level docs]: crate::iter
///
/// ```
/// # struct Counter {
/// #     count: usize,
/// # }
/// # impl Counter {
/// #     fn new() -> Counter {
/// #         Counter { count: 0 }
/// #     }
/// # }
/// # impl Iterator for Counter {
/// #     type Item = usize;
/// #     fn next(&mut self) -> Option<Self::Item> {
/// #         self.count += 1;
/// #         if self.count < 6 {
/// #             Some(self.count)
/// #         } else {
/// #             None
/// #         }
/// #     }
/// # }
/// impl ExactSizeIterator for Counter {
///     // We can easily calculate the remaining number of iterations.
///     fn len(&self) -> usize {
///         5 - self.count
///     }
/// }
///
/// // And now we can use it!
///
/// let counter = Counter::new();
///
/// assert_eq!(5, counter.len());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ExactSizeIterator: Iterator {
    /// Returns the exact length of the iterator.
    ///
    /// The implementation ensures that the iterator will return exactly `len()`
    /// more times a [`Some(T)`] value, before returning [`None`].
    /// This method has a default implementation, so you usually should not
    /// implement it directly. However, if you can provide a more efficient
    /// implementation, you can do so. See the [trait-level] docs for an
    /// example.
    ///
    /// This function has the same safety guarantees as the
    /// [`Iterator::size_hint`] function.
    ///
    /// [trait-level]: ExactSizeIterator
    /// [`Some(T)`]: Some
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// // a finite range knows exactly how many times it will iterate
    /// let five = 0..5;
    ///
    /// assert_eq!(5, five.len());
    /// ```
    #[doc(alias = "length")]
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn len(&self) -> usize {
        let (lower, upper) = self.size_hint();
        // Note: This assertion is overly defensive, but it checks the invariant
        // guaranteed by the trait. If this trait were rust-internal,
        // we could use debug_assert!; assert_eq! will check all Rust user
        // implementations too.
        assert_eq!(upper, Some(lower));
        lower
    }

    /// Returns `true` if the iterator is empty.
    ///
    /// This method has a default implementation using
    /// [`ExactSizeIterator::len()`], so you don't need to implement it yourself.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// #![feature(exact_size_is_empty)]
    ///
    /// let mut one_element = std::iter::once(0);
    /// assert!(!one_element.is_empty());
    ///
    /// assert_eq!(one_element.next(), Some(0));
    /// assert!(one_element.is_empty());
    ///
    /// assert_eq!(one_element.next(), None);
    /// ```
    #[inline]
    #[unstable(feature = "exact_size_is_empty", issue = "35428")]
    fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for &mut I {
    fn len(&self) -> usize {
        (**self).len()
    }
    fn is_empty(&self) -> bool {
        (**self).is_empty()
    }
}
<|endoftext|>


<commit_before>#![macro_escape]

macro_rules! impl_raw_accessors(
    ($($t:ty, $raw:ty);+) => (
        $(
        impl $t {
            #[inline]
            pub fn raw(&self) -> $raw { self.raw }
        }
        )+
    )
)

macro_rules! impl_owned_accessors(
    ($($t:ty, $owned:ident);+) => (
        $(
        impl $t {
            #[inline]
            pub fn $owned(&self) -> bool { self.$owned }
        }
        )+
    )
)

macro_rules! impl_raw_constructor(
    ($($t:ty -> $te:ident ($r:ident:$rt:ty));+) => (
        $(
        impl $t {
            #[inline]
            pub unsafe fn new_from_raw($r:$rt) -> $t {
                $te { $r: $r }
            }
        }
        )+
    );
    ($($t:ty -> $te:ident ($r:ident:$rt:ty, $o:ident:$ot:ty));+) => (
        $(
        impl $t {
            #[inline]
            pub unsafe fn new_from_raw($r:$rt, $o:$ot) -> $t {
                $te { $r: $r, $o: $o }
            }
        }
        )+
    )
)
<commit_msg>Made impl_raw_constructors more general<commit_after>#![macro_escape]

macro_rules! impl_raw_accessors(
    ($($t:ty, $raw:ty);+) => (
        $(
        impl $t {
            #[inline]
            pub fn raw(&self) -> $raw { self.raw }
        }
        )+
    )
)

macro_rules! impl_owned_accessors(
    ($($t:ty, $owned:ident);+) => (
        $(
        impl $t {
            #[inline]
            pub fn $owned(&self) -> bool { self.$owned }
        }
        )+
    )
)

macro_rules! impl_raw_constructor(
    ($($t:ty -> $te:ident ($($r:ident:$rt:ty),+));+) => (
        $(
        impl $t {
            #[inline]
            pub unsafe fn new_from_raw($($r:$rt),+) -> $t {
                $te { $($r: $r),+ }
            }
        }
        )+
    )
)
<|endoftext|>


<commit_before>//! Contains information for keybindings.

use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::hash::{Hash, Hasher};

use rustwlc::xkb::{Keysym, NameFlags};
use rustwlc::types::*; // Need * for bitflags...

use super::layout::tree;
use super::lua;

/// Register default keypresses to a map
macro_rules! register_defaults {
    ( $map:expr; $($func:expr, $press:expr);+ ) => {
        $(
            let _ = $map.insert($press, Arc::new(Box::new($func)));
            )+
    }
}

/// Generate switch_workspace methods and register them in $map
macro_rules! gen_switch_workspace {
    ($map:expr; $($b:ident, $n:expr);+) => {
        $(fn $b() {
            trace!("Switching to workspace {}", $n);
            tree::switch_workspace(&$n.to_string())
                .expect("Could not switch to a work-space");
                }
          register_defaults!( $map; $b, keypress!("Alt", $n) );
          )+
    };
}

lazy_static! {
    static ref BINDINGS: RwLock<HashMap<KeyPress, KeyEvent>> = {
        let mut map = HashMap::<KeyPress, KeyEvent>::new();

        gen_switch_workspace!(map; switch_workspace_1, "1";
                              switch_workspace_2, "2";
                              switch_workspace_3, "3";
                              switch_workspace_4, "4";
                              switch_workspace_5, "5";
                              switch_workspace_6, "6";
                              switch_workspace_7, "7";
                              switch_workspace_8, "8";
                              switch_workspace_9, "9";
                              switch_workspace_0, "0");

        register_defaults! {
            map;
            quit_fn, keypress!("Alt", "Escape");
            terminal_fn, keypress!("Alt", "Return");
            dmenu_fn, keypress!("Alt", "d");
            pointer_fn, keypress!("Alt", "p")
        }

        RwLock::new(map)
    };
}

fn terminal_fn() {
    use std::process::Command;
    Command::new("sh")
        .arg("-c")
        .arg("weston-terminal")
        .spawn().expect("Error launching terminal");
}

fn dmenu_fn() {
    use std::process::Command;
    Command::new("sh")
        .arg("-c")
        .arg("dmenu_run")
        .spawn().expect("Error launching terminal");
}

fn pointer_fn() {
    use lua::LuaQuery;
    let code = "if wm == nil then print('wm table does not exist')\n\
                elseif wm.pointer == nil then print('wm.pointer table does not exist')\n\
                else\n\
                print('get_position is a func, preparing execution')
                local x, y = wm.pointer.get_position()\n\
                print('The cursor is at ' .. x .. ', ' .. y)\n\
                end".to_string();
    lua::send(LuaQuery::Execute(code))
        .expect("Error telling Lua to get pointer coords");
}

fn quit_fn() {
    info!("handler: Esc keypress!");
    ::rustwlc::terminate();
}

#[derive(Eq, PartialEq, Clone, Debug)]
pub struct KeyPress {
    modifiers: KeyMod,
    keys: Vec<Keysym>
}

/// Parses a KeyMod from key names.
pub fn keymod_from_names(keys: Vec<&str>) -> Result<KeyMod, String> {
    let mut result = KeyMod::empty();
    for key in keys {
        match key.to_lowercase().as_str() {
            "shift"            => result = result | MOD_SHIFT,
            "control" | "ctrl" => result = result | MOD_CTRL,
            "alt"              => result = result | MOD_ALT,
            "mod2"             => result = result | MOD_MOD2,
            "mod3"             => result = result | MOD_MOD3,
            "mod4" | "super" | "logo" => result = result | MOD_MOD4,
            "mod5" | "5mod5me" => result = result | MOD_MOD5,
            err => return Err(format!("Invalid modifier: {}", err))
        }
    }
    return Ok(result);
}

impl KeyPress {
    /// Creates a new KeyPress struct from a list of modifier and key names
    pub fn from_key_names(mods: Vec<&str>, keys: Vec<&str>) -> Result<KeyPress, String> {
        keymod_from_names(mods).and_then(|mods| {
            let mut syms: Vec<Keysym> = Vec::with_capacity(keys.len());
            for name in keys {
                // Parse a keysym for each given key
                if let Some(sym) = Keysym::from_name(name.to_string(),
                                                     NameFlags::None) {
                    syms.push(sym);
                }
                // If lowercase cannot be parsed, try case insensitive
                else if let Some(sym) = Keysym::from_name(name.to_string(),
                                                          NameFlags::CaseInsensitive) {
                    syms.push(sym);
                }
                else {
                    return Err(format!("Invalid key: {}", name));
                }
            }
            // Sort and dedup to make sure hashes are the same
            syms.sort_by_key(|s| s.get_code());
            syms.dedup();
            return Ok(KeyPress { modifiers: mods, keys: syms });
        })
    }

    /// Creates a KeyPress from keys that are pressed at the moment
    pub fn new(mods: KeyMod, mut keys: Vec<Keysym>) -> KeyPress {
        // Sort and dedup to make sure hashes are the same
        keys.sort_by_key(|k| k.get_code());
        keys.dedup();

        KeyPress { modifiers: mods, keys: keys }
    }
}

impl Hash for KeyPress {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_u32(self.modifiers.bits());
        for ref sym in &self.keys {
            hasher.write_u32(sym.get_code());
        }
    }
}

/// The type of function a key press handler is.
pub type KeyEvent = Arc<Box<Fn() + Send + Sync>>;

/// Get a key mapping from the list.
pub fn get(key: &KeyPress) -> Option<KeyEvent> {
    let bindings = BINDINGS.read()
        .expect("Keybindings/get: unable to lock keybindings");
    match bindings.get(key) {
        None => None,
        Some(val) => Some(val.clone())
    }
}

/// Register a new set of key mappings
#[allow(dead_code)]
pub fn register(values: Vec<(KeyPress, KeyEvent)>) {
    let mut bindings = BINDINGS.write()
        .expect("Keybindings/register: unable to lock keybindings");
    for value in values {
        bindings.insert(value.0, value.1);
    }
}
<commit_msg>Add test for keybindings<commit_after>//! Contains information for keybindings.

use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::hash::{Hash, Hasher};

use rustwlc::xkb::{Keysym, NameFlags};
use rustwlc::types::*; // Need * for bitflags...

use super::layout::tree;
use super::lua;

/// Register default keypresses to a map
macro_rules! register_defaults {
    ( $map:expr; $($func:expr, $press:expr);+ ) => {
        $(
            let _ = $map.insert($press, Arc::new(Box::new($func)));
            )+
    }
}

/// Generate switch_workspace methods and register them in $map
macro_rules! gen_switch_workspace {
    ($map:expr; $($b:ident, $n:expr);+) => {
        $(fn $b() {
            trace!("Switching to workspace {}", $n);
            tree::switch_workspace(&$n.to_string())
                .expect("Could not switch to a work-space");
                }
          register_defaults!( $map; $b, keypress!("Alt", $n) );
          )+
    };
}

lazy_static! {
    static ref BINDINGS: RwLock<HashMap<KeyPress, KeyEvent>> = {
        let mut map = HashMap::<KeyPress, KeyEvent>::new();

        gen_switch_workspace!(map; switch_workspace_1, "1";
                              switch_workspace_2, "2";
                              switch_workspace_3, "3";
                              switch_workspace_4, "4";
                              switch_workspace_5, "5";
                              switch_workspace_6, "6";
                              switch_workspace_7, "7";
                              switch_workspace_8, "8";
                              switch_workspace_9, "9";
                              switch_workspace_0, "0");

        register_defaults! {
            map;
            quit_fn, keypress!("Alt", "Escape");
            terminal_fn, keypress!("Alt", "Return");
            dmenu_fn, keypress!("Alt", "d");
            pointer_fn, keypress!("Alt", "p")
        }

        RwLock::new(map)
    };
}

fn terminal_fn() {
    use std::process::Command;
    Command::new("sh")
        .arg("-c")
        .arg("weston-terminal")
        .spawn().expect("Error launching terminal");
}

fn dmenu_fn() {
    use std::process::Command;
    Command::new("sh")
        .arg("-c")
        .arg("dmenu_run")
        .spawn().expect("Error launching terminal");
}

fn pointer_fn() {
    use lua::LuaQuery;
    let code = "if wm == nil then print('wm table does not exist')\n\
                elseif wm.pointer == nil then print('wm.pointer table does not exist')\n\
                else\n\
                print('get_position is a func, preparing execution')
                local x, y = wm.pointer.get_position()\n\
                print('The cursor is at ' .. x .. ', ' .. y)\n\
                end".to_string();
    lua::send(LuaQuery::Execute(code))
        .expect("Error telling Lua to get pointer coords");
}

fn quit_fn() {
    info!("handler: Esc keypress!");
    ::rustwlc::terminate();
}

#[derive(Eq, PartialEq, Clone, Debug)]
pub struct KeyPress {
    modifiers: KeyMod,
    keys: Vec<Keysym>
}

/// Parses a KeyMod from key names.
pub fn keymod_from_names(keys: Vec<&str>) -> Result<KeyMod, String> {
    let mut result = KeyMod::empty();
    for key in keys {
        match key.to_lowercase().as_str() {
            "shift"            => result = result | MOD_SHIFT,
            "control" | "ctrl" => result = result | MOD_CTRL,
            "alt"              => result = result | MOD_ALT,
            "mod2"             => result = result | MOD_MOD2,
            "mod3"             => result = result | MOD_MOD3,
            "mod4" | "super" | "logo" => result = result | MOD_MOD4,
            "mod5" | "5mod5me" => result = result | MOD_MOD5,
            err => return Err(format!("Invalid modifier: {}", err))
        }
    }
    return Ok(result);
}

impl KeyPress {
    /// Creates a new KeyPress struct from a list of modifier and key names
    pub fn from_key_names(mods: Vec<&str>, keys: Vec<&str>) -> Result<KeyPress, String> {
        keymod_from_names(mods).and_then(|mods| {
            let mut syms: Vec<Keysym> = Vec::with_capacity(keys.len());
            for name in keys {
                // Parse a keysym for each given key
                if let Some(sym) = Keysym::from_name(name.to_string(),
                                                     NameFlags::None) {
                    syms.push(sym);
                }
                // If lowercase cannot be parsed, try case insensitive
                else if let Some(sym) = Keysym::from_name(name.to_string(),
                                                          NameFlags::CaseInsensitive) {
                    syms.push(sym);
                }
                else {
                    return Err(format!("Invalid key: {}", name));
                }
            }
            // Sort and dedup to make sure hashes are the same
            syms.sort_by_key(|s| s.get_code());
            syms.dedup();
            return Ok(KeyPress { modifiers: mods, keys: syms });
        })
    }

    /// Creates a KeyPress from keys that are pressed at the moment
    pub fn new(mods: KeyMod, mut keys: Vec<Keysym>) -> KeyPress {
        // Sort and dedup to make sure hashes are the same
        keys.sort_by_key(|k| k.get_code());
        keys.dedup();

        KeyPress { modifiers: mods, keys: keys }
    }
}

impl Hash for KeyPress {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_u32(self.modifiers.bits());
        for ref sym in &self.keys {
            hasher.write_u32(sym.get_code());
        }
    }
}

/// The type of function a key press handler is.
pub type KeyEvent = Arc<Box<Fn() + Send + Sync>>;

/// Get a key mapping from the list.
pub fn get(key: &KeyPress) -> Option<KeyEvent> {
    let bindings = BINDINGS.read()
        .expect("Keybindings/get: unable to lock keybindings");
    match bindings.get(key) {
        None => None,
        Some(val) => Some(val.clone())
    }
}

/// Register a new set of key mappings
#[allow(dead_code)]
pub fn register(values: Vec<(KeyPress, KeyEvent)>) {
    let mut bindings = BINDINGS.write()
        .expect("Keybindings/register: unable to lock keybindings");
    for value in values {
        bindings.insert(value.0, value.1);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::Arc;

    fn test_cmd() {
        assert!(true);
    }

    fn keypress() -> KeyPress {
        keypress!("Ctrl", "t")
    }

    #[test]
    fn add_key() {
        register(vec![(keypress(), Arc::new(Box::new(test_cmd)))]);
        assert!(get(&keypress()).is_some(), "Key not registered");
    }
}
<|endoftext|>