<commit_before>use std::num::{Float};
use std::default::Default;
use image::{ImageBuffer, Rgb};
use glium;
use glium::texture;
use glium::framebuffer;
use glium::render_buffer;
use glium::LinearBlendingFactor::*;
use util::{V2, Rect};

pub struct Renderer {
    /// Canvas size.
    size: V2<u32>,
    /// Rendering device resolution.
    resolution: V2<u32>,
    /// Shader for drawing atlas images.
    sprite_shader: glium::Program,
    /// Shader for blitting the canvas texture to screen.
    blit_shader: glium::Program,
    /// Atlas texture, contains all the sprites. Calx is a low-rent operation
    /// so we only have one.
    atlas: texture::Texture2d,
    /// Render target texture.
    buffer: texture::Texture2d,
    params: glium::DrawParameters,
}

impl Renderer {
    pub fn new<'a, T>(size: V2<u32>, display: &glium::Display, texture_image: T) -> Renderer
        where T: texture::Texture2dDataSource<'a> {

        let sprite_shader = glium::Program::from_source(display,
            include_str!("sprite.vert"),
            include_str!("sprite.frag"),
            None).unwrap();
        let blit_shader = glium::Program::from_source(display,
            include_str!("blit.vert"),
            include_str!("blit.frag"),
            None).unwrap();
        let atlas = texture::Texture2d::new(display, texture_image);

        let buffer = texture::Texture2d::new_empty(
            display,
            texture::UncompressedFloatFormat::U8U8U8U8,
            size.0, size.1);

        let mut params: glium::DrawParameters = Default::default();
        params.backface_culling = glium::BackfaceCullingMode::CullCounterClockWise;
        params.depth_test = glium::DepthTest::IfLessOrEqual;
        params.depth_write = true;
        params.blending_function = Some(glium::BlendingFunction::Addition {
            source: SourceAlpha, destination: OneMinusSourceAlpha });

        Renderer {
            size: size,
            resolution: size,
            sprite_shader: sprite_shader,
            blit_shader: blit_shader,
            atlas: atlas,
            buffer: buffer,
            params: params,
        }
    }

    /// Draw sprites on target.
    fn draw_sprites<S>(&self, display: &glium::Display, target: &mut S,
                       vertices: Vec<Vertex>, indices: Vec<u16>)
        where S: glium::Surface {

        // Extract the geometry accumulation buffers and convert into
        // temporary Glium buffers.
        let vertices = glium::VertexBuffer::new(display, vertices);
        let indices = glium::IndexBuffer::new(
            display, glium::index_buffer::TrianglesList(indices));

        let uniforms = glium::uniforms::UniformsStorage::new("texture",
            glium::uniforms::Sampler(&self.atlas, glium::uniforms::SamplerBehavior {
                magnify_filter: glium::uniforms::MagnifySamplerFilter::Nearest,
                .. Default::default() }));

        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.clear_depth(1.0);
        target.draw(&vertices, &indices, &self.sprite_shader, &uniforms, &self.params).unwrap();
    }

    /// Blit the buffer texture to target.
    fn blit_buffer<S>(&self, display: &glium::Display, target: &mut S)
        where S: glium::Surface {
        // TODO: Pixel-perfect scaling to target dimensions.
        //
        let Rect(V2(sx, sy), V2(sw, sh)) = pixel_perfect(self.size, self.resolution);

        let vertices = {
            #[vertex_format]
            #[derive(Copy)]
            struct BlitVertex { pos: [f32; 2], tex_coord: [f32; 2] }

            glium::VertexBuffer::new(display,
            vec![
                BlitVertex { pos: [sx,    sy   ], tex_coord: [0.0, 0.0] },
                BlitVertex { pos: [sx+sw, sy   ], tex_coord: [1.0, 0.0] },
                BlitVertex { pos: [sx+sw, sy+sh], tex_coord: [1.0, 1.0] },
                BlitVertex { pos: [sx,    sy+sh], tex_coord: [0.0, 1.0] },
            ])
        };

        let indices = glium::IndexBuffer::new(display,
            glium::index_buffer::TrianglesList(vec![0u16, 1, 2, 0, 2, 3]));

        let mut params: glium::DrawParameters = Default::default();
        // Set an explicit viewport to apply the custom resolution that fixes
        // pixel perfect rounding errors.
        params.viewport = Some(glium::Rect{
            left: 0, bottom: 0,
            width: self.resolution.0,
            height: self.resolution.1 });

        let uniforms = glium::uniforms::UniformsStorage::new("texture",
            glium::uniforms::Sampler(&self.buffer, glium::uniforms::SamplerBehavior {
                magnify_filter: glium::uniforms::MagnifySamplerFilter::Nearest,
                .. Default::default() }));

        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.clear_depth(1.0);
        target.draw(&vertices, &indices, &self.blit_shader, &uniforms, &params).unwrap();
    }

    /// Draw a geometry buffer.
    pub fn draw<S>(&mut self, display: &glium::Display, target: &mut S,
                   vertices: Vec<Vertex>, indices: Vec<u16>)
        where S: glium::Surface {

        // Render the graphics to a texture to keep the pixels pure and
        // untainted.
        let depth = render_buffer::DepthRenderBuffer::new(
            display, texture::DepthFormat::F32, self.size.0, self.size.1);
        let mut sprite_target = framebuffer::SimpleFrameBuffer::with_depth_buffer(
            display, &self.buffer, &depth);
        self.draw_sprites(display, &mut sprite_target, vertices, indices);

        let (w, h) = display.get_framebuffer_dimensions();
        // Clip viewport dimensions to even to prevent rounding errors in
        // pixel perfect scaling.
        self.resolution = V2(w & !1, h & !1);
        // Render the texture to screen.
        self.blit_buffer(display, target);
    }

    /// Map screen position (eg. of a mouse cursor) to canvas position.
    pub fn screen_to_canvas(&self, V2(sx, sy): V2<i32>) -> V2<i32> {
        let Rect(V2(rx, ry), V2(rw, rh)) = pixel_perfect(self.size, self.resolution);
        // Transform to device coordinates.
        let sx = sx as f32 * 2.0 / self.resolution.0 as f32 - 1.0;
        let sy = sy as f32 * 2.0 / self.resolution.1 as f32 - 1.0;

        V2(((sx - rx) * self.size.0 as f32 / rw) as i32,
           ((sy - ry) * self.size.1 as f32 / rh) as i32)
    }

    pub fn canvas_pixels(&self) -> ImageBuffer<Rgb<u8>, Vec<u8>> {
        self.buffer.read()
    }
}

#[vertex_format]
#[derive(Copy)]
/// Geometry vertex in on-screen graphics.
pub struct Vertex {
    /// Coordinates on screen
    pub pos: [f32; 3],
    /// Texture coordinates
    pub tex_coord: [f32; 2],
    /// Color for the light parts of the texture
    pub color: [f32; 4],
    /// Color for the dark parts of the texture
    pub back_color: [f32; 4],
}

/// A pixel perfect centered and scaled rectangle of resolution dim in a
/// window of size area, mapped to OpenGL device coordinates.
#[inline(always)]
fn pixel_perfect(canvas: V2<u32>, window: V2<u32>) -> Rect<f32> {
    // Scale based on whichever of X or Y axis is the tighter fit.
    let mut scale = (window.0 as f32 / canvas.0 as f32)
        .min(window.1 as f32 / canvas.1 as f32);

    if scale > 1.0 {
        // Snap to pixel scale if more than 1 window pixel per canvas pixel.
        scale = scale.floor();
    }

    let dim = V2((scale * canvas.0 as f32) * 2.0 / window.0 as f32,
                 (scale * canvas.1 as f32) * 2.0 / window.1 as f32);
    let offset = -dim / 2.0;
    Rect(offset, dim)
}
<commit_msg>Fix screen going dark when shrinking window<commit_after>use std::num::{Float};
use std::default::Default;
use image::{ImageBuffer, Rgb};
use glium;
use glium::texture;
use glium::framebuffer;
use glium::render_buffer;
use glium::LinearBlendingFactor::*;
use util::{V2, Rect};

pub struct Renderer {
    /// Canvas size.
    size: V2<u32>,
    /// Rendering device resolution.
    resolution: V2<u32>,
    /// Shader for drawing atlas images.
    sprite_shader: glium::Program,
    /// Shader for blitting the canvas texture to screen.
    blit_shader: glium::Program,
    /// Atlas texture, contains all the sprites. Calx is a low-rent operation
    /// so we only have one.
    atlas: texture::Texture2d,
    /// Render target texture.
    buffer: texture::Texture2d,
    params: glium::DrawParameters,
}

impl Renderer {
    pub fn new<'a, T>(size: V2<u32>, display: &glium::Display, texture_image: T) -> Renderer
        where T: texture::Texture2dDataSource<'a> {

        let sprite_shader = glium::Program::from_source(display,
            include_str!("sprite.vert"),
            include_str!("sprite.frag"),
            None).unwrap();
        let blit_shader = glium::Program::from_source(display,
            include_str!("blit.vert"),
            include_str!("blit.frag"),
            None).unwrap();
        let atlas = texture::Texture2d::new(display, texture_image);

        let buffer = texture::Texture2d::new_empty(
            display,
            texture::UncompressedFloatFormat::U8U8U8U8,
            size.0, size.1);

        let mut params: glium::DrawParameters = Default::default();
        params.backface_culling = glium::BackfaceCullingMode::CullCounterClockWise;
        params.depth_test = glium::DepthTest::IfLessOrEqual;
        params.depth_write = true;
        params.blending_function = Some(glium::BlendingFunction::Addition {
            source: SourceAlpha, destination: OneMinusSourceAlpha });

        Renderer {
            size: size,
            resolution: size,
            sprite_shader: sprite_shader,
            blit_shader: blit_shader,
            atlas: atlas,
            buffer: buffer,
            params: params,
        }
    }

    /// Draw sprites on target.
    fn draw_sprites<S>(&self, display: &glium::Display, target: &mut S,
                       vertices: Vec<Vertex>, indices: Vec<u16>)
        where S: glium::Surface {

        // Extract the geometry accumulation buffers and convert into
        // temporary Glium buffers.
        let vertices = glium::VertexBuffer::new(display, vertices);
        let indices = glium::IndexBuffer::new(
            display, glium::index_buffer::TrianglesList(indices));

        let uniforms = glium::uniforms::UniformsStorage::new("texture",
            glium::uniforms::Sampler(&self.atlas, glium::uniforms::SamplerBehavior {
                magnify_filter: glium::uniforms::MagnifySamplerFilter::Nearest,
                .. Default::default() }));

        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.clear_depth(1.0);
        target.draw(&vertices, &indices, &self.sprite_shader, &uniforms, &self.params).unwrap();
    }

    /// Blit the buffer texture to target.
    fn blit_buffer<S>(&self, display: &glium::Display, target: &mut S)
        where S: glium::Surface {
        // TODO: Pixel-perfect scaling to target dimensions.
        //
        let Rect(V2(sx, sy), V2(sw, sh)) = pixel_perfect(self.size, self.resolution);

        let vertices = {
            #[vertex_format]
            #[derive(Copy)]
            struct BlitVertex { pos: [f32; 2], tex_coord: [f32; 2] }

            glium::VertexBuffer::new(display,
            vec![
                BlitVertex { pos: [sx,    sy   ], tex_coord: [0.0, 0.0] },
                BlitVertex { pos: [sx+sw, sy   ], tex_coord: [1.0, 0.0] },
                BlitVertex { pos: [sx+sw, sy+sh], tex_coord: [1.0, 1.0] },
                BlitVertex { pos: [sx,    sy+sh], tex_coord: [0.0, 1.0] },
            ])
        };

        let indices = glium::IndexBuffer::new(display,
            glium::index_buffer::TrianglesList(vec![0u16, 1, 2, 0, 2, 3]));

        let mut params: glium::DrawParameters = Default::default();
        // Set an explicit viewport to apply the custom resolution that fixes
        // pixel perfect rounding errors.
        params.viewport = Some(glium::Rect{
            left: 0, bottom: 0,
            width: self.resolution.0,
            height: self.resolution.1 });

        let uniforms = glium::uniforms::UniformsStorage::new("texture",
            glium::uniforms::Sampler(&self.buffer, glium::uniforms::SamplerBehavior {
                magnify_filter: glium::uniforms::MagnifySamplerFilter::Nearest,
                minify_filter: glium::uniforms::MinifySamplerFilter::Linear,
                .. Default::default() }));

        target.clear_color(0.0, 0.0, 0.0, 0.0);
        target.clear_depth(1.0);
        target.draw(&vertices, &indices, &self.blit_shader, &uniforms, &params).unwrap();
    }

    /// Draw a geometry buffer.
    pub fn draw<S>(&mut self, display: &glium::Display, target: &mut S,
                   vertices: Vec<Vertex>, indices: Vec<u16>)
        where S: glium::Surface {

        // Render the graphics to a texture to keep the pixels pure and
        // untainted.
        let depth = render_buffer::DepthRenderBuffer::new(
            display, texture::DepthFormat::F32, self.size.0, self.size.1);
        let mut sprite_target = framebuffer::SimpleFrameBuffer::with_depth_buffer(
            display, &self.buffer, &depth);
        self.draw_sprites(display, &mut sprite_target, vertices, indices);

        let (w, h) = display.get_framebuffer_dimensions();
        // Clip viewport dimensions to even to prevent rounding errors in
        // pixel perfect scaling.
        self.resolution = V2(w & !1, h & !1);
        // Render the texture to screen.
        self.blit_buffer(display, target);
    }

    /// Map screen position (eg. of a mouse cursor) to canvas position.
    pub fn screen_to_canvas(&self, V2(sx, sy): V2<i32>) -> V2<i32> {
        let Rect(V2(rx, ry), V2(rw, rh)) = pixel_perfect(self.size, self.resolution);
        // Transform to device coordinates.
        let sx = sx as f32 * 2.0 / self.resolution.0 as f32 - 1.0;
        let sy = sy as f32 * 2.0 / self.resolution.1 as f32 - 1.0;

        V2(((sx - rx) * self.size.0 as f32 / rw) as i32,
           ((sy - ry) * self.size.1 as f32 / rh) as i32)
    }

    pub fn canvas_pixels(&self) -> ImageBuffer<Rgb<u8>, Vec<u8>> {
        self.buffer.read()
    }
}

#[vertex_format]
#[derive(Copy)]
/// Geometry vertex in on-screen graphics.
pub struct Vertex {
    /// Coordinates on screen
    pub pos: [f32; 3],
    /// Texture coordinates
    pub tex_coord: [f32; 2],
    /// Color for the light parts of the texture
    pub color: [f32; 4],
    /// Color for the dark parts of the texture
    pub back_color: [f32; 4],
}

/// A pixel perfect centered and scaled rectangle of resolution dim in a
/// window of size area, mapped to OpenGL device coordinates.
#[inline(always)]
fn pixel_perfect(canvas: V2<u32>, window: V2<u32>) -> Rect<f32> {
    // Scale based on whichever of X or Y axis is the tighter fit.
    let mut scale = (window.0 as f32 / canvas.0 as f32)
        .min(window.1 as f32 / canvas.1 as f32);

    if scale > 1.0 {
        // Snap to pixel scale if more than 1 window pixel per canvas pixel.
        scale = scale.floor();
    }

    let dim = V2((scale * canvas.0 as f32) * 2.0 / window.0 as f32,
                 (scale * canvas.1 as f32) * 2.0 / window.1 as f32);
    let offset = -dim / 2.0;
    Rect(offset, dim)
}
<|endoftext|>


<commit_before>/*!
 * Operations on the ubiquitous `option` type.
 *
 * Type `option` represents an optional value.
 *
 * Every `Option<T>` value can either be `Some(T)` or `none`. Where in other
 * languages you might use a nullable type, in Rust you would use an option
 * type.
 */

/// The option type
enum Option<T> {
    None,
    Some(T),
}

pure fn get<T: copy>(opt: Option<T>) -> T {
    /*!
     * Gets the value out of an option
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */

    match opt {
      Some(x) => return x,
      None => fail ~"option::get none"
    }
}

pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
    /*!
     * Gets an immutable reference to the value inside an option.
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    match *opt {
        Some(ref x) => x,
        None => fail ~"option::get_ref none"
    }
}

pure fn expect<T: copy>(opt: Option<T>, reason: ~str) -> T {
    /*!
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    match opt { Some(x) => x, None => fail reason }
}

pure fn map<T, U>(opt: Option<T>, f: fn(T) -> U) -> Option<U> {
    //! Maps a `some` value from one type to another

    match opt { Some(x) => Some(f(x)), None => None }
}

pure fn map_ref<T, U>(opt: &Option<T>, f: fn(x: &T) -> U) -> Option<U> {
    //! Maps a `some` value by reference from one type to another

    match *opt { Some(ref x) => Some(f(x)), None => None }
}

pure fn map_consume<T, U>(+opt: Option<T>, f: fn(+T) -> U) -> Option<U> {
    /*!
     * As `map`, but consumes the option and gives `f` ownership to avoid
     * copying.
     */
    if opt.is_some() { Some(f(option::unwrap(opt))) } else { None }
}

pure fn chain<T, U>(opt: Option<T>, f: fn(T) -> Option<U>) -> Option<U> {
    /*!
     * Update an optional value by optionally running its content through a
     * function that returns an option.
     */

    match opt { Some(x) => f(x), None => None }
}

pure fn chain_ref<T, U>(opt: &Option<T>,
                        f: fn(x: &T) -> Option<U>) -> Option<U> {
    /*!
     * Update an optional value by optionally running its content by reference
     * through a function that returns an option.
     */

    match *opt { Some(ref x) => f(x), None => None }
}

pure fn or<T>(+opta: Option<T>, +optb: Option<T>) -> Option<T> {
    /*!
     * Returns the leftmost some() value, or none if both are none.
     */
    match opta {
        Some(_) => opta,
        _ => optb
    }
}

#[inline(always)]
pure fn while_some<T>(+x: Option<T>, blk: fn(+T) -> Option<T>) {
    //! Applies a function zero or more times until the result is none.

    let mut opt <- x;
    while opt.is_some() {
        opt = blk(unwrap(opt));
    }
}

pure fn is_none<T>(opt: Option<T>) -> bool {
    //! Returns true if the option equals `none`

    match opt { None => true, Some(_) => false }
}

pure fn is_some<T>(opt: Option<T>) -> bool {
    //! Returns true if the option contains some value

    !is_none(opt)
}

pure fn get_default<T: copy>(opt: Option<T>, def: T) -> T {
    //! Returns the contained value or a default

    match opt { Some(x) => x, None => def }
}

pure fn map_default<T, U>(opt: Option<T>, +def: U, f: fn(T) -> U) -> U {
    //! Applies a function to the contained value or returns a default

    match opt { None => def, Some(t) => f(t) }
}

// This should replace map_default.
pure fn map_default_ref<T, U>(opt: &Option<T>, +def: U,
                              f: fn(x: &T) -> U) -> U {
    //! Applies a function to the contained value or returns a default

    match *opt { None => def, Some(ref t) => f(t) }
}

// This should change to by-copy mode; use iter_ref below for by reference
pure fn iter<T>(opt: Option<T>, f: fn(T)) {
    //! Performs an operation on the contained value or does nothing

    match opt { None => (), Some(t) => f(t) }
}

pure fn iter_ref<T>(opt: &Option<T>, f: fn(x: &T)) {
    //! Performs an operation on the contained value by reference
    match *opt { None => (), Some(ref t) => f(t) }
}

#[inline(always)]
pure fn unwrap<T>(+opt: Option<T>) -> T {
    /*!
     * Moves a value out of an option type and returns it.
     *
     * Useful primarily for getting strings, vectors and unique pointers out
     * of option types without copying them.
     */
    match move opt {
        Some(move x) => x,
        None => fail ~"option::unwrap none"
    }
}

/// The ubiquitous option dance.
#[inline(always)]
fn swap_unwrap<T>(opt: &mut Option<T>) -> T {
    if opt.is_none() { fail ~"option::swap_unwrap none" }
    unwrap(util::replace(opt, None))
}

pure fn unwrap_expect<T>(+opt: Option<T>, reason: &str) -> T {
    //! As unwrap, but with a specified failure message.
    if opt.is_none() { fail reason.to_unique(); }
    unwrap(opt)
}

// Some of these should change to be &Option<T>, some should not. See below.
impl<T> Option<T> {
    /**
     * Update an optional value by optionally running its content through a
     * function that returns an option.
     */
    pure fn chain<U>(f: fn(T) -> Option<U>) -> Option<U> { chain(self, f) }
    /// Applies a function to the contained value or returns a default
    pure fn map_default<U>(+def: U, f: fn(T) -> U) -> U
        { map_default(self, def, f) }
    /// Performs an operation on the contained value or does nothing
    pure fn iter(f: fn(T)) { iter(self, f) }
    /// Returns true if the option equals `none`
    pure fn is_none() -> bool { is_none(self) }
    /// Returns true if the option contains some value
    pure fn is_some() -> bool { is_some(self) }
    /// Maps a `some` value from one type to another
    pure fn map<U>(f: fn(T) -> U) -> Option<U> { map(self, f) }
}

impl<T> &Option<T> {
    /**
     * Update an optional value by optionally running its content by reference
     * through a function that returns an option.
     */
    pure fn chain_ref<U>(f: fn(x: &T) -> Option<U>) -> Option<U> {
        chain_ref(self, f)
    }
    /// Applies a function to the contained value or returns a default
    pure fn map_default_ref<U>(+def: U, f: fn(x: &T) -> U) -> U
        { map_default_ref(self, def, f) }
    /// Performs an operation on the contained value by reference
    pure fn iter_ref(f: fn(x: &T)) { iter_ref(self, f) }
    /// Maps a `some` value from one type to another by reference
    pure fn map_ref<U>(f: fn(x: &T) -> U) -> Option<U> { map_ref(self, f) }
    /// Gets an immutable reference to the value inside a `some`.
    pure fn get_ref() -> &self/T { get_ref(self) }
}

impl<T: copy> Option<T> {
    /**
     * Gets the value out of an option
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    pure fn get() -> T { get(self) }
    pure fn get_default(def: T) -> T { get_default(self, def) }
    /**
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    pure fn expect(reason: ~str) -> T { expect(self, reason) }
    /// Applies a function zero or more times until the result is none.
    pure fn while_some(blk: fn(+T) -> Option<T>) { while_some(self, blk) }
}

#[test]
fn test_unwrap_ptr() {
    let x = ~0;
    let addr_x = ptr::addr_of(*x);
    let opt = Some(x);
    let y = unwrap(opt);
    let addr_y = ptr::addr_of(*y);
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_str() {
    let x = ~"test";
    let addr_x = str::as_buf(x, |buf, _len| ptr::addr_of(buf));
    let opt = Some(x);
    let y = unwrap(opt);
    let addr_y = str::as_buf(y, |buf, _len| ptr::addr_of(buf));
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_resource() {
    struct r {
       let i: @mut int;
       new(i: @mut int) { self.i = i; }
       drop { *(self.i) += 1; }
    }
    let i = @mut 0;
    {
        let x = r(i);
        let opt = Some(x);
        let _y = unwrap(opt);
    }
    assert *i == 1;
}

#[test]
fn test_option_dance() {
    let x = Some(());
    let mut y = Some(5);
    let mut y2 = 0;
    do x.iter |_x| {
        y2 = swap_unwrap(&mut y);
    }
    assert y2 == 5;
    assert y.is_none();
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_option_too_much_dance() {
    let mut y = Some(util::NonCopyable());
    let _y2 = swap_unwrap(&mut y);
    let _y3 = swap_unwrap(&mut y);
}

#[test]
fn test_option_while_some() {
    let mut i = 0;
    do Some(10).while_some |j| {
        i += 1;
        if (j > 0) {
            Some(j-1)
        } else {
            None
        }
    }
    assert i == 11;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>rustc: Implement equality for option types<commit_after>/*!
 * Operations on the ubiquitous `option` type.
 *
 * Type `option` represents an optional value.
 *
 * Every `Option<T>` value can either be `Some(T)` or `none`. Where in other
 * languages you might use a nullable type, in Rust you would use an option
 * type.
 */

use cmp::Eq;

/// The option type
enum Option<T> {
    None,
    Some(T),
}

pure fn get<T: copy>(opt: Option<T>) -> T {
    /*!
     * Gets the value out of an option
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */

    match opt {
      Some(x) => return x,
      None => fail ~"option::get none"
    }
}

pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
    /*!
     * Gets an immutable reference to the value inside an option.
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    match *opt {
        Some(ref x) => x,
        None => fail ~"option::get_ref none"
    }
}

pure fn expect<T: copy>(opt: Option<T>, reason: ~str) -> T {
    /*!
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    match opt { Some(x) => x, None => fail reason }
}

pure fn map<T, U>(opt: Option<T>, f: fn(T) -> U) -> Option<U> {
    //! Maps a `some` value from one type to another

    match opt { Some(x) => Some(f(x)), None => None }
}

pure fn map_ref<T, U>(opt: &Option<T>, f: fn(x: &T) -> U) -> Option<U> {
    //! Maps a `some` value by reference from one type to another

    match *opt { Some(ref x) => Some(f(x)), None => None }
}

pure fn map_consume<T, U>(+opt: Option<T>, f: fn(+T) -> U) -> Option<U> {
    /*!
     * As `map`, but consumes the option and gives `f` ownership to avoid
     * copying.
     */
    if opt.is_some() { Some(f(option::unwrap(opt))) } else { None }
}

pure fn chain<T, U>(opt: Option<T>, f: fn(T) -> Option<U>) -> Option<U> {
    /*!
     * Update an optional value by optionally running its content through a
     * function that returns an option.
     */

    match opt { Some(x) => f(x), None => None }
}

pure fn chain_ref<T, U>(opt: &Option<T>,
                        f: fn(x: &T) -> Option<U>) -> Option<U> {
    /*!
     * Update an optional value by optionally running its content by reference
     * through a function that returns an option.
     */

    match *opt { Some(ref x) => f(x), None => None }
}

pure fn or<T>(+opta: Option<T>, +optb: Option<T>) -> Option<T> {
    /*!
     * Returns the leftmost some() value, or none if both are none.
     */
    match opta {
        Some(_) => opta,
        _ => optb
    }
}

#[inline(always)]
pure fn while_some<T>(+x: Option<T>, blk: fn(+T) -> Option<T>) {
    //! Applies a function zero or more times until the result is none.

    let mut opt <- x;
    while opt.is_some() {
        opt = blk(unwrap(opt));
    }
}

pure fn is_none<T>(opt: Option<T>) -> bool {
    //! Returns true if the option equals `none`

    match opt { None => true, Some(_) => false }
}

pure fn is_some<T>(opt: Option<T>) -> bool {
    //! Returns true if the option contains some value

    !is_none(opt)
}

pure fn get_default<T: copy>(opt: Option<T>, def: T) -> T {
    //! Returns the contained value or a default

    match opt { Some(x) => x, None => def }
}

pure fn map_default<T, U>(opt: Option<T>, +def: U, f: fn(T) -> U) -> U {
    //! Applies a function to the contained value or returns a default

    match opt { None => def, Some(t) => f(t) }
}

// This should replace map_default.
pure fn map_default_ref<T, U>(opt: &Option<T>, +def: U,
                              f: fn(x: &T) -> U) -> U {
    //! Applies a function to the contained value or returns a default

    match *opt { None => def, Some(ref t) => f(t) }
}

// This should change to by-copy mode; use iter_ref below for by reference
pure fn iter<T>(opt: Option<T>, f: fn(T)) {
    //! Performs an operation on the contained value or does nothing

    match opt { None => (), Some(t) => f(t) }
}

pure fn iter_ref<T>(opt: &Option<T>, f: fn(x: &T)) {
    //! Performs an operation on the contained value by reference
    match *opt { None => (), Some(ref t) => f(t) }
}

#[inline(always)]
pure fn unwrap<T>(+opt: Option<T>) -> T {
    /*!
     * Moves a value out of an option type and returns it.
     *
     * Useful primarily for getting strings, vectors and unique pointers out
     * of option types without copying them.
     */
    match move opt {
        Some(move x) => x,
        None => fail ~"option::unwrap none"
    }
}

/// The ubiquitous option dance.
#[inline(always)]
fn swap_unwrap<T>(opt: &mut Option<T>) -> T {
    if opt.is_none() { fail ~"option::swap_unwrap none" }
    unwrap(util::replace(opt, None))
}

pure fn unwrap_expect<T>(+opt: Option<T>, reason: &str) -> T {
    //! As unwrap, but with a specified failure message.
    if opt.is_none() { fail reason.to_unique(); }
    unwrap(opt)
}

// Some of these should change to be &Option<T>, some should not. See below.
impl<T> Option<T> {
    /**
     * Update an optional value by optionally running its content through a
     * function that returns an option.
     */
    pure fn chain<U>(f: fn(T) -> Option<U>) -> Option<U> { chain(self, f) }
    /// Applies a function to the contained value or returns a default
    pure fn map_default<U>(+def: U, f: fn(T) -> U) -> U
        { map_default(self, def, f) }
    /// Performs an operation on the contained value or does nothing
    pure fn iter(f: fn(T)) { iter(self, f) }
    /// Returns true if the option equals `none`
    pure fn is_none() -> bool { is_none(self) }
    /// Returns true if the option contains some value
    pure fn is_some() -> bool { is_some(self) }
    /// Maps a `some` value from one type to another
    pure fn map<U>(f: fn(T) -> U) -> Option<U> { map(self, f) }
}

impl<T> &Option<T> {
    /**
     * Update an optional value by optionally running its content by reference
     * through a function that returns an option.
     */
    pure fn chain_ref<U>(f: fn(x: &T) -> Option<U>) -> Option<U> {
        chain_ref(self, f)
    }
    /// Applies a function to the contained value or returns a default
    pure fn map_default_ref<U>(+def: U, f: fn(x: &T) -> U) -> U
        { map_default_ref(self, def, f) }
    /// Performs an operation on the contained value by reference
    pure fn iter_ref(f: fn(x: &T)) { iter_ref(self, f) }
    /// Maps a `some` value from one type to another by reference
    pure fn map_ref<U>(f: fn(x: &T) -> U) -> Option<U> { map_ref(self, f) }
    /// Gets an immutable reference to the value inside a `some`.
    pure fn get_ref() -> &self/T { get_ref(self) }
}

impl<T: copy> Option<T> {
    /**
     * Gets the value out of an option
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    pure fn get() -> T { get(self) }
    pure fn get_default(def: T) -> T { get_default(self, def) }
    /**
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    pure fn expect(reason: ~str) -> T { expect(self, reason) }
    /// Applies a function zero or more times until the result is none.
    pure fn while_some(blk: fn(+T) -> Option<T>) { while_some(self, blk) }
}

impl<T: Eq> Option<T> : Eq {
    pure fn eq(&&other: Option<T>) -> bool {
        match self {
            None => {
                match other {
                    None => true,
                    Some(_) => false
                }
            }
            Some(self_contents) => {
                match other {
                    None => false,
                    Some(other_contents) => self_contents.eq(other_contents)
                }
            }
        }
    }
}

#[test]
fn test_unwrap_ptr() {
    let x = ~0;
    let addr_x = ptr::addr_of(*x);
    let opt = Some(x);
    let y = unwrap(opt);
    let addr_y = ptr::addr_of(*y);
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_str() {
    let x = ~"test";
    let addr_x = str::as_buf(x, |buf, _len| ptr::addr_of(buf));
    let opt = Some(x);
    let y = unwrap(opt);
    let addr_y = str::as_buf(y, |buf, _len| ptr::addr_of(buf));
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_resource() {
    struct r {
       let i: @mut int;
       new(i: @mut int) { self.i = i; }
       drop { *(self.i) += 1; }
    }
    let i = @mut 0;
    {
        let x = r(i);
        let opt = Some(x);
        let _y = unwrap(opt);
    }
    assert *i == 1;
}

#[test]
fn test_option_dance() {
    let x = Some(());
    let mut y = Some(5);
    let mut y2 = 0;
    do x.iter |_x| {
        y2 = swap_unwrap(&mut y);
    }
    assert y2 == 5;
    assert y.is_none();
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_option_too_much_dance() {
    let mut y = Some(util::NonCopyable());
    let _y2 = swap_unwrap(&mut y);
    let _y3 = swap_unwrap(&mut y);
}

#[test]
fn test_option_while_some() {
    let mut i = 0;
    do Some(10).while_some |j| {
        i += 1;
        if (j > 0) {
            Some(j-1)
        } else {
            None
        }
    }
    assert i == 11;
}

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


<commit_before>
extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
// use gitlab::Pagination;
use gitlab::issues;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let gl = GitLab::new_https(&hostname, &token);

    let issues = gl.issues(issues::Listing::new()).unwrap();
    println!("issues: {:?}", issues);

    let listing = issues::Listing::new().state(issues::ListingState::Opened).clone();
    let opened_issues = gl.issues(listing).unwrap();
    println!("opened_issues: {:?}", opened_issues);

    let listing = issues::Listing::new().state(issues::ListingState::Closed).clone();
    let closed_issues = gl.issues(listing).unwrap();
    println!("closed_issues: {:?}", closed_issues);
}
<commit_msg>Add single listing to issue example.<commit_after>
extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
// use gitlab::Pagination;
use gitlab::issues;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let gl = GitLab::new_https(&hostname, &token);

    let issues = gl.issues(issues::Listing::new()).unwrap();
    println!("issues: {:?}", issues);

    let listing = issues::Listing::new().state(issues::ListingState::Opened).clone();
    let opened_issues = gl.issues(listing).unwrap();
    println!("opened_issues: {:?}", opened_issues);

    let listing = issues::Listing::new().state(issues::ListingState::Closed).clone();
    let closed_issues = gl.issues(listing).unwrap();
    println!("closed_issues: {:?}", closed_issues);

    let listing = issues::single::Listing::new(142, 739);
    let issue = gl.issue(listing).unwrap();
    println!("issue: {:?}", issue);
}
<|endoftext|>


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

/*! Utility implementations of Reader and Writer */

use prelude::*;
use cmp;
use io;
use slice::bytes::MutableByteVector;

/// Wraps a `Reader`, limiting the number of bytes that can be read from it.
pub struct LimitReader<R> {
    limit: uint,
    inner: R
}

impl<R: Reader> LimitReader<R> {
    /// Creates a new `LimitReader`
    pub fn new(r: R, limit: uint) -> LimitReader<R> {
        LimitReader { limit: limit, inner: r }
    }

    /// Consumes the `LimitReader`, returning the underlying `Reader`.
    pub fn unwrap(self) -> R { self.inner }

    /// Returns the number of bytes that can be read before the `LimitReader`
    /// will return EOF.
    ///
    /// # Note
    ///
    /// The reader may reach EOF after reading fewer bytes than indicated by
    /// this method if the underlying reader reaches EOF.
    pub fn limit(&self) -> uint { self.limit }
}

impl<R: Reader> Reader for LimitReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
        if self.limit == 0 {
            return Err(io::standard_error(io::EndOfFile));
        }

        let len = cmp::min(self.limit, buf.len());
        self.inner.read(buf.mut_slice_to(len)).map(|len| {
            self.limit -= len;
            len
        })
    }
}

/// A `Writer` which ignores bytes written to it, like /dev/null.
pub struct NullWriter;

impl Writer for NullWriter {
    #[inline]
    fn write(&mut self, _buf: &[u8]) -> io::IoResult<()> { Ok(()) }
}

/// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero.
pub struct ZeroReader;

impl Reader for ZeroReader {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
        buf.set_memory(0);
        Ok(buf.len())
    }
}

/// A `Reader` which is always at EOF, like /dev/null.
pub struct NullReader;

impl Reader for NullReader {
    #[inline]
    fn read(&mut self, _buf: &mut [u8]) -> io::IoResult<uint> {
        Err(io::standard_error(io::EndOfFile))
    }
}

/// A `Writer` which multiplexes writes to a set of `Writers`.
pub struct MultiWriter {
    writers: ~[~Writer]
}

impl MultiWriter {
    /// Creates a new `MultiWriter`
    pub fn new(writers: ~[~Writer]) -> MultiWriter {
        MultiWriter { writers: writers }
    }
}

impl Writer for MultiWriter {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
        let mut ret = Ok(());
        for writer in self.writers.mut_iter() {
            ret = ret.and(writer.write(buf));
        }
        return ret;
    }

    #[inline]
    fn flush(&mut self) -> io::IoResult<()> {
        let mut ret = Ok(());
        for writer in self.writers.mut_iter() {
            ret = ret.and(writer.flush());
        }
        return ret;
    }
}

/// A `Reader` which chains input from multiple `Readers`, reading each to
/// completion before moving onto the next.
pub struct ChainedReader<I, R> {
    readers: I,
    cur_reader: Option<R>,
}

impl<R: Reader, I: Iterator<R>> ChainedReader<I, R> {
    /// Creates a new `ChainedReader`
    pub fn new(mut readers: I) -> ChainedReader<I, R> {
        let r = readers.next();
        ChainedReader { readers: readers, cur_reader: r }
    }
}

impl<R: Reader, I: Iterator<R>> Reader for ChainedReader<I, R> {
    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
        loop {
            let err = match self.cur_reader {
                Some(ref mut r) => {
                    match r.read(buf) {
                        Ok(len) => return Ok(len),
                        Err(ref e) if e.kind == io::EndOfFile => None,
                        Err(e) => Some(e),
                    }
                }
                None => break
            };
            self.cur_reader = self.readers.next();
            match err {
                Some(e) => return Err(e),
                None => {}
            }
        }
        Err(io::standard_error(io::EndOfFile))
    }
}

/// A `Reader` which forwards input from another `Reader`, passing it along to
/// a `Writer` as well. Similar to the `tee(1)` command.
pub struct TeeReader<R, W> {
    reader: R,
    writer: W,
}

impl<R: Reader, W: Writer> TeeReader<R, W> {
    /// Creates a new `TeeReader`
    pub fn new(r: R, w: W) -> TeeReader<R, W> {
        TeeReader { reader: r, writer: w }
    }

    /// Consumes the `TeeReader`, returning the underlying `Reader` and
    /// `Writer`.
    pub fn unwrap(self) -> (R, W) {
        let TeeReader { reader, writer } = self;
        (reader, writer)
    }
}

impl<R: Reader, W: Writer> Reader for TeeReader<R, W> {
    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
        self.reader.read(buf).and_then(|len| {
            self.writer.write(buf.slice_to(len)).map(|()| len)
        })
    }
}

/// Copies all data from a `Reader` to a `Writer`.
pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
    let mut buf = [0, ..super::DEFAULT_BUF_SIZE];
    loop {
        let len = match r.read(buf) {
            Ok(len) => len,
            Err(ref e) if e.kind == io::EndOfFile => return Ok(()),
            Err(e) => return Err(e),
        };
        try!(w.write(buf.slice_to(len)));
    }
}

#[cfg(test)]
mod test {
    use io;
    use io::{MemReader, MemWriter};
    use super::*;
    use prelude::*;

    #[test]
    fn test_limit_reader_unlimited() {
        let mut r = MemReader::new(vec!(0, 1, 2));
        {
            let mut r = LimitReader::new(r.by_ref(), 4);
            assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
        }
    }

    #[test]
    fn test_limit_reader_limited() {
        let mut r = MemReader::new(vec!(0, 1, 2));
        {
            let mut r = LimitReader::new(r.by_ref(), 2);
            assert_eq!(vec!(0, 1), r.read_to_end().unwrap());
        }
        assert_eq!(vec!(2), r.read_to_end().unwrap());
    }

    #[test]
    fn test_limit_reader_limit() {
        let r = MemReader::new(vec!(0, 1, 2));
        let mut r = LimitReader::new(r, 3);
        assert_eq!(3, r.limit());
        assert_eq!(0, r.read_byte().unwrap());
        assert_eq!(2, r.limit());
        assert_eq!(vec!(1, 2), r.read_to_end().unwrap());
        assert_eq!(0, r.limit());
    }

    #[test]
    fn test_null_writer() {
        let mut s = NullWriter;
        let buf = ~[0, 0, 0];
        s.write(buf).unwrap();
        s.flush().unwrap();
    }

    #[test]
    fn test_zero_reader() {
        let mut s = ZeroReader;
        let mut buf = ~[1, 2, 3];
        assert_eq!(s.read(buf), Ok(3));
        assert_eq!(~[0, 0, 0], buf);
    }

    #[test]
    fn test_null_reader() {
        let mut r = NullReader;
        let mut buf = ~[0];
        assert!(r.read(buf).is_err());
    }

    #[test]
    fn test_multi_writer() {
        static mut writes: uint = 0;
        static mut flushes: uint = 0;

        struct TestWriter;
        impl Writer for TestWriter {
            fn write(&mut self, _buf: &[u8]) -> io::IoResult<()> {
                unsafe { writes += 1 }
                Ok(())
            }

            fn flush(&mut self) -> io::IoResult<()> {
                unsafe { flushes += 1 }
                Ok(())
            }
        }

        let mut multi = MultiWriter::new(~[~TestWriter as ~Writer,
                                           ~TestWriter as ~Writer]);
        multi.write([1, 2, 3]).unwrap();
        assert_eq!(2, unsafe { writes });
        assert_eq!(0, unsafe { flushes });
        multi.flush().unwrap();
        assert_eq!(2, unsafe { writes });
        assert_eq!(2, unsafe { flushes });
    }

    #[test]
    fn test_chained_reader() {
        let rs = ~[MemReader::new(vec!(0, 1)), MemReader::new(vec!()),
                   MemReader::new(vec!(2, 3))];
        let mut r = ChainedReader::new(rs.move_iter());
        assert_eq!(vec!(0, 1, 2, 3), r.read_to_end().unwrap());
    }

    #[test]
    fn test_tee_reader() {
        let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)),
                                   MemWriter::new());
        assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
        let (_, w) = r.unwrap();
        assert_eq!(vec!(0, 1, 2), w.unwrap());
    }

    #[test]
    fn test_copy() {
        let mut r = MemReader::new(vec!(0, 1, 2, 3, 4));
        let mut w = MemWriter::new();
        copy(&mut r, &mut w).unwrap();
        assert_eq!(vec!(0, 1, 2, 3, 4), w.unwrap());
    }
}
<commit_msg>De-~[] IO utils<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*! Utility implementations of Reader and Writer */

use prelude::*;
use cmp;
use io;
use slice::bytes::MutableByteVector;

/// Wraps a `Reader`, limiting the number of bytes that can be read from it.
pub struct LimitReader<R> {
    limit: uint,
    inner: R
}

impl<R: Reader> LimitReader<R> {
    /// Creates a new `LimitReader`
    pub fn new(r: R, limit: uint) -> LimitReader<R> {
        LimitReader { limit: limit, inner: r }
    }

    /// Consumes the `LimitReader`, returning the underlying `Reader`.
    pub fn unwrap(self) -> R { self.inner }

    /// Returns the number of bytes that can be read before the `LimitReader`
    /// will return EOF.
    ///
    /// # Note
    ///
    /// The reader may reach EOF after reading fewer bytes than indicated by
    /// this method if the underlying reader reaches EOF.
    pub fn limit(&self) -> uint { self.limit }
}

impl<R: Reader> Reader for LimitReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
        if self.limit == 0 {
            return Err(io::standard_error(io::EndOfFile));
        }

        let len = cmp::min(self.limit, buf.len());
        self.inner.read(buf.mut_slice_to(len)).map(|len| {
            self.limit -= len;
            len
        })
    }
}

/// A `Writer` which ignores bytes written to it, like /dev/null.
pub struct NullWriter;

impl Writer for NullWriter {
    #[inline]
    fn write(&mut self, _buf: &[u8]) -> io::IoResult<()> { Ok(()) }
}

/// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero.
pub struct ZeroReader;

impl Reader for ZeroReader {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
        buf.set_memory(0);
        Ok(buf.len())
    }
}

/// A `Reader` which is always at EOF, like /dev/null.
pub struct NullReader;

impl Reader for NullReader {
    #[inline]
    fn read(&mut self, _buf: &mut [u8]) -> io::IoResult<uint> {
        Err(io::standard_error(io::EndOfFile))
    }
}

/// A `Writer` which multiplexes writes to a set of `Writers`.
pub struct MultiWriter {
    writers: Vec<~Writer>
}

impl MultiWriter {
    /// Creates a new `MultiWriter`
    pub fn new(writers: Vec<~Writer>) -> MultiWriter {
        MultiWriter { writers: writers }
    }
}

impl Writer for MultiWriter {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
        let mut ret = Ok(());
        for writer in self.writers.mut_iter() {
            ret = ret.and(writer.write(buf));
        }
        return ret;
    }

    #[inline]
    fn flush(&mut self) -> io::IoResult<()> {
        let mut ret = Ok(());
        for writer in self.writers.mut_iter() {
            ret = ret.and(writer.flush());
        }
        return ret;
    }
}

/// A `Reader` which chains input from multiple `Readers`, reading each to
/// completion before moving onto the next.
pub struct ChainedReader<I, R> {
    readers: I,
    cur_reader: Option<R>,
}

impl<R: Reader, I: Iterator<R>> ChainedReader<I, R> {
    /// Creates a new `ChainedReader`
    pub fn new(mut readers: I) -> ChainedReader<I, R> {
        let r = readers.next();
        ChainedReader { readers: readers, cur_reader: r }
    }
}

impl<R: Reader, I: Iterator<R>> Reader for ChainedReader<I, R> {
    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
        loop {
            let err = match self.cur_reader {
                Some(ref mut r) => {
                    match r.read(buf) {
                        Ok(len) => return Ok(len),
                        Err(ref e) if e.kind == io::EndOfFile => None,
                        Err(e) => Some(e),
                    }
                }
                None => break
            };
            self.cur_reader = self.readers.next();
            match err {
                Some(e) => return Err(e),
                None => {}
            }
        }
        Err(io::standard_error(io::EndOfFile))
    }
}

/// A `Reader` which forwards input from another `Reader`, passing it along to
/// a `Writer` as well. Similar to the `tee(1)` command.
pub struct TeeReader<R, W> {
    reader: R,
    writer: W,
}

impl<R: Reader, W: Writer> TeeReader<R, W> {
    /// Creates a new `TeeReader`
    pub fn new(r: R, w: W) -> TeeReader<R, W> {
        TeeReader { reader: r, writer: w }
    }

    /// Consumes the `TeeReader`, returning the underlying `Reader` and
    /// `Writer`.
    pub fn unwrap(self) -> (R, W) {
        let TeeReader { reader, writer } = self;
        (reader, writer)
    }
}

impl<R: Reader, W: Writer> Reader for TeeReader<R, W> {
    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
        self.reader.read(buf).and_then(|len| {
            self.writer.write(buf.slice_to(len)).map(|()| len)
        })
    }
}

/// Copies all data from a `Reader` to a `Writer`.
pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
    let mut buf = [0, ..super::DEFAULT_BUF_SIZE];
    loop {
        let len = match r.read(buf) {
            Ok(len) => len,
            Err(ref e) if e.kind == io::EndOfFile => return Ok(()),
            Err(e) => return Err(e),
        };
        try!(w.write(buf.slice_to(len)));
    }
}

#[cfg(test)]
mod test {
    use io;
    use io::{MemReader, MemWriter};
    use super::*;
    use prelude::*;

    #[test]
    fn test_limit_reader_unlimited() {
        let mut r = MemReader::new(vec!(0, 1, 2));
        {
            let mut r = LimitReader::new(r.by_ref(), 4);
            assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
        }
    }

    #[test]
    fn test_limit_reader_limited() {
        let mut r = MemReader::new(vec!(0, 1, 2));
        {
            let mut r = LimitReader::new(r.by_ref(), 2);
            assert_eq!(vec!(0, 1), r.read_to_end().unwrap());
        }
        assert_eq!(vec!(2), r.read_to_end().unwrap());
    }

    #[test]
    fn test_limit_reader_limit() {
        let r = MemReader::new(vec!(0, 1, 2));
        let mut r = LimitReader::new(r, 3);
        assert_eq!(3, r.limit());
        assert_eq!(0, r.read_byte().unwrap());
        assert_eq!(2, r.limit());
        assert_eq!(vec!(1, 2), r.read_to_end().unwrap());
        assert_eq!(0, r.limit());
    }

    #[test]
    fn test_null_writer() {
        let mut s = NullWriter;
        let buf = ~[0, 0, 0];
        s.write(buf).unwrap();
        s.flush().unwrap();
    }

    #[test]
    fn test_zero_reader() {
        let mut s = ZeroReader;
        let mut buf = ~[1, 2, 3];
        assert_eq!(s.read(buf), Ok(3));
        assert_eq!(~[0, 0, 0], buf);
    }

    #[test]
    fn test_null_reader() {
        let mut r = NullReader;
        let mut buf = ~[0];
        assert!(r.read(buf).is_err());
    }

    #[test]
    fn test_multi_writer() {
        static mut writes: uint = 0;
        static mut flushes: uint = 0;

        struct TestWriter;
        impl Writer for TestWriter {
            fn write(&mut self, _buf: &[u8]) -> io::IoResult<()> {
                unsafe { writes += 1 }
                Ok(())
            }

            fn flush(&mut self) -> io::IoResult<()> {
                unsafe { flushes += 1 }
                Ok(())
            }
        }

        let mut multi = MultiWriter::new(vec!(~TestWriter as ~Writer,
                                              ~TestWriter as ~Writer));
        multi.write([1, 2, 3]).unwrap();
        assert_eq!(2, unsafe { writes });
        assert_eq!(0, unsafe { flushes });
        multi.flush().unwrap();
        assert_eq!(2, unsafe { writes });
        assert_eq!(2, unsafe { flushes });
    }

    #[test]
    fn test_chained_reader() {
        let rs = vec!(MemReader::new(vec!(0, 1)), MemReader::new(vec!()),
                      MemReader::new(vec!(2, 3)));
        let mut r = ChainedReader::new(rs.move_iter());
        assert_eq!(vec!(0, 1, 2, 3), r.read_to_end().unwrap());
    }

    #[test]
    fn test_tee_reader() {
        let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)),
                                   MemWriter::new());
        assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
        let (_, w) = r.unwrap();
        assert_eq!(vec!(0, 1, 2), w.unwrap());
    }

    #[test]
    fn test_copy() {
        let mut r = MemReader::new(vec!(0, 1, 2, 3, 4));
        let mut w = MemWriter::new();
        copy(&mut r, &mut w).unwrap();
        assert_eq!(vec!(0, 1, 2, 3, 4), w.unwrap());
    }
}
<|endoftext|>


<commit_before><commit_msg>Extent query explaination<commit_after><|endoftext|>


<commit_before>#![feature(test)]
#![feature(scoped)]
#![allow(dead_code)]

extern crate test;
extern crate columnar;
extern crate byteorder;
extern crate timely;

extern crate docopt;
use docopt::Docopt;

use test::Bencher;
use std::thread;
use std::hash::Hash;
use std::fmt::Debug;

use columnar::Columnar;

use timely::progress::Scope;
use timely::progress::nested::Summary::Local;
use timely::progress::timestamp::RootTimestamp;
use timely::communication::{ThreadCommunicator, ProcessCommunicator, Communicator};
use timely::communication::channels::Data;
use timely::networking::initialize_networking;

use timely::example_static::*;

static USAGE: &'static str = "
Usage: timely distinct [options] [<arguments>...]
       timely barrier [options] [<arguments>...]
       timely command [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
";

fn main() {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Hello, world!");
    println!("Starting timely with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");
        let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
        let communicators = initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking");
        if args.get_bool("distinct") { _distinct_multi(communicators); }
        else if args.get_bool("barrier") { _barrier_multi(communicators); }
        else if args.get_bool("command") { _command_multi(communicators); }
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        let communicators = ProcessCommunicator::new_vector(workers);
        if args.get_bool("distinct") { _distinct_multi(communicators); }
        else if args.get_bool("barrier") { _barrier_multi(communicators); }
        else if args.get_bool("command") { _command_multi(communicators); }
    }
    else {
        println!("Initializing ThreadCommunicator");
        let communicators = vec![ThreadCommunicator];
        if args.get_bool("distinct") { _distinct_multi(communicators); }
        else if args.get_bool("barrier") { _barrier_multi(communicators); }
        else if args.get_bool("command") { _command_multi(communicators); }
    };
}

#[bench]
fn distinct_bench(bencher: &mut Bencher) { _distinct(ProcessCommunicator::new_vector(1).swap_remove(0), Some(bencher)); }
fn _distinct_multi<C: Communicator+Send>(communicators: Vec<C>) {
    let mut guards = Vec::new();
    for communicator in communicators.into_iter() {
        guards.push(thread::Builder::new().name(format!("worker thread {}", communicator.index()))
                                          .scoped(move || _distinct(communicator, None))
                                          .unwrap());
    }
}

// #[bench]
// fn command_bench(bencher: &mut Bencher) { _command(ProcessCommunicator::new_vector(1).swap_remove(0).unwrap(), Some(bencher)); }
fn _command_multi<C: Communicator+Send>(_communicators: Vec<C>) {
    println!("command currently disabled awaiting io reform");
    // let mut guards = Vec::new();
    // for communicator in communicators.into_iter() {
    //     guards.push(thread::scoped(move || _command(communicator, None)));
    // }
}

#[bench]
fn barrier_bench(bencher: &mut Bencher) { _barrier(ProcessCommunicator::new_vector(1).swap_remove(0), Some(bencher)); }
fn _barrier_multi<C: Communicator+Send>(communicators: Vec<C>) {
    let mut guards = Vec::new();
    for communicator in communicators.into_iter() {
        guards.push(thread::scoped(move || _barrier(communicator, None)));
    }
}

fn create_subgraph<G: GraphBuilder, D>(builder: &mut G,
                                        source1: &Stream<G::Timestamp, D>,
                                        source2: &Stream<G::Timestamp, D>) ->
                                            (Stream<G::Timestamp, D>, Stream<G::Timestamp, D>)
where D: Data+Hash+Eq+Debug+Columnar, G::Timestamp: Hash {

    let mut subgraph = builder.new_subgraph::<u64>();

    (subgraph.enter(source1).distinct().leave(),
     subgraph.enter(source2).leave())
}

fn _distinct<C: Communicator>(communicator: C, bencher: Option<&mut Bencher>) {

    let mut root = GraphRoot::new(communicator);

    let (mut input1, mut input2) = {

        // allocate a new graph builder
        let mut graph = root.new_subgraph();

        // try building some input scopes
        let (input1, stream1) = graph.new_input::<u64>();
        let (input2, stream2) = graph.new_input::<u64>();

        // prepare some feedback edges
        let (loop1_source, loop1) = graph.loop_variable(RootTimestamp::new(100), Local(1));
        let (loop2_source, loop2) = graph.loop_variable(RootTimestamp::new(100), Local(1));

        let concat1 = (&mut graph).concatenate(vec![stream1, loop1]).disable();
        let concat2 = (&mut graph).concatenate(vec![stream2, loop2]).disable();

        // build up a subgraph using the concatenated inputs/feedbacks
        let (egress1, egress2) = create_subgraph(&mut graph, &concat1, &concat2);

        // connect feedback sources. notice that we have swapped indices ...
        egress1.enable(&mut graph).connect_loop(loop2_source);
        egress2.enable(&mut graph).connect_loop(loop1_source);

        (input1, input2)
    };

    root.step();

    // move some data into the dataflow graph.
    input1.send_messages(&RootTimestamp::new(0), vec![1u64]);
    input2.send_messages(&RootTimestamp::new(0), vec![2u64]);

    // see what everyone thinks about that ...
    root.step();

    input1.advance(&RootTimestamp::new(0), &RootTimestamp::new(1000000));
    input2.advance(&RootTimestamp::new(0), &RootTimestamp::new(1000000));
    input1.close_at(&RootTimestamp::new(1000000));
    input2.close_at(&RootTimestamp::new(1000000));

    // spin
    match bencher {
        Some(b) => b.iter(|| { root.step(); }),
        None    => while root.step() { }
    }
}

// fn _command<C: Communicator>(communicator: C, bencher: Option<&mut Bencher>) {
//     let communicator = Rc::new(RefCell::new(communicator));
//
//     // no "base scopes" yet, so the root pretends to be a subscope of some parent with a () timestamp type.
//     let mut graph = new_graph(Progcaster::new(&mut (*communicator.borrow_mut())));
//     let mut input = graph.new_input::<u64>(communicator);
//     let mut feedback = input.1.feedback(((), 1000), Local(1));
//     let mut result: Stream<_, u64, _> = input.1.concat(&mut feedback.1)
//                                                .command("./target/release/command".to_string());
//
//     feedback.0.connect_input(&mut result);
//
//     // start things up!
//     graph.borrow_mut().get_internal_summary();
//     graph.borrow_mut().set_external_summary(Vec::new(), &mut []);
//     graph.borrow_mut().push_external_progress(&mut []);
//
//     input.0.close_at(&((), 0));
//
//     // spin
//     match bencher {
//         Some(b) => b.iter(|| { graph.borrow_mut().pull_internal_progress(&mut [], &mut [], &mut []); }),
//         None    => while graph.borrow_mut().pull_internal_progress(&mut [], &mut [], &mut []) { },
//     }
// }

fn _barrier<C: Communicator>(communicator: C, bencher: Option<&mut Bencher>) {

    let mut root = GraphRoot::new(communicator);
    //
    // {
    //     let borrow = root.builder();
    //     let mut graph = SubgraphBuilder::new(&borrow);
    //
    //     let peers = graph.with_communicator(|x| x.peers());
    //     {
    //         let builder = &graph.builder();
    //
    //         builder.borrow_mut().add_scope(BarrierScope { epoch: 0, ready: true, degree: peers, ttl: 1000000 });
    //         builder.borrow_mut().connect(ScopeOutput(0, 0), ScopeInput(0, 0));
    //     }
    //
    //     graph.seal();
    // }
    //
    // // spin
    match bencher {
        Some(b) => b.iter(|| { root.step(); }),
        None    => while root.step() { },
    }
}
<commit_msg>main_static.rs moved to src/bin/main.rs<commit_after><|endoftext|>


<commit_before>//! Defines a specular glass material
//!
//! # Scene Usage Example
//! The specular glass material describes a thing glass surface type of material,
//! not a solid block of glass (there is no absorption of light). The glass requires
//! a reflective and emissive color along with a refrective index, eta.
//!
//! ```json
//! "materials": [
//!     {
//!         "name": "clear_glass",
//!         "type": "glass",
//!         "reflect": [1, 1, 1],
//!         "transmit": [1, 1, 1],
//!         "eta": 1.52
//!     },
//!     ...
//! ]
//! ```

use std::vec::Vec;

use film::Colorf;
use geometry::Intersection;
use bxdf::{BxDF, BSDF, SpecularReflection, SpecularTransmission};
use bxdf::fresnel::{Dielectric, Fresnel};
use material::Material;

/// The Glass material describes specularly transmissive and reflective glass material
pub struct Glass {
    bxdfs: Vec<Box<BxDF + Send + Sync>>,
    eta: f32,
}

impl Glass {
    /// Create the glass material with the desired color and index of refraction
    /// `reflect`: color of reflected light
    /// `transmit`: color of transmitted light
    /// `eta`: refractive index of the material
    pub fn new(reflect: &Colorf, transmit: &Colorf, eta: f32) -> Glass {
        let mut bxdfs = Vec::new();
        if !reflect.is_black() {
            bxdfs.push(Box::new(SpecularReflection::new(reflect,
                            Box::new(Dielectric::new(1.0, eta)) as Box<Fresnel + Send + Sync>))
                      as Box<BxDF + Send + Sync>);
        }
        if !transmit.is_black() {
            bxdfs.push(Box::new(SpecularTransmission::new(transmit, Dielectric::new(1.0, eta)))
                      as Box<BxDF + Send + Sync>);
        }
        Glass { bxdfs: bxdfs, eta: eta }
    }
}

impl Material for Glass {
    fn bsdf<'a, 'b>(&'a self, hit: &Intersection<'a, 'b>) -> BSDF<'a> {
        BSDF::new(&self.bxdfs, self.eta, &hit.dg)
    }
}

<commit_msg>Typo fix<commit_after>//! Defines a specular glass material
//!
//! # Scene Usage Example
//! The specular glass material describes a thin glass surface type of material,
//! not a solid block of glass (there is no absorption of light). The glass requires
//! a reflective and emissive color along with a refrective index, eta.
//!
//! ```json
//! "materials": [
//!     {
//!         "name": "clear_glass",
//!         "type": "glass",
//!         "reflect": [1, 1, 1],
//!         "transmit": [1, 1, 1],
//!         "eta": 1.52
//!     },
//!     ...
//! ]
//! ```

use std::vec::Vec;

use film::Colorf;
use geometry::Intersection;
use bxdf::{BxDF, BSDF, SpecularReflection, SpecularTransmission};
use bxdf::fresnel::{Dielectric, Fresnel};
use material::Material;

/// The Glass material describes specularly transmissive and reflective glass material
pub struct Glass {
    bxdfs: Vec<Box<BxDF + Send + Sync>>,
    eta: f32,
}

impl Glass {
    /// Create the glass material with the desired color and index of refraction
    /// `reflect`: color of reflected light
    /// `transmit`: color of transmitted light
    /// `eta`: refractive index of the material
    pub fn new(reflect: &Colorf, transmit: &Colorf, eta: f32) -> Glass {
        let mut bxdfs = Vec::new();
        if !reflect.is_black() {
            bxdfs.push(Box::new(SpecularReflection::new(reflect,
                            Box::new(Dielectric::new(1.0, eta)) as Box<Fresnel + Send + Sync>))
                      as Box<BxDF + Send + Sync>);
        }
        if !transmit.is_black() {
            bxdfs.push(Box::new(SpecularTransmission::new(transmit, Dielectric::new(1.0, eta)))
                      as Box<BxDF + Send + Sync>);
        }
        Glass { bxdfs: bxdfs, eta: eta }
    }
}

impl Material for Glass {
    fn bsdf<'a, 'b>(&'a self, hit: &Intersection<'a, 'b>) -> BSDF<'a> {
        BSDF::new(&self.bxdfs, self.eta, &hit.dg)
    }
}

<|endoftext|>


<commit_before>pub mod search;

use std::thread;
use std::cmp::min;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::time::SystemTime;
use basetypes::*;
use uci::{UciEngine, UciEngineFactory, EngineReply, OptionName, OptionDescription};
use position::Position;
use chess_move::*;
use tt::TranspositionTable;

// use rand;
// use rand::distributions::{Sample, Range};
// let mut rng = rand::thread_rng();
// let mut between = Range::new(0, 10);
// let x = between.sample(&mut rng);

const VERSION: &'static str = "0.1";
const MAX_DEPTH: u8 = 126;

/// Implements `UciEngine` trait.
pub struct Engine {
    position: Position,
    pondering_is_allowed: bool,
    is_thinking: bool,
    is_pondering: bool,
    replies: Vec<EngineReply>,
    tt: Arc<TranspositionTable>,
    commands: Sender<search::Command>,
    reports: Receiver<search::Report>,
    thinking_since: SystemTime,
    searched_nodes: NodeCount,
    searched_time: u64,  // milliseconds
    searched_depth: u8,
    stop_when: TimeManagement,
}

impl Engine {
    /// Creates a new instance.
    ///
    /// `tt_size_mb` is the preferred size of the transposition
    /// table in Mbytes.
    pub fn new(tt_size_mb: usize) -> Engine {
        let mut tt = TranspositionTable::new();
        tt.resize(tt_size_mb);
        let tt = Arc::new(tt);
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let tt2 = tt.clone();
        thread::spawn(move || {
            search::run_deepening(tt2, commands_rx, reports_tx);
        });

        Engine {
            position: Position::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w QKqk - 0 \
                                          1")
                          .ok()
                          .unwrap(),
            pondering_is_allowed: false,
            is_thinking: false,
            is_pondering: false,
            replies: vec![],
            tt: tt,
            commands: commands_tx,
            reports: reports_rx,
            thinking_since: SystemTime::now(),
            searched_nodes: 0,
            searched_time: 0,
            searched_depth: 0,
            stop_when: TimeManagement::Infinite,
        }
    }
}

impl UciEngine for Engine {
    fn set_option(&mut self, name: &str, value: &str) {
        match name {
            // Tells the engine that it will be allowed to ponder.
            // This option is needed because the engine might change
            // its time management algorithm when pondering is
            // allowed.
            "Ponder" => {
                self.pondering_is_allowed = value == "true";
            }

            // An invalid option. Notice that we do not support
            // re-sizing of the transposition table once the engine
            // had started.
            _ => (),
        }
    }

    fn new_game(&mut self) {
        // Clearing the transposition table would not change anything,
        // so we do nothing.
    }

    fn position(&mut self, fen: &str, moves: &mut Iterator<Item = &str>) {
        if !self.is_thinking {
            if let Ok(p) = Position::from_history(fen, moves) {
                self.position = p;
                self.tt.new_search();
            }
        }
    }

    #[allow(unused_variables)]
    fn go(&mut self,
          searchmoves: Option<Vec<String>>,
          ponder: bool,
          wtime: Option<u64>,
          btime: Option<u64>,
          winc: Option<u64>,
          binc: Option<u64>,
          movestogo: Option<u64>,
          depth: Option<u64>,
          nodes: Option<u64>,
          mate: Option<u64>,
          movetime: Option<u64>,
          infinite: bool) {
        if !self.is_thinking {
            // Note: We do not support the "searchmoves" parameter.

            let (time, inc) = if self.position.board().to_move() == WHITE {
                (wtime, winc.unwrap_or(0))
            } else {
                (btime, binc.unwrap_or(0))
            };
            self.is_thinking = true;
            self.is_pondering = ponder;
            self.stop_when = if infinite {
                TimeManagement::Infinite
            } else if movetime.is_some() {
                TimeManagement::MoveTime(movetime.unwrap())
            } else if nodes.is_some() {
                TimeManagement::Nodes(nodes.unwrap())
            } else if depth.is_some() {
                TimeManagement::Depth(min(depth.unwrap(), MAX_DEPTH as u64) as u8)
            } else {
                // TODO: Robert Hyatt proposes this:
                //
                // nMoves =  min( numberOfMovesOutOfBook, 10 )
                // factor = 2 - nMoves / 10
                // target = timeLeft / numberOfMovesUntilNextTimeControl
                // time   = factor * target
                let time = time.unwrap_or(0);
                let movestogo = movestogo.unwrap_or(40);
                let movetime = (time + inc * movestogo) / movestogo;
                TimeManagement::MoveTimeHint(min(movetime, time / 2))
            };
            self.thinking_since = SystemTime::now();
            self.searched_nodes = 0;
            self.searched_time = 0;
            self.searched_depth = 0;

            self.commands
                .send(search::Command::Search {
                    search_id: 0,
                    position: self.position.clone(),
                    depth: MAX_DEPTH,
                    lower_bound: -20000,
                    upper_bound: 20000,
                })
                .unwrap();
        }
    }

    fn ponder_hit(&mut self) {
        if self.is_thinking && self.is_pondering {
            self.is_pondering = false;
        }
    }

    fn stop(&mut self) {
        if self.is_thinking {
            self.commands.send(search::Command::Stop).unwrap();
            let best_move = self.get_best_move();
            self.replies.push(EngineReply::BestMove {
                best_move: best_move,
                ponder_move: None,
            });
            self.is_thinking = false;
        }
    }

    fn is_thinking(&self) -> bool {
        self.is_thinking
    }

    fn get_reply(&mut self) -> Option<EngineReply> {
        // TODO: implement panic mode for MoveTimeHint management.
        if self.is_thinking && !self.is_pondering {
            if match self.stop_when {
                TimeManagement::MoveTime(t) => self.searched_time >= t,
                TimeManagement::MoveTimeHint(t) => self.searched_time >= t,
                TimeManagement::Nodes(n) => self.searched_nodes >= n,
                TimeManagement::Depth(d) => self.searched_depth >= d,
                TimeManagement::Infinite => false,
            } {
                self.stop();
            }
        }

        // Empty the reports queue.
        while let Ok(report) = self.reports.try_recv() {
            // let rep_type = match report {
            //     search::Report::Progress { searched_nodes, .. } => format!("progress {}", searched_nodes),
            //     search::Report::Done { .. } => "done".to_string(),
            // };
            // self.replies.push(EngineReply::Info(vec![
            //     ("string".to_string(), rep_type),
            // ]));
            if self.is_thinking {
                match report {
                    search::Report::Progress { searched_nodes, depth, .. } => {
                        self.searched_nodes = searched_nodes;
                        let duration = self.thinking_since.elapsed().unwrap();
                        self.searched_time = 1000 * duration.as_secs() +
                                             (duration.subsec_nanos() / 1000000) as u64;
                        if self.searched_depth < depth {
                            self.searched_depth = depth;
                            let mut p = self.position.clone();
                            let mut v = MoveStack::new();
                            let mut pv = String::from("");
                            let mut pv_length = 0;
                            let mut value = None;
                            'depthloop: for _ in 0..depth {
                                let m = match self.tt.probe(p.hash()) {
                                    Some(entry) => {
                                        if value.is_none() {
                                            value = Some(entry.value());
                                        }
                                        entry.move16()
                                    }
                                    None => 0,
                                };
                                if m != 0 {
                                    p.generate_moves(&mut v);
                                    while let Some(x) = v.pop() {
                                        if x.digest() == m && p.do_move(x) {
                                            pv_length += 1;
                                            pv.push_str(&x.notation());
                                            pv.push(' ');
                                            v.clear();
                                            continue 'depthloop;
                                        }
                                    }
                                }
                                break;
                            }
                            if searched_nodes > 0 && pv_length >= depth {
                                self.replies.push(EngineReply::Info(vec![
                                    ("depth".to_string(), format!("{}", depth)),
                                    ("score".to_string(), format!("cp {}", value.unwrap_or(666))),
                                    ("nodes".to_string(), format!("{}", searched_nodes)),
                                    ("time".to_string(), format!("{}", self.searched_time)),
                                    ("pv".to_string(), format!("{}", pv)),
                                ]));
                            }
                        }
                    }
                    _ => (),
                }
            }
        }

        if self.replies.len() > 0 {
            Some(self.replies.remove(0))
        } else {
            None
        }
    }
}

impl Engine {
    fn get_best_move(&mut self) -> String {
        let mut m = match self.tt.probe(self.position.hash()) {
            Some(entry) => entry.move16(),
            None => 0,
        };
        if m == 0 {
            // Pick the first legal move.
            let mut first_legal_move = Move::invalid();
            let mut v = MoveStack::new();
            self.position.generate_moves(&mut v);
            while let Some(x) = v.pop() {
                if self.position.do_move(x) {
                    self.position.undo_move();
                    first_legal_move = x;
                    break;
                }
            }
            m = first_legal_move.digest();
        }
        if m != 0 {
            let move_type = move_type(m);
            let orig_square = orig_square(m);
            let dest_square = dest_square(m);
            let promoted_piece = match aux_data(m) {
                0 => "q",
                1 => "r",
                2 => "b",
                3 => "n",
                _ => panic!("invalid promoted piece code"),
            };
            format!("{}{}{}",
                    notation(orig_square),
                    notation(dest_square),
                    if move_type == MOVE_PROMOTION {
                        promoted_piece
                    } else {
                        ""
                    })

        } else {
            "0000".to_string()
        }
    }
}

/// Implements `UciEngineFactory` trait.
pub struct EngineFactory;

impl UciEngineFactory<Engine> for EngineFactory {
    fn name(&self) -> String {
        format!("Alcibiades {}", VERSION)
    }

    fn author(&self) -> String {
        "Evgeni Pandurski".to_string()
    }

    fn options(&self) -> Vec<(OptionName, OptionDescription)> {
        vec![
            // TODO: Calculate a sane limit for the hash size.
            ("Hash".to_string(), OptionDescription::Spin { min: 1, max: 2048, default: 16 }),
            ("Ponder".to_string(), OptionDescription::Check { default: false }),
        ]
    }

    fn create(&self, hash_size_mb: Option<usize>) -> Engine {
        Engine::new(hash_size_mb.unwrap_or(16))
    }
}

enum TimeManagement {
    MoveTime(u64),
    MoveTimeHint(u64),
    Nodes(NodeCount),
    Depth(u8),
    Infinite,
}
<commit_msg>comments<commit_after>pub mod search;

use std::thread;
use std::cmp::min;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::time::SystemTime;
use basetypes::*;
use uci::{UciEngine, UciEngineFactory, EngineReply, OptionName, OptionDescription};
use position::Position;
use chess_move::*;
use tt::TranspositionTable;

// use rand;
// use rand::distributions::{Sample, Range};
// let mut rng = rand::thread_rng();
// let mut between = Range::new(0, 10);
// let x = between.sample(&mut rng);

const VERSION: &'static str = "0.1";
const MAX_DEPTH: u8 = 126;

/// Implements `UciEngine` trait.
pub struct Engine {
    position: Position,
    pondering_is_allowed: bool,
    is_thinking: bool,
    is_pondering: bool,
    replies: Vec<EngineReply>,
    tt: Arc<TranspositionTable>,
    commands: Sender<search::Command>,
    reports: Receiver<search::Report>,
    thinking_since: SystemTime,
    searched_nodes: NodeCount,
    searched_time: u64, // milliseconds
    searched_depth: u8,
    stop_when: TimeManagement,
}

impl Engine {
    /// Creates a new instance.
    ///
    /// `tt_size_mb` is the preferred size of the transposition
    /// table in Mbytes.
    pub fn new(tt_size_mb: usize) -> Engine {
        let mut tt = TranspositionTable::new();
        tt.resize(tt_size_mb);
        let tt = Arc::new(tt);
        let (commands_tx, commands_rx) = channel();
        let (reports_tx, reports_rx) = channel();
        let tt2 = tt.clone();
        thread::spawn(move || {
            search::run_deepening(tt2, commands_rx, reports_tx);
        });

        Engine {
            position: Position::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w QKqk - 0 \
                                          1")
                          .ok()
                          .unwrap(),
            pondering_is_allowed: false,
            is_thinking: false,
            is_pondering: false,
            replies: vec![],
            tt: tt,
            commands: commands_tx,
            reports: reports_rx,
            thinking_since: SystemTime::now(),
            searched_nodes: 0,
            searched_time: 0,
            searched_depth: 0,
            stop_when: TimeManagement::Infinite,
        }
    }
}

impl UciEngine for Engine {
    fn set_option(&mut self, name: &str, value: &str) {
        match name {
            // Tells the engine that it will be allowed to ponder.
            // This option is needed because the engine might change
            // its time management algorithm when pondering is
            // allowed.
            "Ponder" => {
                self.pondering_is_allowed = value == "true";
            }

            // An invalid option. Notice that we do not support
            // re-sizing of the transposition table once the engine
            // had started.
            _ => (),
        }
    }

    fn new_game(&mut self) {
        // Clearing the transposition table would not change anything,
        // so we do nothing.
    }

    fn position(&mut self, fen: &str, moves: &mut Iterator<Item = &str>) {
        if !self.is_thinking {
            if let Ok(p) = Position::from_history(fen, moves) {
                self.position = p;
                self.tt.new_search();
            }
        }
    }

    #[allow(unused_variables)]
    fn go(&mut self,
          searchmoves: Option<Vec<String>>,
          ponder: bool,
          wtime: Option<u64>,
          btime: Option<u64>,
          winc: Option<u64>,
          binc: Option<u64>,
          movestogo: Option<u64>,
          depth: Option<u64>,
          nodes: Option<u64>,
          mate: Option<u64>,
          movetime: Option<u64>,
          infinite: bool) {
        if !self.is_thinking {
            // Note: We ignore the "searchmoves" parameter.

            self.is_thinking = true;
            self.is_pondering = ponder;
            self.thinking_since = SystemTime::now();
            self.searched_nodes = 0;
            self.searched_time = 0;
            self.searched_depth = 0;

            // Figure out when we should stop thinking.
            let (time, inc) = if self.position.board().to_move() == WHITE {
                (wtime, winc.unwrap_or(0))
            } else {
                (btime, binc.unwrap_or(0))
            };
            self.stop_when = if infinite {
                TimeManagement::Infinite
            } else if movetime.is_some() {
                TimeManagement::MoveTime(movetime.unwrap())
            } else if nodes.is_some() {
                TimeManagement::Nodes(nodes.unwrap())
            } else if depth.is_some() {
                TimeManagement::Depth(min(depth.unwrap(), MAX_DEPTH as u64) as u8)
            } else {
                // TODO: Robert Hyatt proposes this:
                //
                // nMoves =  min( numberOfMovesOutOfBook, 10 )
                // factor = 2 - nMoves / 10
                // target = timeLeft / numberOfMovesUntilNextTimeControl
                // time   = factor * target
                let time = time.unwrap_or(0);
                let movestogo = movestogo.unwrap_or(40);
                let movetime = (time + inc * movestogo) / movestogo;
                TimeManagement::MoveTimeHint(min(movetime, time / 2))
            };

            // Start a search with the maximum possible depth.
            self.commands
                .send(search::Command::Search {
                    search_id: 0,
                    position: self.position.clone(),
                    depth: MAX_DEPTH,
                    lower_bound: -20000,
                    upper_bound: 20000,
                })
                .unwrap();
        }
    }

    fn ponder_hit(&mut self) {
        if self.is_thinking && self.is_pondering {
            self.is_pondering = false;
        }
    }

    fn stop(&mut self) {
        if self.is_thinking {
            self.commands.send(search::Command::Stop).unwrap();
            let best_move = self.get_best_move();
            self.replies.push(EngineReply::BestMove {
                best_move: best_move,
                ponder_move: None,
            });
            self.is_thinking = false;
        }
    }

    fn is_thinking(&self) -> bool {
        self.is_thinking
    }

    fn get_reply(&mut self) -> Option<EngineReply> {
        // TODO: implement panic mode for MoveTimeHint management.
        if self.is_thinking && !self.is_pondering {
            if match self.stop_when {
                TimeManagement::MoveTime(t) => self.searched_time >= t,
                TimeManagement::MoveTimeHint(t) => self.searched_time >= t,
                TimeManagement::Nodes(n) => self.searched_nodes >= n,
                TimeManagement::Depth(d) => self.searched_depth >= d,
                TimeManagement::Infinite => false,
            } {
                self.stop();
            }
        }

        // Empty the reports queue.
        while let Ok(report) = self.reports.try_recv() {
            // let rep_type = match report {
            //     search::Report::Progress { searched_nodes, .. } => format!("progress {}", searched_nodes),
            //     search::Report::Done { .. } => "done".to_string(),
            // };
            // self.replies.push(EngineReply::Info(vec![
            //     ("string".to_string(), rep_type),
            // ]));
            if self.is_thinking {
                match report {
                    search::Report::Progress { searched_nodes, depth, .. } => {
                        self.searched_nodes = searched_nodes;
                        let duration = self.thinking_since.elapsed().unwrap();
                        self.searched_time = 1000 * duration.as_secs() +
                                             (duration.subsec_nanos() / 1000000) as u64;
                        if self.searched_depth < depth {
                            self.searched_depth = depth;
                            let mut p = self.position.clone();
                            let mut v = MoveStack::new();
                            let mut pv = String::from("");
                            let mut pv_length = 0;
                            let mut value = None;
                            'depthloop: for _ in 0..depth {
                                let m = match self.tt.probe(p.hash()) {
                                    Some(entry) => {
                                        if value.is_none() {
                                            value = Some(entry.value());
                                        }
                                        entry.move16()
                                    }
                                    None => 0,
                                };
                                if m != 0 {
                                    p.generate_moves(&mut v);
                                    while let Some(x) = v.pop() {
                                        if x.digest() == m && p.do_move(x) {
                                            pv_length += 1;
                                            pv.push_str(&x.notation());
                                            pv.push(' ');
                                            v.clear();
                                            continue 'depthloop;
                                        }
                                    }
                                }
                                break;
                            }
                            if searched_nodes > 0 && pv_length >= depth {
                                self.replies.push(EngineReply::Info(vec![
                                    ("depth".to_string(), format!("{}", depth)),
                                    ("score".to_string(), format!("cp {}", value.unwrap_or(666))),
                                    ("nodes".to_string(), format!("{}", searched_nodes)),
                                    ("time".to_string(), format!("{}", self.searched_time)),
                                    ("pv".to_string(), format!("{}", pv)),
                                ]));
                            }
                        }
                    }
                    _ => (),
                }
            }
        }

        if self.replies.len() > 0 {
            Some(self.replies.remove(0))
        } else {
            None
        }
    }
}

impl Engine {
    fn get_best_move(&mut self) -> String {
        let mut m = match self.tt.probe(self.position.hash()) {
            Some(entry) => entry.move16(),
            None => 0,
        };
        if m == 0 {
            // Pick the first legal move.
            let mut first_legal_move = Move::invalid();
            let mut v = MoveStack::new();
            self.position.generate_moves(&mut v);
            while let Some(x) = v.pop() {
                if self.position.do_move(x) {
                    self.position.undo_move();
                    first_legal_move = x;
                    break;
                }
            }
            m = first_legal_move.digest();
        }
        if m != 0 {
            let move_type = move_type(m);
            let orig_square = orig_square(m);
            let dest_square = dest_square(m);
            let promoted_piece = match aux_data(m) {
                0 => "q",
                1 => "r",
                2 => "b",
                3 => "n",
                _ => panic!("invalid promoted piece code"),
            };
            format!("{}{}{}",
                    notation(orig_square),
                    notation(dest_square),
                    if move_type == MOVE_PROMOTION {
                        promoted_piece
                    } else {
                        ""
                    })

        } else {
            "0000".to_string()
        }
    }
}

/// Implements `UciEngineFactory` trait.
pub struct EngineFactory;

impl UciEngineFactory<Engine> for EngineFactory {
    fn name(&self) -> String {
        format!("Alcibiades {}", VERSION)
    }

    fn author(&self) -> String {
        "Evgeni Pandurski".to_string()
    }

    fn options(&self) -> Vec<(OptionName, OptionDescription)> {
        vec![
            // TODO: Calculate a sane limit for the hash size.
            ("Hash".to_string(), OptionDescription::Spin { min: 1, max: 2048, default: 16 }),
            ("Ponder".to_string(), OptionDescription::Check { default: false }),
        ]
    }

    fn create(&self, hash_size_mb: Option<usize>) -> Engine {
        Engine::new(hash_size_mb.unwrap_or(16))
    }
}

enum TimeManagement {
    MoveTime(u64),
    MoveTimeHint(u64),
    Nodes(NodeCount),
    Depth(u8),
    Infinite,
}
<|endoftext|>


<commit_before>fn main() {
    // `{}` are placeholders for arguments that will be stringified.
    println!("{} days", 31);

    // Without a suffix, 31 becomes an i32. You can change what type 31 is,
    // with a suffix, and that is covered in the next chapter.

    // The positional arguments can be reused along the template.
    println!("{0}, this is {1}. {1}, this is {0}", "Alice", "Bob");

    // Named arguments can also be used.
    println!("{subject} {verb} {predicate}",
             predicate="over the lazy dog",
             subject="the quick brown fox",
             verb="jumps");

    // Special formatting can be specified in the placeholder after a `:`.
    println!("{} of {:b} people know binary, the other half don't", 1, 2);

    // Error! You are missing an argument.
    println!("My name is {0}, {1} {0}", "Bond");
    // FIXME ^ Add the missing argument: "James"
}
<commit_msg>{} to {:?}<commit_after>fn main() {
    // `{:?}` are placeholders for arguments that will be stringified.
    println!("{:?} days", 31);

    // Without a suffix, 31 becomes an i32. You can change what type 31 is,
    // with a suffix, and that is covered in the next chapter.

    // The positional arguments can be reused along the template.
    println!("{0:?}, this is {1:?}. {1:?}, this is {0:?}", "Alice", "Bob");

    // Named arguments can also be used.
    println!("{subject:?} {verb:?} {predicate:?}",
             predicate="over the lazy dog",
             subject="the quick brown fox",
             verb="jumps");

    // Special formatting can be specified in the place of the `?`.
    println!("{:?} of {:b} people know binary, the other half don't", 1, 2);

    // Error! You are missing an argument.
    println!("My name is {0:?}, {1:?} {0:?}", "Bond");
    // FIXME ^ Add the missing argument: "James"
}
<|endoftext|>