<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// The task that handles all rendering/painting.

use azure::azure_hl::{B8G8R8A8, Color, DrawTarget, StolenGLResources};
use azure::AzFloat;
use geom::matrix2d::Matrix2D;
use geom::rect::Rect;
use geom::size::Size2D;
use layers::platform::surface::{NativePaintingGraphicsContext, NativeSurface};
use layers::platform::surface::{NativeSurfaceMethods};
use layers;
use servo_msg::compositor_msg::{Epoch, IdleRenderState, LayerBuffer, LayerBufferSet};
use servo_msg::compositor_msg::{RenderListener, RenderingRenderState};
use servo_msg::constellation_msg::{ConstellationChan, PipelineId, RendererReadyMsg};
use servo_msg::constellation_msg::{Failure, FailureMsg};
use servo_msg::platform::surface::NativeSurfaceAzureMethods;
use servo_util::opts::Opts;
use servo_util::time::{ProfilerChan, profile};
use servo_util::time;
use servo_util::task::send_on_failure;

use std::comm::{Chan, Port};
use std::task;
use sync::Arc;

use buffer_map::BufferMap;
use display_list::DisplayListCollection;
use font_context::{FontContext, FontContextInfo};
use render_context::RenderContext;

pub struct RenderLayer<T> {
    display_list_collection: Arc<DisplayListCollection<T>>,
    size: Size2D<uint>,
    color: Color
}

pub enum Msg<T> {
    RenderMsg(RenderLayer<T>),
    ReRenderMsg(~[BufferRequest], f32, Epoch),
    UnusedBufferMsg(~[~LayerBuffer]),
    PaintPermissionGranted,
    PaintPermissionRevoked,
    ExitMsg(Option<Chan<()>>),
}

/// A request from the compositor to the renderer for tiles that need to be (re)displayed.
#[deriving(Clone)]
pub struct BufferRequest {
    // The rect in pixels that will be drawn to the screen
    screen_rect: Rect<uint>,

    // The rect in page coordinates that this tile represents
    page_rect: Rect<f32>,
}

pub fn BufferRequest(screen_rect: Rect<uint>, page_rect: Rect<f32>) -> BufferRequest {
    BufferRequest {
        screen_rect: screen_rect,
        page_rect: page_rect,
    }
}

// FIXME(rust#9155): this should be a newtype struct, but
// generic newtypes ICE when compiled cross-crate
pub struct RenderChan<T> {
    chan: Chan<Msg<T>>,
}

impl<T: Send> Clone for RenderChan<T> {
    fn clone(&self) -> RenderChan<T> {
        RenderChan {
            chan: self.chan.clone(),
        }
    }
}

impl<T: Send> RenderChan<T> {
    pub fn new() -> (Port<Msg<T>>, RenderChan<T>) {
        let (port, chan) = Chan::new();
        let render_chan = RenderChan {
            chan: chan,
        };
        (port, render_chan)
    }

    pub fn send(&self, msg: Msg<T>) {
        assert!(self.try_send(msg), "RenderChan.send: render port closed")
    }

    pub fn try_send(&self, msg: Msg<T>) -> bool {
        self.chan.try_send(msg)
    }
}

/// If we're using GPU rendering, this provides the metadata needed to create a GL context that
/// is compatible with that of the main thread.
enum GraphicsContext {
    CpuGraphicsContext,
    GpuGraphicsContext,
}

pub struct RenderTask<C,T> {
    id: PipelineId,
    port: Port<Msg<T>>,
    compositor: C,
    constellation_chan: ConstellationChan,
    font_ctx: ~FontContext,
    opts: Opts,

    /// A channel to the profiler.
    profiler_chan: ProfilerChan,

    /// The graphics context to use.
    graphics_context: GraphicsContext,

    /// The native graphics context.
    native_graphics_context: Option<NativePaintingGraphicsContext>,

    /// The layer to be rendered
    render_layer: Option<RenderLayer<T>>,

    /// Permission to send paint messages to the compositor
    paint_permission: bool,

    /// A counter for epoch messages
    epoch: Epoch,

    /// A data structure to store unused LayerBuffers
    buffer_map: BufferMap<~LayerBuffer>,
}

// If we implement this as a function, we get borrowck errors from borrowing
// the whole RenderTask struct.
macro_rules! native_graphics_context(
    ($task:expr) => (
        $task.native_graphics_context.as_ref().expect("Need a graphics context to do rendering")
    )
)

impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
    pub fn create(id: PipelineId,
                  port: Port<Msg<T>>,
                  compositor: C,
                  constellation_chan: ConstellationChan,
                  failure_msg: Failure,
                  opts: Opts,
                  profiler_chan: ProfilerChan,
                  shutdown_chan: Chan<()>) {
        let mut builder = task::task().named("RenderTask");
        let ConstellationChan(c) = constellation_chan.clone();
        send_on_failure(&mut builder, FailureMsg(failure_msg), c);
        builder.spawn(proc() {

            { // Ensures RenderTask and graphics context are destroyed before shutdown msg
                let native_graphics_context = compositor.get_graphics_metadata().map(
                    |md| NativePaintingGraphicsContext::from_metadata(&md));
                let cpu_painting = opts.cpu_painting;

                // FIXME: rust/#5967
                let mut render_task = RenderTask {
                    id: id,
                    port: port,
                    compositor: compositor,
                    constellation_chan: constellation_chan,
                    font_ctx: ~FontContext::new(FontContextInfo {
                        backend: opts.render_backend.clone(),
                        needs_font_list: false,
                        profiler_chan: profiler_chan.clone(),
                    }),
                    opts: opts,
                    profiler_chan: profiler_chan,

                    graphics_context: if cpu_painting {
                        CpuGraphicsContext
                    } else {
                        GpuGraphicsContext
                    },

                    native_graphics_context: native_graphics_context,

                    render_layer: None,

                    paint_permission: false,
                    epoch: Epoch(0),
                    buffer_map: BufferMap::new(10000000),
                };

                render_task.start();

                // Destroy all the buffers.
                {
                    let ctx = render_task.native_graphics_context.as_ref().unwrap();
                    render_task.buffer_map.clear(ctx);
                }
            }

            debug!("render_task: shutdown_chan send");
            shutdown_chan.send(());
        });
    }

    fn start(&mut self) {
        debug!("render_task: beginning rendering loop");

        loop {
            match self.port.recv() {
                RenderMsg(render_layer) => {
                    if self.paint_permission {
                        self.epoch.next();
                        self.compositor.set_layer_page_size_and_color(self.id, render_layer.size, self.epoch, render_layer.color);
                    } else {
                        debug!("render_task: render ready msg");
                        let ConstellationChan(ref mut c) = self.constellation_chan;
                        c.send(RendererReadyMsg(self.id));
                    }
                    self.render_layer = Some(render_layer);
                }
                ReRenderMsg(tiles, scale, epoch) => {
                    if self.epoch == epoch {
                        self.render(tiles, scale);
                    } else {
                        debug!("renderer epoch mismatch: {:?} != {:?}", self.epoch, epoch);
                    }
                }
                UnusedBufferMsg(unused_buffers) => {
                    // move_rev_iter is more efficient
                    for buffer in unused_buffers.move_rev_iter() {
                        self.buffer_map.insert(native_graphics_context!(self), buffer);
                    }
                }
                PaintPermissionGranted => {
                    self.paint_permission = true;
                    match self.render_layer {
                        Some(ref render_layer) => {
                            self.epoch.next();
                            self.compositor.set_layer_page_size_and_color(self.id, render_layer.size, self.epoch, render_layer.color);
                        }
                        None => {}
                    }
                }
                PaintPermissionRevoked => {
                    self.paint_permission = false;
                }
                ExitMsg(response_ch) => {
                    debug!("render_task: exitmsg response send");
                    response_ch.map(|ch| ch.send(()));
                    break;
                }
            }
        }
    }

    fn render(&mut self, tiles: ~[BufferRequest], scale: f32) {
        if self.render_layer.is_none() {
            return
        }

        self.compositor.set_render_state(RenderingRenderState);
        time::profile(time::RenderingCategory, self.profiler_chan.clone(), || {
            // FIXME: Try not to create a new array here.
            let mut new_buffers = ~[];

            // Divide up the layer into tiles.
            time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone(), || {
                for tile in tiles.iter() {
                    let width = tile.screen_rect.size.width;
                    let height = tile.screen_rect.size.height;

                    let size = Size2D(width as i32, height as i32);
                    let draw_target = match self.graphics_context {
                        CpuGraphicsContext => {
                            DrawTarget::new(self.opts.render_backend, size, B8G8R8A8)
                        }
                        GpuGraphicsContext => {
                            // FIXME(pcwalton): Cache the components of draw targets
                            // (texture color buffer, renderbuffers) instead of recreating them.
                            let draw_target =
                                DrawTarget::new_with_fbo(self.opts.render_backend,
                                                         native_graphics_context!(self),
                                                         size,
                                                         B8G8R8A8);
                            draw_target.make_current();
                            draw_target
                        }
                    };

                    {
                        // Build the render context.
                        let mut ctx = RenderContext {
                            draw_target: &draw_target,
                            font_ctx: &mut self.font_ctx,
                            opts: &self.opts,
                            page_rect: tile.page_rect,
                            screen_rect: tile.screen_rect,
                        };

                        // Apply the translation to render the tile we want.
                        let matrix: Matrix2D<AzFloat> = Matrix2D::identity();
                        let matrix = matrix.scale(scale as AzFloat, scale as AzFloat);
                        let matrix = matrix.translate(-(tile.page_rect.origin.x) as AzFloat,
                                                      -(tile.page_rect.origin.y) as AzFloat);

                        ctx.draw_target.set_transform(&matrix);

                        // Clear the buffer.
                        ctx.clear();

                        // Draw the display list.
                        profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || {
                            let render_layer = self.render_layer.as_ref().unwrap();
                            render_layer.display_list_collection.get().draw_lists_into_context(&mut ctx);
                            ctx.draw_target.flush();
                        });
                    }

                    // Extract the texture from the draw target and place it into its slot in the
                    // buffer. If using CPU rendering, upload it first.
                    //
                    // FIXME(pcwalton): We should supply the texture and native surface *to* the
                    // draw target in GPU rendering mode, so that it doesn't have to recreate it.
                    let buffer = match self.graphics_context {
                        CpuGraphicsContext => {
                            let buffer = match self.buffer_map.find(tile.screen_rect.size) {
                                Some(buffer) => {
                                    let mut buffer = buffer;
                                    buffer.rect = tile.page_rect;
                                    buffer.screen_pos = tile.screen_rect;
                                    buffer.resolution = scale;
                                    buffer.native_surface.mark_wont_leak();
                                    buffer
                                }
                                None => {
                                    // Create an empty native surface. We mark it as not leaking
                                    // in case it dies in transit to the compositor task.
                                    let mut native_surface: NativeSurface =
                                        layers::platform::surface::NativeSurfaceMethods::new(
                                            native_graphics_context!(self),
                                            Size2D(width as i32, height as i32),
                                            width as i32 * 4);
                                    native_surface.mark_wont_leak();

                                    ~LayerBuffer {
                                        native_surface: native_surface,
                                        rect: tile.page_rect,
                                        screen_pos: tile.screen_rect,
                                        resolution: scale,
                                        stride: (width * 4) as uint
                                    }
                                }
                            };

                            draw_target.snapshot().get_data_surface().with_data(|data| {
                                buffer.native_surface.upload(native_graphics_context!(self), data);
                                debug!("RENDERER uploading to native surface {:d}",
                                       buffer.native_surface.get_id() as int);
                            });

                            buffer
                        }
                        GpuGraphicsContext => {
                            draw_target.make_current();
                            let StolenGLResources {
                                surface: native_surface
                            } = draw_target.steal_gl_resources().unwrap();

                            // We mark the native surface as not leaking in case the surfaces
                            // die on their way to the compositor task.
                            let mut native_surface: NativeSurface =
                                NativeSurfaceAzureMethods::from_azure_surface(native_surface);
                            native_surface.mark_wont_leak();

                            ~LayerBuffer {
                                native_surface: native_surface,
                                rect: tile.page_rect,
                                screen_pos: tile.screen_rect,
                                resolution: scale,
                                stride: (width * 4) as uint
                            }
                        }
                    };

                    new_buffers.push(buffer);
                }
            });

            let layer_buffer_set = ~LayerBufferSet {
                buffers: new_buffers,
            };

            debug!("render_task: returning surface");
            if self.paint_permission {
                self.compositor.paint(self.id, layer_buffer_set, self.epoch);
            } else {
                debug!("render_task: RendererReadyMsg send");
                let ConstellationChan(ref mut c) = self.constellation_chan;
                c.send(RendererReadyMsg(self.id));
            }
            self.compositor.set_render_state(IdleRenderState);
        })
    }
}

<commit_msg>Check properly for None in the headless compositor case<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// The task that handles all rendering/painting.

use azure::azure_hl::{B8G8R8A8, Color, DrawTarget, StolenGLResources};
use azure::AzFloat;
use geom::matrix2d::Matrix2D;
use geom::rect::Rect;
use geom::size::Size2D;
use layers::platform::surface::{NativePaintingGraphicsContext, NativeSurface};
use layers::platform::surface::{NativeSurfaceMethods};
use layers;
use servo_msg::compositor_msg::{Epoch, IdleRenderState, LayerBuffer, LayerBufferSet};
use servo_msg::compositor_msg::{RenderListener, RenderingRenderState};
use servo_msg::constellation_msg::{ConstellationChan, PipelineId, RendererReadyMsg};
use servo_msg::constellation_msg::{Failure, FailureMsg};
use servo_msg::platform::surface::NativeSurfaceAzureMethods;
use servo_util::opts::Opts;
use servo_util::time::{ProfilerChan, profile};
use servo_util::time;
use servo_util::task::send_on_failure;

use std::comm::{Chan, Port};
use std::task;
use sync::Arc;

use buffer_map::BufferMap;
use display_list::DisplayListCollection;
use font_context::{FontContext, FontContextInfo};
use render_context::RenderContext;

pub struct RenderLayer<T> {
    display_list_collection: Arc<DisplayListCollection<T>>,
    size: Size2D<uint>,
    color: Color
}

pub enum Msg<T> {
    RenderMsg(RenderLayer<T>),
    ReRenderMsg(~[BufferRequest], f32, Epoch),
    UnusedBufferMsg(~[~LayerBuffer]),
    PaintPermissionGranted,
    PaintPermissionRevoked,
    ExitMsg(Option<Chan<()>>),
}

/// A request from the compositor to the renderer for tiles that need to be (re)displayed.
#[deriving(Clone)]
pub struct BufferRequest {
    // The rect in pixels that will be drawn to the screen
    screen_rect: Rect<uint>,

    // The rect in page coordinates that this tile represents
    page_rect: Rect<f32>,
}

pub fn BufferRequest(screen_rect: Rect<uint>, page_rect: Rect<f32>) -> BufferRequest {
    BufferRequest {
        screen_rect: screen_rect,
        page_rect: page_rect,
    }
}

// FIXME(rust#9155): this should be a newtype struct, but
// generic newtypes ICE when compiled cross-crate
pub struct RenderChan<T> {
    chan: Chan<Msg<T>>,
}

impl<T: Send> Clone for RenderChan<T> {
    fn clone(&self) -> RenderChan<T> {
        RenderChan {
            chan: self.chan.clone(),
        }
    }
}

impl<T: Send> RenderChan<T> {
    pub fn new() -> (Port<Msg<T>>, RenderChan<T>) {
        let (port, chan) = Chan::new();
        let render_chan = RenderChan {
            chan: chan,
        };
        (port, render_chan)
    }

    pub fn send(&self, msg: Msg<T>) {
        assert!(self.try_send(msg), "RenderChan.send: render port closed")
    }

    pub fn try_send(&self, msg: Msg<T>) -> bool {
        self.chan.try_send(msg)
    }
}

/// If we're using GPU rendering, this provides the metadata needed to create a GL context that
/// is compatible with that of the main thread.
enum GraphicsContext {
    CpuGraphicsContext,
    GpuGraphicsContext,
}

pub struct RenderTask<C,T> {
    id: PipelineId,
    port: Port<Msg<T>>,
    compositor: C,
    constellation_chan: ConstellationChan,
    font_ctx: ~FontContext,
    opts: Opts,

    /// A channel to the profiler.
    profiler_chan: ProfilerChan,

    /// The graphics context to use.
    graphics_context: GraphicsContext,

    /// The native graphics context.
    native_graphics_context: Option<NativePaintingGraphicsContext>,

    /// The layer to be rendered
    render_layer: Option<RenderLayer<T>>,

    /// Permission to send paint messages to the compositor
    paint_permission: bool,

    /// A counter for epoch messages
    epoch: Epoch,

    /// A data structure to store unused LayerBuffers
    buffer_map: BufferMap<~LayerBuffer>,
}

// If we implement this as a function, we get borrowck errors from borrowing
// the whole RenderTask struct.
macro_rules! native_graphics_context(
    ($task:expr) => (
        $task.native_graphics_context.as_ref().expect("Need a graphics context to do rendering")
    )
)

impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
    pub fn create(id: PipelineId,
                  port: Port<Msg<T>>,
                  compositor: C,
                  constellation_chan: ConstellationChan,
                  failure_msg: Failure,
                  opts: Opts,
                  profiler_chan: ProfilerChan,
                  shutdown_chan: Chan<()>) {
        let mut builder = task::task().named("RenderTask");
        let ConstellationChan(c) = constellation_chan.clone();
        send_on_failure(&mut builder, FailureMsg(failure_msg), c);
        builder.spawn(proc() {

            { // Ensures RenderTask and graphics context are destroyed before shutdown msg
                let native_graphics_context = compositor.get_graphics_metadata().map(
                    |md| NativePaintingGraphicsContext::from_metadata(&md));
                let cpu_painting = opts.cpu_painting;

                // FIXME: rust/#5967
                let mut render_task = RenderTask {
                    id: id,
                    port: port,
                    compositor: compositor,
                    constellation_chan: constellation_chan,
                    font_ctx: ~FontContext::new(FontContextInfo {
                        backend: opts.render_backend.clone(),
                        needs_font_list: false,
                        profiler_chan: profiler_chan.clone(),
                    }),
                    opts: opts,
                    profiler_chan: profiler_chan,

                    graphics_context: if cpu_painting {
                        CpuGraphicsContext
                    } else {
                        GpuGraphicsContext
                    },

                    native_graphics_context: native_graphics_context,

                    render_layer: None,

                    paint_permission: false,
                    epoch: Epoch(0),
                    buffer_map: BufferMap::new(10000000),
                };

                render_task.start();

                // Destroy all the buffers.
                {
                    match render_task.native_graphics_context.as_ref() {
                        Some(ctx) => render_task.buffer_map.clear(ctx),
                        None => (),
                    }
                }
            }

            debug!("render_task: shutdown_chan send");
            shutdown_chan.send(());
        });
    }

    fn start(&mut self) {
        debug!("render_task: beginning rendering loop");

        loop {
            match self.port.recv() {
                RenderMsg(render_layer) => {
                    if self.paint_permission {
                        self.epoch.next();
                        self.compositor.set_layer_page_size_and_color(self.id, render_layer.size, self.epoch, render_layer.color);
                    } else {
                        debug!("render_task: render ready msg");
                        let ConstellationChan(ref mut c) = self.constellation_chan;
                        c.send(RendererReadyMsg(self.id));
                    }
                    self.render_layer = Some(render_layer);
                }
                ReRenderMsg(tiles, scale, epoch) => {
                    if self.epoch == epoch {
                        self.render(tiles, scale);
                    } else {
                        debug!("renderer epoch mismatch: {:?} != {:?}", self.epoch, epoch);
                    }
                }
                UnusedBufferMsg(unused_buffers) => {
                    // move_rev_iter is more efficient
                    for buffer in unused_buffers.move_rev_iter() {
                        self.buffer_map.insert(native_graphics_context!(self), buffer);
                    }
                }
                PaintPermissionGranted => {
                    self.paint_permission = true;
                    match self.render_layer {
                        Some(ref render_layer) => {
                            self.epoch.next();
                            self.compositor.set_layer_page_size_and_color(self.id, render_layer.size, self.epoch, render_layer.color);
                        }
                        None => {}
                    }
                }
                PaintPermissionRevoked => {
                    self.paint_permission = false;
                }
                ExitMsg(response_ch) => {
                    debug!("render_task: exitmsg response send");
                    response_ch.map(|ch| ch.send(()));
                    break;
                }
            }
        }
    }

    fn render(&mut self, tiles: ~[BufferRequest], scale: f32) {
        if self.render_layer.is_none() {
            return
        }

        self.compositor.set_render_state(RenderingRenderState);
        time::profile(time::RenderingCategory, self.profiler_chan.clone(), || {
            // FIXME: Try not to create a new array here.
            let mut new_buffers = ~[];

            // Divide up the layer into tiles.
            time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone(), || {
                for tile in tiles.iter() {
                    let width = tile.screen_rect.size.width;
                    let height = tile.screen_rect.size.height;

                    let size = Size2D(width as i32, height as i32);
                    let draw_target = match self.graphics_context {
                        CpuGraphicsContext => {
                            DrawTarget::new(self.opts.render_backend, size, B8G8R8A8)
                        }
                        GpuGraphicsContext => {
                            // FIXME(pcwalton): Cache the components of draw targets
                            // (texture color buffer, renderbuffers) instead of recreating them.
                            let draw_target =
                                DrawTarget::new_with_fbo(self.opts.render_backend,
                                                         native_graphics_context!(self),
                                                         size,
                                                         B8G8R8A8);
                            draw_target.make_current();
                            draw_target
                        }
                    };

                    {
                        // Build the render context.
                        let mut ctx = RenderContext {
                            draw_target: &draw_target,
                            font_ctx: &mut self.font_ctx,
                            opts: &self.opts,
                            page_rect: tile.page_rect,
                            screen_rect: tile.screen_rect,
                        };

                        // Apply the translation to render the tile we want.
                        let matrix: Matrix2D<AzFloat> = Matrix2D::identity();
                        let matrix = matrix.scale(scale as AzFloat, scale as AzFloat);
                        let matrix = matrix.translate(-(tile.page_rect.origin.x) as AzFloat,
                                                      -(tile.page_rect.origin.y) as AzFloat);

                        ctx.draw_target.set_transform(&matrix);

                        // Clear the buffer.
                        ctx.clear();

                        // Draw the display list.
                        profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || {
                            let render_layer = self.render_layer.as_ref().unwrap();
                            render_layer.display_list_collection.get().draw_lists_into_context(&mut ctx);
                            ctx.draw_target.flush();
                        });
                    }

                    // Extract the texture from the draw target and place it into its slot in the
                    // buffer. If using CPU rendering, upload it first.
                    //
                    // FIXME(pcwalton): We should supply the texture and native surface *to* the
                    // draw target in GPU rendering mode, so that it doesn't have to recreate it.
                    let buffer = match self.graphics_context {
                        CpuGraphicsContext => {
                            let buffer = match self.buffer_map.find(tile.screen_rect.size) {
                                Some(buffer) => {
                                    let mut buffer = buffer;
                                    buffer.rect = tile.page_rect;
                                    buffer.screen_pos = tile.screen_rect;
                                    buffer.resolution = scale;
                                    buffer.native_surface.mark_wont_leak();
                                    buffer
                                }
                                None => {
                                    // Create an empty native surface. We mark it as not leaking
                                    // in case it dies in transit to the compositor task.
                                    let mut native_surface: NativeSurface =
                                        layers::platform::surface::NativeSurfaceMethods::new(
                                            native_graphics_context!(self),
                                            Size2D(width as i32, height as i32),
                                            width as i32 * 4);
                                    native_surface.mark_wont_leak();

                                    ~LayerBuffer {
                                        native_surface: native_surface,
                                        rect: tile.page_rect,
                                        screen_pos: tile.screen_rect,
                                        resolution: scale,
                                        stride: (width * 4) as uint
                                    }
                                }
                            };

                            draw_target.snapshot().get_data_surface().with_data(|data| {
                                buffer.native_surface.upload(native_graphics_context!(self), data);
                                debug!("RENDERER uploading to native surface {:d}",
                                       buffer.native_surface.get_id() as int);
                            });

                            buffer
                        }
                        GpuGraphicsContext => {
                            draw_target.make_current();
                            let StolenGLResources {
                                surface: native_surface
                            } = draw_target.steal_gl_resources().unwrap();

                            // We mark the native surface as not leaking in case the surfaces
                            // die on their way to the compositor task.
                            let mut native_surface: NativeSurface =
                                NativeSurfaceAzureMethods::from_azure_surface(native_surface);
                            native_surface.mark_wont_leak();

                            ~LayerBuffer {
                                native_surface: native_surface,
                                rect: tile.page_rect,
                                screen_pos: tile.screen_rect,
                                resolution: scale,
                                stride: (width * 4) as uint
                            }
                        }
                    };

                    new_buffers.push(buffer);
                }
            });

            let layer_buffer_set = ~LayerBufferSet {
                buffers: new_buffers,
            };

            debug!("render_task: returning surface");
            if self.paint_permission {
                self.compositor.paint(self.id, layer_buffer_set, self.epoch);
            } else {
                debug!("render_task: RendererReadyMsg send");
                let ConstellationChan(ref mut c) = self.constellation_chan;
                c.send(RendererReadyMsg(self.id));
            }
            self.compositor.set_render_state(IdleRenderState);
        })
    }
}

<|endoftext|>


<commit_before><commit_msg>Advent day8_all<commit_after><|endoftext|>


<commit_before>#![feature(rustc_attrs, step_trait, rustc_private)]

#[macro_use] extern crate rustc_data_structures;
extern crate rustc_serialize;

use rustc_data_structures::indexed_vec::Idx;

newtype_index!(struct MyIdx { MAX = 0xFFFF_FFFA });

use std::mem::size_of;

fn main() {
    assert_eq!(size_of::<MyIdx>(), 4);
    assert_eq!(size_of::<Option<MyIdx>>(), 4);
    assert_eq!(size_of::<Option<Option<MyIdx>>>(), 4);
    assert_eq!(size_of::<Option<Option<Option<MyIdx>>>>(), 4);
    assert_eq!(size_of::<Option<Option<Option<Option<MyIdx>>>>>(), 4);
    assert_eq!(size_of::<Option<Option<Option<Option<Option<MyIdx>>>>>>(), 4);
    assert_eq!(size_of::<Option<Option<Option<Option<Option<Option<MyIdx>>>>>>>(), 8);
}<commit_msg>Satisfy tidy<commit_after>#![feature(rustc_attrs, step_trait, rustc_private)]

#[macro_use] extern crate rustc_data_structures;
extern crate rustc_serialize;

use rustc_data_structures::indexed_vec::Idx;

newtype_index!(struct MyIdx { MAX = 0xFFFF_FFFA });

use std::mem::size_of;

fn main() {
    assert_eq!(size_of::<MyIdx>(), 4);
    assert_eq!(size_of::<Option<MyIdx>>(), 4);
    assert_eq!(size_of::<Option<Option<MyIdx>>>(), 4);
    assert_eq!(size_of::<Option<Option<Option<MyIdx>>>>(), 4);
    assert_eq!(size_of::<Option<Option<Option<Option<MyIdx>>>>>(), 4);
    assert_eq!(size_of::<Option<Option<Option<Option<Option<MyIdx>>>>>>(), 4);
    assert_eq!(size_of::<Option<Option<Option<Option<Option<Option<MyIdx>>>>>>>(), 8);
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::fs;

use clap::{self, SubCommand};
use cargo::CargoResult;
use cargo::core::Workspace;
use cargo::core::compiler::{BuildConfig, MessageFormat};
use cargo::ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};
use cargo::util::paths;
use cargo::util::important_paths::find_root_manifest_for_wd;

pub use clap::{AppSettings, Arg, ArgMatches};
pub use cargo::{CliError, CliResult, Config};
pub use cargo::core::compiler::CompileMode;

pub type App = clap::App<'static, 'static>;

pub trait AppExt: Sized {
    fn _arg(self, arg: Arg<'static, 'static>) -> Self;

    fn arg_package_spec(
        self,
        package: &'static str,
        all: &'static str,
        exclude: &'static str,
    ) -> Self {
        self.arg_package_spec_simple(package)
            ._arg(opt("all", all))
            ._arg(multi_opt("exclude", "SPEC", exclude))
    }

    fn arg_package_spec_simple(self, package: &'static str) -> Self {
        self._arg(multi_opt("package", "SPEC", package).short("p"))
    }

    fn arg_package(self, package: &'static str) -> Self {
        self._arg(opt("package", package).short("p").value_name("SPEC"))
    }

    fn arg_jobs(self) -> Self {
        self._arg(
            opt("jobs", "Number of parallel jobs, defaults to # of CPUs")
                .short("j")
                .value_name("N"),
        )
    }

    fn arg_targets_all(
        self,
        lib: &'static str,
        bin: &'static str,
        bins: &'static str,
        example: &'static str,
        examples: &'static str,
        test: &'static str,
        tests: &'static str,
        bench: &'static str,
        benches: &'static str,
        all: &'static str,
    ) -> Self {
        self.arg_targets_lib_bin(lib, bin, bins)
            ._arg(multi_opt("example", "NAME", example))
            ._arg(opt("examples", examples))
            ._arg(multi_opt("test", "NAME", test))
            ._arg(opt("tests", tests))
            ._arg(multi_opt("bench", "NAME", bench))
            ._arg(opt("benches", benches))
            ._arg(opt("all-targets", all))
    }

    fn arg_targets_lib_bin(self, lib: &'static str, bin: &'static str, bins: &'static str) -> Self {
        self._arg(opt("lib", lib))
            ._arg(multi_opt("bin", "NAME", bin))
            ._arg(opt("bins", bins))
    }

    fn arg_targets_bins_examples(
        self,
        bin: &'static str,
        bins: &'static str,
        example: &'static str,
        examples: &'static str,
    ) -> Self {
        self._arg(multi_opt("bin", "NAME", bin))
            ._arg(opt("bins", bins))
            ._arg(multi_opt("example", "NAME", example))
            ._arg(opt("examples", examples))
    }

    fn arg_targets_bin_example(self, bin: &'static str, example: &'static str) -> Self {
        self._arg(multi_opt("bin", "NAME", bin))
            ._arg(multi_opt("example", "NAME", example))
    }

    fn arg_features(self) -> Self {
        self._arg(
            opt("features", "Space-separated list of features to activate").value_name("FEATURES"),
        )._arg(opt("all-features", "Activate all available features"))
            ._arg(opt(
                "no-default-features",
                "Do not activate the `default` feature",
            ))
    }

    fn arg_release(self, release: &'static str) -> Self {
        self._arg(opt("release", release))
    }

    fn arg_doc(self, doc: &'static str) -> Self {
        self._arg(opt("doc", doc))
    }

    fn arg_target_triple(self, target: &'static str) -> Self {
        self._arg(opt("target", target).value_name("TRIPLE"))
    }

    fn arg_target_dir(self) -> Self {
        self._arg(opt("target-dir", "Directory for all generated artifacts").value_name("DIRECTORY"))
    }

    fn arg_manifest_path(self) -> Self {
        self._arg(opt("manifest-path", "Path to Cargo.toml").value_name("PATH"))
    }

    fn arg_message_format(self) -> Self {
        self._arg(
            opt("message-format", "Error format")
                .value_name("FMT")
                .case_insensitive(true)
                .possible_values(&["human", "json"])
                .default_value("human"),
        )
    }

    fn arg_build_plan(self) -> Self {
        self._arg(opt("build-plan", "Output the build plan in JSON"))
    }

    fn arg_new_opts(self) -> Self {
        self._arg(
            opt(
                "vcs",
                "\
                 Initialize a new repository for the given version \
                 control system (git, hg, pijul, or fossil) or do not \
                 initialize any version control at all (none), overriding \
                 a global configuration.",
            ).value_name("VCS")
                .possible_values(&["git", "hg", "pijul", "fossil", "none"]),
        )._arg(opt("bin", "Use a binary (application) template [default]"))
            ._arg(opt("lib", "Use a library template"))
            ._arg(
                opt(
                    "name",
                    "Set the resulting package name, defaults to the directory name",
                ).value_name("NAME"),
            )
    }

    fn arg_index(self) -> Self {
        self._arg(opt("index", "Registry index to upload the package to").value_name("INDEX"))
            ._arg(
                opt("host", "DEPRECATED, renamed to '--index'")
                    .value_name("HOST")
                    .hidden(true),
            )
    }
}

impl AppExt for App {
    fn _arg(self, arg: Arg<'static, 'static>) -> Self {
        self.arg(arg)
    }
}

pub fn opt(name: &'static str, help: &'static str) -> Arg<'static, 'static> {
    Arg::with_name(name).long(name).help(help)
}

pub fn multi_opt(
    name: &'static str,
    value_name: &'static str,
    help: &'static str,
) -> Arg<'static, 'static> {
    // Note that all `.multiple(true)` arguments in Cargo should specify
    // `.number_of_values(1)` as well, so that `--foo val1 val2` is
    // **not** parsed as `foo` with values ["val1", "val2"].
    // `number_of_values` should become the default in clap 3.
    opt(name, help)
        .value_name(value_name)
        .multiple(true)
        .number_of_values(1)
}

pub fn subcommand(name: &'static str) -> App {
    SubCommand::with_name(name).settings(&[
        AppSettings::UnifiedHelpMessage,
        AppSettings::DeriveDisplayOrder,
        AppSettings::DontCollapseArgsInUsage,
    ])
}

pub trait ArgMatchesExt {
    fn value_of_u32(&self, name: &str) -> CargoResult<Option<u32>> {
        let arg = match self._value_of(name) {
            None => None,
            Some(arg) => Some(arg.parse::<u32>().map_err(|_| {
                clap::Error::value_validation_auto(format!("could not parse `{}` as a number", arg))
            })?),
        };
        Ok(arg)
    }

    /// Returns value of the `name` command-line argument as an absolute path
    fn value_of_path(&self, name: &str, config: &Config) -> Option<PathBuf> {
        self._value_of(name).map(|path| config.cwd().join(path))
    }

    fn root_manifest(&self, config: &Config) -> CargoResult<PathBuf> {
        if let Some(path) = self.value_of_path("manifest-path", config) {
            // In general, we try to avoid normalizing paths in Cargo,
            // but in this particular case we need it to fix #3586.
            let path = paths::normalize_path(&path);
            if !path.ends_with("Cargo.toml") {
                bail!("the manifest-path must be a path to a Cargo.toml file")
            }
            if !fs::metadata(&path).is_ok() {
                bail!(
                    "manifest path `{}` does not exist",
                    self._value_of("manifest-path").unwrap()
                )
            }
            return Ok(path);
        }
        find_root_manifest_for_wd(config.cwd())
    }

    fn workspace<'a>(&self, config: &'a Config) -> CargoResult<Workspace<'a>> {
        let root = self.root_manifest(config)?;
        let mut ws = Workspace::new(&root, config)?;
        if config.cli_unstable().avoid_dev_deps {
            ws.set_require_optional_deps(false);
        }
        Ok(ws)
    }

    fn jobs(&self) -> CargoResult<Option<u32>> {
        self.value_of_u32("jobs")
    }

    fn target(&self) -> Option<String> {
        self._value_of("target").map(|s| s.to_string())
    }

    fn compile_options<'a>(
        &self,
        config: &'a Config,
        mode: CompileMode,
    ) -> CargoResult<CompileOptions<'a>> {
        let spec = Packages::from_flags(
            self._is_present("all"),
            self._values_of("exclude"),
            self._values_of("package"),
        )?;

        let message_format = match self._value_of("message-format") {
            None => MessageFormat::Human,
            Some(f) => {
                if f.eq_ignore_ascii_case("json") {
                    MessageFormat::Json
                } else if f.eq_ignore_ascii_case("human") {
                    MessageFormat::Human
                } else {
                    panic!("Impossible message format: {:?}", f)
                }
            }
        };

        let mut build_config = BuildConfig::new(config, self.jobs()?, &self.target(), mode)?;
        build_config.message_format = message_format;
        build_config.release = self._is_present("release");
        build_config.build_plan = self._is_present("build-plan");
        if build_config.build_plan && !config.cli_unstable().unstable_options {
            Err(format_err!(
                "`--build-plan` flag is unstable, pass `-Z unstable-options` to enable it"
            ))?;
        };

        let opts = CompileOptions {
            config,
            build_config,
            features: self._values_of("features"),
            all_features: self._is_present("all-features"),
            no_default_features: self._is_present("no-default-features"),
            spec,
            filter: CompileFilter::new(
                self._is_present("lib"),
                self._values_of("bin"),
                self._is_present("bins"),
                self._values_of("test"),
                self._is_present("tests"),
                self._values_of("example"),
                self._is_present("examples"),
                self._values_of("bench"),
                self._is_present("benches"),
                self._is_present("all-targets"),
            ),
            target_rustdoc_args: None,
            target_rustc_args: None,
            export_dir: None,
        };
        Ok(opts)
    }

    fn compile_options_for_single_package<'a>(
        &self,
        config: &'a Config,
        mode: CompileMode,
    ) -> CargoResult<CompileOptions<'a>> {
        let mut compile_opts = self.compile_options(config, mode)?;
        compile_opts.spec = Packages::Packages(self._values_of("package"));
        Ok(compile_opts)
    }

    fn new_options(&self, config: &Config) -> CargoResult<NewOptions> {
        let vcs = self._value_of("vcs").map(|vcs| match vcs {
            "git" => VersionControl::Git,
            "hg" => VersionControl::Hg,
            "pijul" => VersionControl::Pijul,
            "fossil" => VersionControl::Fossil,
            "none" => VersionControl::NoVcs,
            vcs => panic!("Impossible vcs: {:?}", vcs),
        });
        NewOptions::new(
            vcs,
            self._is_present("bin"),
            self._is_present("lib"),
            self.value_of_path("path", config).unwrap(),
            self._value_of("name").map(|s| s.to_string()),
        )
    }

    fn registry(&self, config: &Config) -> CargoResult<Option<String>> {
        match self._value_of("registry") {
            Some(registry) => {
                if !config.cli_unstable().unstable_options {
                    return Err(format_err!(
                        "registry option is an unstable feature and \
                         requires -Zunstable-options to use."
                    ).into());
                }
                Ok(Some(registry.to_string()))
            }
            None => Ok(None),
        }
    }

    fn index(&self, config: &Config) -> CargoResult<Option<String>> {
        // TODO: Deprecated
        // remove once it has been decided --host can be removed
        // We may instead want to repurpose the host flag, as
        // mentioned in this issue
        // https://github.com/rust-lang/cargo/issues/4208
        let msg = "The flag '--host' is no longer valid.

Previous versions of Cargo accepted this flag, but it is being
deprecated. The flag is being renamed to 'index', as the flag
wants the location of the index. Please use '--index' instead.

This will soon become a hard error, so it's either recommended
to update to a fixed version or contact the upstream maintainer
about this warning.";

        let index = match self._value_of("host") {
            Some(host) => {
                config.shell().warn(&msg)?;
                Some(host.to_string())
            }
            None => self._value_of("index").map(|s| s.to_string()),
        };
        Ok(index)
    }

    fn _value_of(&self, name: &str) -> Option<&str>;

    fn _values_of(&self, name: &str) -> Vec<String>;

    fn _is_present(&self, name: &str) -> bool;
}

impl<'a> ArgMatchesExt for ArgMatches<'a> {
    fn _value_of(&self, name: &str) -> Option<&str> {
        self.value_of(name)
    }

    fn _values_of(&self, name: &str) -> Vec<String> {
        self.values_of(name)
            .unwrap_or_default()
            .map(|s| s.to_string())
            .collect()
    }

    fn _is_present(&self, name: &str) -> bool {
        self.is_present(name)
    }
}

pub fn values(args: &ArgMatches, name: &str) -> Vec<String> {
    args.values_of(name)
        .unwrap_or_default()
        .map(|s| s.to_string())
        .collect()
}
<commit_msg>Resolve a nonminimal_bool lint warning<commit_after>use std::path::PathBuf;
use std::fs;

use clap::{self, SubCommand};
use cargo::CargoResult;
use cargo::core::Workspace;
use cargo::core::compiler::{BuildConfig, MessageFormat};
use cargo::ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};
use cargo::util::paths;
use cargo::util::important_paths::find_root_manifest_for_wd;

pub use clap::{AppSettings, Arg, ArgMatches};
pub use cargo::{CliError, CliResult, Config};
pub use cargo::core::compiler::CompileMode;

pub type App = clap::App<'static, 'static>;

pub trait AppExt: Sized {
    fn _arg(self, arg: Arg<'static, 'static>) -> Self;

    fn arg_package_spec(
        self,
        package: &'static str,
        all: &'static str,
        exclude: &'static str,
    ) -> Self {
        self.arg_package_spec_simple(package)
            ._arg(opt("all", all))
            ._arg(multi_opt("exclude", "SPEC", exclude))
    }

    fn arg_package_spec_simple(self, package: &'static str) -> Self {
        self._arg(multi_opt("package", "SPEC", package).short("p"))
    }

    fn arg_package(self, package: &'static str) -> Self {
        self._arg(opt("package", package).short("p").value_name("SPEC"))
    }

    fn arg_jobs(self) -> Self {
        self._arg(
            opt("jobs", "Number of parallel jobs, defaults to # of CPUs")
                .short("j")
                .value_name("N"),
        )
    }

    fn arg_targets_all(
        self,
        lib: &'static str,
        bin: &'static str,
        bins: &'static str,
        example: &'static str,
        examples: &'static str,
        test: &'static str,
        tests: &'static str,
        bench: &'static str,
        benches: &'static str,
        all: &'static str,
    ) -> Self {
        self.arg_targets_lib_bin(lib, bin, bins)
            ._arg(multi_opt("example", "NAME", example))
            ._arg(opt("examples", examples))
            ._arg(multi_opt("test", "NAME", test))
            ._arg(opt("tests", tests))
            ._arg(multi_opt("bench", "NAME", bench))
            ._arg(opt("benches", benches))
            ._arg(opt("all-targets", all))
    }

    fn arg_targets_lib_bin(self, lib: &'static str, bin: &'static str, bins: &'static str) -> Self {
        self._arg(opt("lib", lib))
            ._arg(multi_opt("bin", "NAME", bin))
            ._arg(opt("bins", bins))
    }

    fn arg_targets_bins_examples(
        self,
        bin: &'static str,
        bins: &'static str,
        example: &'static str,
        examples: &'static str,
    ) -> Self {
        self._arg(multi_opt("bin", "NAME", bin))
            ._arg(opt("bins", bins))
            ._arg(multi_opt("example", "NAME", example))
            ._arg(opt("examples", examples))
    }

    fn arg_targets_bin_example(self, bin: &'static str, example: &'static str) -> Self {
        self._arg(multi_opt("bin", "NAME", bin))
            ._arg(multi_opt("example", "NAME", example))
    }

    fn arg_features(self) -> Self {
        self._arg(
            opt("features", "Space-separated list of features to activate").value_name("FEATURES"),
        )._arg(opt("all-features", "Activate all available features"))
            ._arg(opt(
                "no-default-features",
                "Do not activate the `default` feature",
            ))
    }

    fn arg_release(self, release: &'static str) -> Self {
        self._arg(opt("release", release))
    }

    fn arg_doc(self, doc: &'static str) -> Self {
        self._arg(opt("doc", doc))
    }

    fn arg_target_triple(self, target: &'static str) -> Self {
        self._arg(opt("target", target).value_name("TRIPLE"))
    }

    fn arg_target_dir(self) -> Self {
        self._arg(opt("target-dir", "Directory for all generated artifacts").value_name("DIRECTORY"))
    }

    fn arg_manifest_path(self) -> Self {
        self._arg(opt("manifest-path", "Path to Cargo.toml").value_name("PATH"))
    }

    fn arg_message_format(self) -> Self {
        self._arg(
            opt("message-format", "Error format")
                .value_name("FMT")
                .case_insensitive(true)
                .possible_values(&["human", "json"])
                .default_value("human"),
        )
    }

    fn arg_build_plan(self) -> Self {
        self._arg(opt("build-plan", "Output the build plan in JSON"))
    }

    fn arg_new_opts(self) -> Self {
        self._arg(
            opt(
                "vcs",
                "\
                 Initialize a new repository for the given version \
                 control system (git, hg, pijul, or fossil) or do not \
                 initialize any version control at all (none), overriding \
                 a global configuration.",
            ).value_name("VCS")
                .possible_values(&["git", "hg", "pijul", "fossil", "none"]),
        )._arg(opt("bin", "Use a binary (application) template [default]"))
            ._arg(opt("lib", "Use a library template"))
            ._arg(
                opt(
                    "name",
                    "Set the resulting package name, defaults to the directory name",
                ).value_name("NAME"),
            )
    }

    fn arg_index(self) -> Self {
        self._arg(opt("index", "Registry index to upload the package to").value_name("INDEX"))
            ._arg(
                opt("host", "DEPRECATED, renamed to '--index'")
                    .value_name("HOST")
                    .hidden(true),
            )
    }
}

impl AppExt for App {
    fn _arg(self, arg: Arg<'static, 'static>) -> Self {
        self.arg(arg)
    }
}

pub fn opt(name: &'static str, help: &'static str) -> Arg<'static, 'static> {
    Arg::with_name(name).long(name).help(help)
}

pub fn multi_opt(
    name: &'static str,
    value_name: &'static str,
    help: &'static str,
) -> Arg<'static, 'static> {
    // Note that all `.multiple(true)` arguments in Cargo should specify
    // `.number_of_values(1)` as well, so that `--foo val1 val2` is
    // **not** parsed as `foo` with values ["val1", "val2"].
    // `number_of_values` should become the default in clap 3.
    opt(name, help)
        .value_name(value_name)
        .multiple(true)
        .number_of_values(1)
}

pub fn subcommand(name: &'static str) -> App {
    SubCommand::with_name(name).settings(&[
        AppSettings::UnifiedHelpMessage,
        AppSettings::DeriveDisplayOrder,
        AppSettings::DontCollapseArgsInUsage,
    ])
}

pub trait ArgMatchesExt {
    fn value_of_u32(&self, name: &str) -> CargoResult<Option<u32>> {
        let arg = match self._value_of(name) {
            None => None,
            Some(arg) => Some(arg.parse::<u32>().map_err(|_| {
                clap::Error::value_validation_auto(format!("could not parse `{}` as a number", arg))
            })?),
        };
        Ok(arg)
    }

    /// Returns value of the `name` command-line argument as an absolute path
    fn value_of_path(&self, name: &str, config: &Config) -> Option<PathBuf> {
        self._value_of(name).map(|path| config.cwd().join(path))
    }

    fn root_manifest(&self, config: &Config) -> CargoResult<PathBuf> {
        if let Some(path) = self.value_of_path("manifest-path", config) {
            // In general, we try to avoid normalizing paths in Cargo,
            // but in this particular case we need it to fix #3586.
            let path = paths::normalize_path(&path);
            if !path.ends_with("Cargo.toml") {
                bail!("the manifest-path must be a path to a Cargo.toml file")
            }
            if fs::metadata(&path).is_err() {
                bail!(
                    "manifest path `{}` does not exist",
                    self._value_of("manifest-path").unwrap()
                )
            }
            return Ok(path);
        }
        find_root_manifest_for_wd(config.cwd())
    }

    fn workspace<'a>(&self, config: &'a Config) -> CargoResult<Workspace<'a>> {
        let root = self.root_manifest(config)?;
        let mut ws = Workspace::new(&root, config)?;
        if config.cli_unstable().avoid_dev_deps {
            ws.set_require_optional_deps(false);
        }
        Ok(ws)
    }

    fn jobs(&self) -> CargoResult<Option<u32>> {
        self.value_of_u32("jobs")
    }

    fn target(&self) -> Option<String> {
        self._value_of("target").map(|s| s.to_string())
    }

    fn compile_options<'a>(
        &self,
        config: &'a Config,
        mode: CompileMode,
    ) -> CargoResult<CompileOptions<'a>> {
        let spec = Packages::from_flags(
            self._is_present("all"),
            self._values_of("exclude"),
            self._values_of("package"),
        )?;

        let message_format = match self._value_of("message-format") {
            None => MessageFormat::Human,
            Some(f) => {
                if f.eq_ignore_ascii_case("json") {
                    MessageFormat::Json
                } else if f.eq_ignore_ascii_case("human") {
                    MessageFormat::Human
                } else {
                    panic!("Impossible message format: {:?}", f)
                }
            }
        };

        let mut build_config = BuildConfig::new(config, self.jobs()?, &self.target(), mode)?;
        build_config.message_format = message_format;
        build_config.release = self._is_present("release");
        build_config.build_plan = self._is_present("build-plan");
        if build_config.build_plan && !config.cli_unstable().unstable_options {
            Err(format_err!(
                "`--build-plan` flag is unstable, pass `-Z unstable-options` to enable it"
            ))?;
        };

        let opts = CompileOptions {
            config,
            build_config,
            features: self._values_of("features"),
            all_features: self._is_present("all-features"),
            no_default_features: self._is_present("no-default-features"),
            spec,
            filter: CompileFilter::new(
                self._is_present("lib"),
                self._values_of("bin"),
                self._is_present("bins"),
                self._values_of("test"),
                self._is_present("tests"),
                self._values_of("example"),
                self._is_present("examples"),
                self._values_of("bench"),
                self._is_present("benches"),
                self._is_present("all-targets"),
            ),
            target_rustdoc_args: None,
            target_rustc_args: None,
            export_dir: None,
        };
        Ok(opts)
    }

    fn compile_options_for_single_package<'a>(
        &self,
        config: &'a Config,
        mode: CompileMode,
    ) -> CargoResult<CompileOptions<'a>> {
        let mut compile_opts = self.compile_options(config, mode)?;
        compile_opts.spec = Packages::Packages(self._values_of("package"));
        Ok(compile_opts)
    }

    fn new_options(&self, config: &Config) -> CargoResult<NewOptions> {
        let vcs = self._value_of("vcs").map(|vcs| match vcs {
            "git" => VersionControl::Git,
            "hg" => VersionControl::Hg,
            "pijul" => VersionControl::Pijul,
            "fossil" => VersionControl::Fossil,
            "none" => VersionControl::NoVcs,
            vcs => panic!("Impossible vcs: {:?}", vcs),
        });
        NewOptions::new(
            vcs,
            self._is_present("bin"),
            self._is_present("lib"),
            self.value_of_path("path", config).unwrap(),
            self._value_of("name").map(|s| s.to_string()),
        )
    }

    fn registry(&self, config: &Config) -> CargoResult<Option<String>> {
        match self._value_of("registry") {
            Some(registry) => {
                if !config.cli_unstable().unstable_options {
                    return Err(format_err!(
                        "registry option is an unstable feature and \
                         requires -Zunstable-options to use."
                    ).into());
                }
                Ok(Some(registry.to_string()))
            }
            None => Ok(None),
        }
    }

    fn index(&self, config: &Config) -> CargoResult<Option<String>> {
        // TODO: Deprecated
        // remove once it has been decided --host can be removed
        // We may instead want to repurpose the host flag, as
        // mentioned in this issue
        // https://github.com/rust-lang/cargo/issues/4208
        let msg = "The flag '--host' is no longer valid.

Previous versions of Cargo accepted this flag, but it is being
deprecated. The flag is being renamed to 'index', as the flag
wants the location of the index. Please use '--index' instead.

This will soon become a hard error, so it's either recommended
to update to a fixed version or contact the upstream maintainer
about this warning.";

        let index = match self._value_of("host") {
            Some(host) => {
                config.shell().warn(&msg)?;
                Some(host.to_string())
            }
            None => self._value_of("index").map(|s| s.to_string()),
        };
        Ok(index)
    }

    fn _value_of(&self, name: &str) -> Option<&str>;

    fn _values_of(&self, name: &str) -> Vec<String>;

    fn _is_present(&self, name: &str) -> bool;
}

impl<'a> ArgMatchesExt for ArgMatches<'a> {
    fn _value_of(&self, name: &str) -> Option<&str> {
        self.value_of(name)
    }

    fn _values_of(&self, name: &str) -> Vec<String> {
        self.values_of(name)
            .unwrap_or_default()
            .map(|s| s.to_string())
            .collect()
    }

    fn _is_present(&self, name: &str) -> bool {
        self.is_present(name)
    }
}

pub fn values(args: &ArgMatches, name: &str) -> Vec<String> {
    args.values_of(name)
        .unwrap_or_default()
        .map(|s| s.to_string())
        .collect()
}
<|endoftext|>


<commit_before><commit_msg>Add implementations of the Default trait for UniformBlockSpec, UniformSpec, and BlockUniformSpec<commit_after><|endoftext|>


<commit_before><commit_msg>Added a note to the tokenizer to clarify how we close line comments.<commit_after><|endoftext|>


<commit_before>//! A set of utilities to help with common use cases that are not required to
//! fully use the library.

#[macro_use]
pub mod macros;

pub mod builder;

mod colour;

mod message_builder;

pub use self::colour::Colour;

use base64;
use std::ffi::OsStr;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use ::internal::prelude::*;
use ::model::{EmojiIdentifier, EmojiId};

pub use self::message_builder::MessageBuilder;

#[doc(hidden)]
pub fn decode_array<T, F: Fn(Value) -> Result<T>>(value: Value, f: F) -> Result<Vec<T>> {
    into_array(value).and_then(|x| x.into_iter().map(f).collect())
}

#[doc(hidden)]
pub fn into_array(value: Value) -> Result<Vec<Value>> {
    match value {
        Value::Array(v) => Ok(v),
        value => Err(Error::Decode("Expected array", value)),
    }
}

/// Retrieves the "code" part of an [invite][`RichInvite`] out of a URL.
///
/// # Examples
///
/// Three formats of codes are supported:
///
/// 1. Retrieving the code from the URL `"https://discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "https://discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// 2. Retrieving the code from the URL `"http://discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "http://discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// 3. Retrieving the code from the URL `"discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// [`RichInvite`]: ../model/struct.RichInvite.html
pub fn parse_invite(code: &str) -> &str {
    if code.starts_with("https://discord.gg/") {
        &code[19..]
    } else if code.starts_with("http://discord.gg/") {
        &code[18..]
    } else if code.starts_with("discord.gg/") {
        &code[11..]
    } else {
        code
    }
}

/// Retreives Id from a username mention.
pub fn parse_username(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<@!") {
        let len = mention.len() - 1;
        mention[3..len].parse::<u64>().ok()
    } else if mention.starts_with("<@") {
        let len = mention.len() - 1;
        mention[2..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives Id from a role mention.
pub fn parse_role(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<@&") {
        let len = mention.len() - 1;
        mention[3..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives Id from a channel mention.
pub fn parse_channel(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<#") {
        let len = mention.len() - 1;
        mention[2..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives name and Id from an emoji mention.
pub fn parse_emoji(mention: &str) -> Option<EmojiIdentifier> {
    let len = mention.len();
    if len < 6 || len > 56 {
        return None;
    }

    if mention.starts_with("<:") {
        let mut name = String::default();
        let mut id = String::default();
        for (i, x) in mention[2..].chars().enumerate() {
            if x == ':' {
                let from = i + 3;
                for y in mention[from..].chars() {
                    if y == '>' {
                        break;
                    } else {
                        id.push(y);
                    }
                }
                break;
            } else {
                name.push(x);
            }
        }
        match id.parse::<u64>() {
            Ok(x) => Some(EmojiIdentifier {
                name: name,
                id: EmojiId(x)
            }),
            _ => None
        }
    } else {
        None
    }
}

/// Reads an image from a path and encodes it into base64.
///
/// This can be used for methods like [`EditProfile::avatar`].
///
/// # Examples
///
/// Reads an image located at `./cat.png` into a base64-encoded string:
///
/// ```rust,no_run
/// use serenity::utils;
///
/// let image = utils::read_image("./cat.png")
///     .expect("Failed to read image");
/// ```
///
/// [`EditProfile::avatar`]: ../builder/struct.EditProfile.html#method.avatar
pub fn read_image<P: AsRef<Path>>(path: P) -> Result<String> {
    let path = path.as_ref();

    let mut v = Vec::default();
    let mut f = File::open(path)?;
    let _ = f.read_to_end(&mut v);

    let b64 = base64::encode(&v);
    let ext = if path.extension() == Some(OsStr::new("png")) {
        "png"
    } else {
        "jpg"
    };

    Ok(format!("data:image/{};base64,{}", ext, b64))
}

/// Turns a string into a vector of string arguments, splitting by spaces, but
/// parsing content within quotes as one individual argument.
pub fn parse_quotes(s: &str) -> Vec<String> {
    let mut args = vec![];
    let mut in_string = false;
    let mut current_str = String::default();

    for x in s.chars() {
        if in_string {
            if x == '"' {
                if !current_str.is_empty() {
                    args.push(current_str);
                }

                current_str = String::default();
                in_string = false;
            } else {
                current_str.push(x);
            }
        } else if x == ' ' {
            if !current_str.is_empty() {
                args.push(current_str.clone());
            }

            current_str = String::default();
        } else if x == '"' {
            if !current_str.is_empty() {
                args.push(current_str.clone());
            }

            in_string = true;
            current_str = String::default();
        } else {
            current_str.push(x);
        }
    }

    if !current_str.is_empty() {
        args.push(current_str);
    }

    args
}
<commit_msg>allow quotes to be escaped in quote parser<commit_after>//! A set of utilities to help with common use cases that are not required to
//! fully use the library.

#[macro_use]
pub mod macros;

pub mod builder;

mod colour;

mod message_builder;

pub use self::colour::Colour;

use base64;
use std::ffi::OsStr;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use ::internal::prelude::*;
use ::model::{EmojiIdentifier, EmojiId};

pub use self::message_builder::MessageBuilder;

#[doc(hidden)]
pub fn decode_array<T, F: Fn(Value) -> Result<T>>(value: Value, f: F) -> Result<Vec<T>> {
    into_array(value).and_then(|x| x.into_iter().map(f).collect())
}

#[doc(hidden)]
pub fn into_array(value: Value) -> Result<Vec<Value>> {
    match value {
        Value::Array(v) => Ok(v),
        value => Err(Error::Decode("Expected array", value)),
    }
}

/// Retrieves the "code" part of an [invite][`RichInvite`] out of a URL.
///
/// # Examples
///
/// Three formats of codes are supported:
///
/// 1. Retrieving the code from the URL `"https://discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "https://discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// 2. Retrieving the code from the URL `"http://discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "http://discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// 3. Retrieving the code from the URL `"discord.gg/0cDvIgU2voY8RSYL"`:
///
/// ```rust
/// use serenity::utils;
///
/// let url = "discord.gg/0cDvIgU2voY8RSYL";
///
/// assert_eq!(utils::parse_invite(url), "0cDvIgU2voY8RSYL");
/// ```
///
/// [`RichInvite`]: ../model/struct.RichInvite.html
pub fn parse_invite(code: &str) -> &str {
    if code.starts_with("https://discord.gg/") {
        &code[19..]
    } else if code.starts_with("http://discord.gg/") {
        &code[18..]
    } else if code.starts_with("discord.gg/") {
        &code[11..]
    } else {
        code
    }
}

/// Retreives Id from a username mention.
pub fn parse_username(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<@!") {
        let len = mention.len() - 1;
        mention[3..len].parse::<u64>().ok()
    } else if mention.starts_with("<@") {
        let len = mention.len() - 1;
        mention[2..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives Id from a role mention.
pub fn parse_role(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<@&") {
        let len = mention.len() - 1;
        mention[3..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives Id from a channel mention.
pub fn parse_channel(mention: &str) -> Option<u64> {
    if mention.len() < 4 {
        return None;
    }

    if mention.starts_with("<#") {
        let len = mention.len() - 1;
        mention[2..len].parse::<u64>().ok()
    } else {
        None
    }
}

/// Retreives name and Id from an emoji mention.
pub fn parse_emoji(mention: &str) -> Option<EmojiIdentifier> {
    let len = mention.len();
    if len < 6 || len > 56 {
        return None;
    }

    if mention.starts_with("<:") {
        let mut name = String::default();
        let mut id = String::default();
        for (i, x) in mention[2..].chars().enumerate() {
            if x == ':' {
                let from = i + 3;
                for y in mention[from..].chars() {
                    if y == '>' {
                        break;
                    } else {
                        id.push(y);
                    }
                }
                break;
            } else {
                name.push(x);
            }
        }
        match id.parse::<u64>() {
            Ok(x) => Some(EmojiIdentifier {
                name: name,
                id: EmojiId(x)
            }),
            _ => None
        }
    } else {
        None
    }
}

/// Reads an image from a path and encodes it into base64.
///
/// This can be used for methods like [`EditProfile::avatar`].
///
/// # Examples
///
/// Reads an image located at `./cat.png` into a base64-encoded string:
///
/// ```rust,no_run
/// use serenity::utils;
///
/// let image = utils::read_image("./cat.png")
///     .expect("Failed to read image");
/// ```
///
/// [`EditProfile::avatar`]: ../builder/struct.EditProfile.html#method.avatar
pub fn read_image<P: AsRef<Path>>(path: P) -> Result<String> {
    let path = path.as_ref();

    let mut v = Vec::default();
    let mut f = File::open(path)?;
    let _ = f.read_to_end(&mut v);

    let b64 = base64::encode(&v);
    let ext = if path.extension() == Some(OsStr::new("png")) {
        "png"
    } else {
        "jpg"
    };

    Ok(format!("data:image/{};base64,{}", ext, b64))
}

/// Turns a string into a vector of string arguments, splitting by spaces, but
/// parsing content within quotes as one individual argument.
pub fn parse_quotes(s: &str) -> Vec<String> {
    let mut args = vec![];
    let mut in_string = false;
    let mut escaping = false;
    let mut current_str = String::default();

    for x in s.chars() {
        if in_string {
            if x == '\\' && !escaping {
                escaping = true;
            } else if x == '"' && !escaping {
                if !current_str.is_empty() {
                    args.push(current_str);
                }

                current_str = String::default();
                in_string = false;
            } else {
                current_str.push(x);
                escaping = false;
            }
        } else if x == ' ' {
            if !current_str.is_empty() {
                args.push(current_str.clone());
            }

            current_str = String::default();
        } else if x == '"' {
            if !current_str.is_empty() {
                args.push(current_str.clone());
            }

            in_string = true;
            current_str = String::default();
        } else {
            current_str.push(x);
        }
    }

    if !current_str.is_empty() {
        args.push(current_str);
    }

    args
}
<|endoftext|>


<commit_before>// Copyright 2012-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.

/*!
 * A type representing values that may be computed concurrently and
 * operations for working with them.
 *
 * # Example
 *
 * ```rust
 * use std::sync::Future;
 * # fn fib(n: uint) -> uint {42};
 * # fn make_a_sandwich() {};
 * let mut delayed_fib = Future::spawn(proc() { fib(5000) });
 * make_a_sandwich();
 * println!("fib(5000) = {}", delayed_fib.get())
 * ```
 */

#![allow(missing_doc)]

use core::prelude::*;
use core::mem::replace;

use comm::{Receiver, channel};
use task::spawn;

/// A type encapsulating the result of a computation which may not be complete
pub struct Future<A> {
    state: FutureState<A>,
}

enum FutureState<A> {
    Pending(proc():Send -> A),
    Evaluating,
    Forced(A)
}

/// Methods on the `future` type
impl<A:Clone> Future<A> {
    pub fn get(&mut self) -> A {
        //! Get the value of the future.
        (*(self.get_ref())).clone()
    }
}

impl<A> Future<A> {
    /// Gets the value from this future, forcing evaluation.
    pub fn unwrap(mut self) -> A {
        self.get_ref();
        let state = replace(&mut self.state, Evaluating);
        match state {
            Forced(v) => v,
            _ => fail!( "Logic error." ),
        }
    }

    pub fn get_ref<'a>(&'a mut self) -> &'a A {
        /*!
        * Executes the future's closure and then returns a reference
        * to the result.  The reference lasts as long as
        * the future.
        */
        match self.state {
            Forced(ref v) => return v,
            Evaluating => fail!("Recursive forcing of future!"),
            Pending(_) => {
                match replace(&mut self.state, Evaluating) {
                    Forced(_) | Evaluating => fail!("Logic error."),
                    Pending(f) => {
                        self.state = Forced(f());
                        self.get_ref()
                    }
                }
            }
        }
    }

    pub fn from_value(val: A) -> Future<A> {
        /*!
         * Create a future from a value.
         *
         * The value is immediately available and calling `get` later will
         * not block.
         */

        Future {state: Forced(val)}
    }

    pub fn from_fn(f: proc():Send -> A) -> Future<A> {
        /*!
         * Create a future from a function.
         *
         * The first time that the value is requested it will be retrieved by
         * calling the function.  Note that this function is a local
         * function. It is not spawned into another task.
         */

        Future {state: Pending(f)}
    }
}

impl<A:Send> Future<A> {
    pub fn from_receiver(rx: Receiver<A>) -> Future<A> {
        /*!
         * Create a future from a port
         *
         * The first time that the value is requested the task will block
         * waiting for the result to be received on the port.
         */

        Future::from_fn(proc() {
            rx.recv()
        })
    }

    pub fn spawn(blk: proc():Send -> A) -> Future<A> {
        /*!
         * Create a future from a unique closure.
         *
         * The closure will be run in a new task and its result used as the
         * value of the future.
         */

        let (tx, rx) = channel();

        spawn(proc() {
            // Don't fail if the other end has hung up
            let _ = tx.send_opt(blk());
        });

        Future::from_receiver(rx)
    }
}

#[cfg(test)]
mod test {
    use prelude::*;
    use sync::Future;
    use task;
    use comm::{channel, Sender};

    #[test]
    fn test_from_value() {
        let mut f = Future::from_value("snail".to_string());
        assert_eq!(f.get(), "snail".to_string());
    }

    #[test]
    fn test_from_receiver() {
        let (tx, rx) = channel();
        tx.send("whale".to_string());
        let mut f = Future::from_receiver(rx);
        assert_eq!(f.get(), "whale".to_string());
    }

    #[test]
    fn test_from_fn() {
        let mut f = Future::from_fn(proc() "brail".to_string());
        assert_eq!(f.get(), "brail".to_string());
    }

    #[test]
    fn test_interface_get() {
        let mut f = Future::from_value("fail".to_string());
        assert_eq!(f.get(), "fail".to_string());
    }

    #[test]
    fn test_interface_unwrap() {
        let f = Future::from_value("fail".to_string());
        assert_eq!(f.unwrap(), "fail".to_string());
    }

    #[test]
    fn test_get_ref_method() {
        let mut f = Future::from_value(22i);
        assert_eq!(*f.get_ref(), 22);
    }

    #[test]
    fn test_spawn() {
        let mut f = Future::spawn(proc() "bale".to_string());
        assert_eq!(f.get(), "bale".to_string());
    }

    #[test]
    #[should_fail]
    fn test_futurefail() {
        let mut f = Future::spawn(proc() fail!());
        let _x: String = f.get();
    }

    #[test]
    fn test_sendable_future() {
        let expected = "schlorf";
        let f = Future::spawn(proc() { expected });
        task::spawn(proc() {
            let mut f = f;
            let actual = f.get();
            assert_eq!(actual, expected);
        });
    }

    #[test]
    fn test_dropped_future_doesnt_fail() {
        struct Bomb(Sender<bool>);

        local_data_key!(LOCAL: Bomb)

        impl Drop for Bomb {
            fn drop(&mut self) {
                let Bomb(ref tx) = *self;
                tx.send(task::failing());
            }
        }

        // Spawn a future, but drop it immediately. When we receive the result
        // later on, we should never view the task as having failed.
        let (tx, rx) = channel();
        drop(Future::spawn(proc() {
            LOCAL.replace(Some(Bomb(tx)));
        }));

        // Make sure the future didn't fail the task.
        assert!(!rx.recv());
    }
}
<commit_msg>rollup merge of #17686 : lucidd/fix<commit_after>// Copyright 2012-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.

/*!
 * A type representing values that may be computed concurrently and
 * operations for working with them.
 *
 * # Example
 *
 * ```rust
 * use std::sync::Future;
 * # fn fib(n: uint) -> uint {42};
 * # fn make_a_sandwich() {};
 * let mut delayed_fib = Future::spawn(proc() { fib(5000) });
 * make_a_sandwich();
 * println!("fib(5000) = {}", delayed_fib.get())
 * ```
 */

#![allow(missing_doc)]

use core::prelude::*;
use core::mem::replace;

use comm::{Receiver, channel};
use task::spawn;

/// A type encapsulating the result of a computation which may not be complete
pub struct Future<A> {
    state: FutureState<A>,
}

enum FutureState<A> {
    Pending(proc():Send -> A),
    Evaluating,
    Forced(A)
}

/// Methods on the `future` type
impl<A:Clone> Future<A> {
    pub fn get(&mut self) -> A {
        //! Get the value of the future.
        (*(self.get_ref())).clone()
    }
}

impl<A> Future<A> {
    /// Gets the value from this future, forcing evaluation.
    pub fn unwrap(mut self) -> A {
        self.get_ref();
        let state = replace(&mut self.state, Evaluating);
        match state {
            Forced(v) => v,
            _ => fail!( "Logic error." ),
        }
    }

    pub fn get_ref<'a>(&'a mut self) -> &'a A {
        /*!
        * Executes the future's closure and then returns a reference
        * to the result.  The reference lasts as long as
        * the future.
        */
        match self.state {
            Forced(ref v) => return v,
            Evaluating => fail!("Recursive forcing of future!"),
            Pending(_) => {
                match replace(&mut self.state, Evaluating) {
                    Forced(_) | Evaluating => fail!("Logic error."),
                    Pending(f) => {
                        self.state = Forced(f());
                        self.get_ref()
                    }
                }
            }
        }
    }

    pub fn from_value(val: A) -> Future<A> {
        /*!
         * Create a future from a value.
         *
         * The value is immediately available and calling `get` later will
         * not block.
         */

        Future {state: Forced(val)}
    }

    pub fn from_fn(f: proc():Send -> A) -> Future<A> {
        /*!
         * Create a future from a function.
         *
         * The first time that the value is requested it will be retrieved by
         * calling the function.  Note that this function is a local
         * function. It is not spawned into another task.
         */

        Future {state: Pending(f)}
    }
}

impl<A:Send> Future<A> {
    pub fn from_receiver(rx: Receiver<A>) -> Future<A> {
        /*!
         * Create a future from a port
         *
         * The first time that the value is requested the task will block
         * waiting for the result to be received on the port.
         */

        Future::from_fn(proc() {
            rx.recv()
        })
    }

    pub fn spawn(blk: proc():Send -> A) -> Future<A> {
        /*!
         * Create a future from a unique closure.
         *
         * The closure will be run in a new task and its result used as the
         * value of the future.
         */

        let (tx, rx) = channel();

        spawn(proc() {
            // Don't fail if the other end has hung up
            let _ = tx.send_opt(blk());
        });

        Future::from_receiver(rx)
    }
}

#[cfg(test)]
mod test {
    use prelude::*;
    use sync::Future;
    use task;
    use comm::{channel, Sender};

    #[test]
    fn test_from_value() {
        let mut f = Future::from_value("snail".to_string());
        assert_eq!(f.get(), "snail".to_string());
    }

    #[test]
    fn test_from_receiver() {
        let (tx, rx) = channel();
        tx.send("whale".to_string());
        let mut f = Future::from_receiver(rx);
        assert_eq!(f.get(), "whale".to_string());
    }

    #[test]
    fn test_from_fn() {
        let mut f = Future::from_fn(proc() "brail".to_string());
        assert_eq!(f.get(), "brail".to_string());
    }

    #[test]
    fn test_interface_get() {
        let mut f = Future::from_value("fail".to_string());
        assert_eq!(f.get(), "fail".to_string());
    }

    #[test]
    fn test_interface_unwrap() {
        let f = Future::from_value("fail".to_string());
        assert_eq!(f.unwrap(), "fail".to_string());
    }

    #[test]
    fn test_get_ref_method() {
        let mut f = Future::from_value(22i);
        assert_eq!(*f.get_ref(), 22);
    }

    #[test]
    fn test_spawn() {
        let mut f = Future::spawn(proc() "bale".to_string());
        assert_eq!(f.get(), "bale".to_string());
    }

    #[test]
    #[should_fail]
    fn test_futurefail() {
        let mut f = Future::spawn(proc() fail!());
        let _x: String = f.get();
    }

    #[test]
    fn test_sendable_future() {
        let expected = "schlorf";
        let (tx, rx) = channel();
        let f = Future::spawn(proc() { expected });
        task::spawn(proc() {
            let mut f = f;
            tx.send(f.get());
        });
        assert_eq!(rx.recv(), expected);
    }

    #[test]
    fn test_dropped_future_doesnt_fail() {
        struct Bomb(Sender<bool>);

        local_data_key!(LOCAL: Bomb)

        impl Drop for Bomb {
            fn drop(&mut self) {
                let Bomb(ref tx) = *self;
                tx.send(task::failing());
            }
        }

        // Spawn a future, but drop it immediately. When we receive the result
        // later on, we should never view the task as having failed.
        let (tx, rx) = channel();
        drop(Future::spawn(proc() {
            LOCAL.replace(Some(Bomb(tx)));
        }));

        // Make sure the future didn't fail the task.
        assert!(!rx.recv());
    }
}
<|endoftext|>


<commit_before><commit_msg>Duplicate test for type conversion with unsigned int<commit_after>#![cfg(not(feature = "preserve_order"))]

#[derive(serde::Deserialize, Eq, PartialEq, Debug)]
struct Container<T> {
    inner: T,
}

#[derive(serde::Deserialize, Eq, PartialEq, Debug)]
struct Unsigned {
    unsigned: u16,
}

impl Default for Unsigned {
    fn default() -> Self {
        Self { unsigned: 128 }
    }
}

impl From<Unsigned> for config::ValueKind {
    fn from(unsigned: Unsigned) -> Self {
        let mut properties = std::collections::HashMap::new();
        properties.insert(
            "unsigned".to_string(),
            config::Value::from(unsigned.unsigned),
        );

        Self::Table(properties)
    }
}

#[test]
fn test_deser_unsigned_int_hm() {
    let container = Container {
        inner: Unsigned::default(),
    };

    let built = config::Config::builder()
        .set_default("inner", Unsigned::default())
        .unwrap()
        .build()
        .unwrap()
        .try_deserialize::<Container<Unsigned>>()
        .unwrap();

    assert_eq!(container, built);
}
<|endoftext|>


<commit_before><commit_msg>Add external throughput test<commit_after>#![feature(phase)]
#![feature(macro_rules)]
#[phase(syntax, link)]

extern crate log;
extern crate sync;

extern crate time;
extern crate turbine;

use turbine::{Turbine, Slot, WaitStrategy, BusyWait};

use std::io::timer;
use std::fmt;
use std::task::{TaskBuilder};
use std::sync::Future;
use time::precise_time_ns;
use std::io::File;

struct TestSlot {
    pub value: int
}

impl Slot for TestSlot {
    fn new() -> TestSlot {
        TestSlot {
            value: -1	// Negative value here helps catch bugs since counts will be wrong
        }
    }
}

fn bench_chan_100m() -> f32 {

    let (tx_bench, rx_bench): (Sender<int>, Receiver<int>) = channel();

    let mut future = Future::spawn(proc() {
        for _ in range(0i, 100000000)  {
            tx_bench.send(1);
        }

    });

    let start = precise_time_ns();
    let mut counter = 0;
    for i in range(0i, 100000000) {
        counter += rx_bench.recv();
    }
    let end = precise_time_ns();

    future.get();

    error!("Channel: Total time: {}s", (end-start) as f32 / 1000000000f32);
    error!("Channel: ops/s: {}", 100000000f32 / ((end-start) as f32 / 1000000000f32));
    100000000f32 / ((end-start) as f32 / 1000000000f32)
}

fn bench_turbine_100m() -> f32 {
    let mut t: Turbine<TestSlot> = Turbine::new(16384);
    let e1 = t.ep_new().unwrap();

    let event_processor = t.ep_finalize(e1);
    let (tx, rx): (Sender<int>, Receiver<int>) = channel();

    let mut future = Future::spawn(proc() {
        let mut counter = 0;
        event_processor.start::<BusyWait>(|data: &[TestSlot]| -> Result<(),()> {
            for d in data.iter() {
                counter += d.value;
            }

            if counter == 100000000 {
                return Err(());
            } else {
                return Ok(());
            }

        });
        tx.send(1);
    });

    let start = precise_time_ns();
    for i in range(0i, 100000000) {
        let mut s: TestSlot = Slot::new();
        s.value = 1;
        t.write(s);
    }

    rx.recv_opt();
    let end = precise_time_ns();

     // 1000000000 ns == 1s
    error!("Turbine: Total time: {}s", (end-start) as f32 / 1000000000f32);
    error!("Turbine: ops/s: {}", 100000000f32 / ((end-start) as f32 / 1000000000f32));
    100000000f32 / ((end-start) as f32 / 1000000000f32)
}

fn main() {

    let path = Path::new("turbine_throughput.csv");
    let mut file = match File::create(&path) {
            Err(why) => fail!("couldn't create file: {}", why.desc),
            Ok(file) => file
    };

    for i in range(0i,20) {
        let value = bench_turbine_100m();
        match file.write_line(value.to_string().as_slice()) {
            Err(why) => {
                fail!("couldn't write to file: {}", why.desc)
            },
            Ok(_) => {}
        }
    }

    let path = Path::new("chan_throughput.csv");
    let mut file = match File::create(&path) {
            Err(why) => fail!("couldn't create file: {}", why.desc),
            Ok(file) => file
    };
    for i in range(0i,20) {
        let value =  bench_chan_100m();
        match file.write_line(value.to_string().as_slice()) {
            Err(why) => {
                fail!("couldn't write to file: {}", why.desc)
            },
            Ok(_) => {}
        }
    }
}

<|endoftext|>


<commit_before>// A port of the simplistic benchmark from
//
//    http://github.com/PaulKeeble/ScalaVErlangAgents
//
// I *think* it's the same, more or less.

use std;
import io::writer;
import io::writer_util;

enum request {
    get_count,
    bytes(uint),
    stop
}

fn server(requests: comm::port<request>, responses: comm::chan<uint>) {
    let mut count = 0u;
    let mut done = false;
    while !done {
        alt comm::recv(requests) {
          get_count { comm::send(responses, copy count); }
          bytes(b) { count += b; }
          stop { done = true; }
        }
    }
    comm::send(responses, count);
}

fn run(args: [str]) {
    let from_child = comm::port();
    let to_parent = comm::chan(from_child);
    let to_child = task::spawn_listener {|po|
        server(po, to_parent);
    };
    let size = option::get(uint::from_str(args[1]));
    let workers = option::get(uint::from_str(args[2]));
    let start = std::time::precise_time_s();
    let to_child = to_child;
    let mut worker_results = [];
    for uint::range(0u, workers) {|_i|
        let builder = task::builder();
        worker_results += [task::future_result(builder)];
        task::run(builder) {||
            for uint::range(0u, size / workers) {|_i|
                comm::send(to_child, bytes(100u));
            }
        };
    }
    vec::iter(worker_results) {|r| future::get(r); }
    comm::send(to_child, stop);
    let result = comm::recv(from_child);
    let end = std::time::precise_time_s();
    let elapsed = end - start;
    io::stdout().write_str(#fmt("Count is %?\n", result));
    io::stdout().write_str(#fmt("Test took %? seconds\n", elapsed));
    let thruput = ((size / workers * workers) as float) / (elapsed as float);
    io::stdout().write_str(#fmt("Throughput=%f per sec\n", thruput));
}

fn main(args: [str]) {
    let args = if os::getenv("RUST_BENCH").is_some() {
        ["", "1000000", "10000"]
    } else if args.len() <= 1u {
        ["", "10000", "4"]
    } else {
        args
    };

    #debug("%?", args);
    run(args);
}

<commit_msg>Improved perf for msgsend (Issue #2719)<commit_after>// A port of the simplistic benchmark from
//
//    http://github.com/PaulKeeble/ScalaVErlangAgents
//
// I *think* it's the same, more or less.

use std;
import io::writer;
import io::writer_util;

enum request {
    get_count,
    bytes(uint),
    stop
}

fn server(requests: comm::port<request>, responses: comm::chan<uint>) {
    let mut count = 0u;
    let mut done = false;
    while !done {
        alt comm::recv(requests) {
          get_count { comm::send(responses, copy count); }
          bytes(b) { count += b; }
          stop { done = true; }
        }
    }
    comm::send(responses, count);
}

fn run(args: [str]) {
    let from_child = comm::port();
    let to_parent = comm::chan(from_child);
    let to_child = task::spawn_listener {|po|
        server(po, to_parent);
    };
    let size = option::get(uint::from_str(args[1]));
    let workers = option::get(uint::from_str(args[2]));
    let start = std::time::precise_time_s();
    let to_child = to_child;
    let mut worker_results = [];
    for uint::range(0u, workers) {|_i|
        let builder = task::builder();
        vec::push(worker_results, task::future_result(builder));
        task::run(builder) {||
            for uint::range(0u, size / workers) {|_i|
                comm::send(to_child, bytes(100u));
            }
        };
    }
    vec::iter(worker_results) {|r| future::get(r); }
    comm::send(to_child, stop);
    let result = comm::recv(from_child);
    let end = std::time::precise_time_s();
    let elapsed = end - start;
    io::stdout().write_str(#fmt("Count is %?\n", result));
    io::stdout().write_str(#fmt("Test took %? seconds\n", elapsed));
    let thruput = ((size / workers * workers) as float) / (elapsed as float);
    io::stdout().write_str(#fmt("Throughput=%f per sec\n", thruput));
}

fn main(args: [str]) {
    let args = if os::getenv("RUST_BENCH").is_some() {
        ["", "1000000", "10000"]
    } else if args.len() <= 1u {
        ["", "10000", "4"]
    } else {
        args
    };

    #debug("%?", args);
    run(args);
}

<|endoftext|>