<commit_before>use crate::{pagecache::*, *};

/// A pending log reservation which can be aborted or completed.
/// NB the holder should quickly call `complete` or `abort` as
/// taking too long to decide will cause the underlying IO
/// buffer to become blocked.
pub struct Reservation<'a> {
    pub(super) log: &'a Log,
    pub(super) iobuf: Arc<IoBuf>,
    pub(super) buf: &'a mut [u8],
    pub(super) flushed: bool,
    pub(super) pointer: DiskPtr,
    pub(super) lsn: Lsn,
    pub(super) is_blob_rewrite: bool,
}

impl<'a> Drop for Reservation<'a> {
    fn drop(&mut self) {
        // We auto-abort if the user never uses a reservation.
        if !self.flushed {
            let _written = self.flush(false).unwrap();
        }
    }
}

impl<'a> Reservation<'a> {
    /// Cancel the reservation, placing a failed flush on disk, returning
    /// the (cancelled) log sequence number and file offset.
    pub fn abort(mut self) -> Result<(Lsn, DiskPtr)> {
        if self.pointer.is_blob() && !self.is_blob_rewrite {
            // we don't want to remove this blob if something
            // else may still be using it.

            trace!(
                "removing blob for aborted reservation at lsn {}",
                self.pointer
            );

            remove_blob(self.pointer.blob().1, &self.log.config)?;
        }

        self.flush(false)
    }

    /// Complete the reservation, placing the buffer on disk. returns
    /// the log sequence number of the write, and the file offset.
    pub fn complete(mut self) -> Result<(Lsn, DiskPtr)> {
        self.flush(true)
    }

    /// Get the log file offset for reading this buffer in the future.
    pub fn lid(&self) -> LogOffset {
        self.pointer.lid()
    }

    /// Get the log sequence number for this update.
    pub const fn lsn(&self) -> Lsn {
        self.lsn
    }

    /// Get the underlying storage location for the written value.
    /// Note that an blob write still has a pointer in the
    /// log at the provided lid location.
    pub const fn pointer(&self) -> DiskPtr {
        self.pointer
    }

    /// Returns the length of the on-log reservation.
    pub const fn reservation_len(&self) -> usize {
        self.buf.len()
    }

    /// Refills the reservation buffer with new data.
    /// Must supply a buffer of an identical length
    /// as the one initially provided. Don't use this
    /// on messages subject to compression etc...
    ///
    /// # Panics
    ///
    /// Will panic if the reservation is not the correct
    /// size to hold a serialized Lsn.
    #[doc(hidden)]
    pub fn mark_writebatch(&mut self, lsn: Lsn) {
        trace!(
            "writing batch required stable lsn {} into \
             BatchManifest at lid {} lsn {}",
            lsn,
            self.pointer.lid(),
            self.lsn
        );

        self.buf[0] = MessageKind::BatchManifest.into();

        let buf = u64_to_arr(u64::try_from(lsn).unwrap());

        let dst = &mut self.buf[MSG_HEADER_LEN..];

        dst.copy_from_slice(&buf);
    }

    fn flush(&mut self, valid: bool) -> Result<(Lsn, DiskPtr)> {
        if self.flushed {
            panic!("flushing already-flushed reservation!");
        }

        self.flushed = true;

        if !valid {
            // don't actually zero the message, still check its hash
            // on recovery to find corruption.
            self.buf[0] = MessageKind::Cancelled.into();
        }

        // the order of hashing must be the
        // same here as during calls to
        // LogReader::read_message
        let mut hasher = crc32fast::Hasher::new();
        hasher.update(&self.buf[MSG_HEADER_LEN..]);
        hasher.update(&self.buf[..MSG_HEADER_LEN]);
        let crc32 = hasher.finalize();
        let crc32_arr = u32_to_arr(crc32 ^ 0xFFFF_FFFF);

        #[allow(unsafe_code)]
        unsafe {
            std::ptr::copy_nonoverlapping(
                crc32_arr.as_ptr(),
                self.buf
                    .as_mut_ptr()
                    .add(MSG_HEADER_LEN - std::mem::size_of::<u32>()),
                std::mem::size_of::<u32>(),
            );
        }
        self.log.exit_reservation(&self.iobuf)?;

        Ok((self.lsn(), self.pointer()))
    }
}
<commit_msg>revert making reservation_len a const fn, as it bumps the MSRV up too quickly<commit_after>use crate::{pagecache::*, *};

/// A pending log reservation which can be aborted or completed.
/// NB the holder should quickly call `complete` or `abort` as
/// taking too long to decide will cause the underlying IO
/// buffer to become blocked.
pub struct Reservation<'a> {
    pub(super) log: &'a Log,
    pub(super) iobuf: Arc<IoBuf>,
    pub(super) buf: &'a mut [u8],
    pub(super) flushed: bool,
    pub(super) pointer: DiskPtr,
    pub(super) lsn: Lsn,
    pub(super) is_blob_rewrite: bool,
}

impl<'a> Drop for Reservation<'a> {
    fn drop(&mut self) {
        // We auto-abort if the user never uses a reservation.
        if !self.flushed {
            let _written = self.flush(false).unwrap();
        }
    }
}

impl<'a> Reservation<'a> {
    /// Cancel the reservation, placing a failed flush on disk, returning
    /// the (cancelled) log sequence number and file offset.
    pub fn abort(mut self) -> Result<(Lsn, DiskPtr)> {
        if self.pointer.is_blob() && !self.is_blob_rewrite {
            // we don't want to remove this blob if something
            // else may still be using it.

            trace!(
                "removing blob for aborted reservation at lsn {}",
                self.pointer
            );

            remove_blob(self.pointer.blob().1, &self.log.config)?;
        }

        self.flush(false)
    }

    /// Complete the reservation, placing the buffer on disk. returns
    /// the log sequence number of the write, and the file offset.
    pub fn complete(mut self) -> Result<(Lsn, DiskPtr)> {
        self.flush(true)
    }

    /// Get the log file offset for reading this buffer in the future.
    pub fn lid(&self) -> LogOffset {
        self.pointer.lid()
    }

    /// Get the log sequence number for this update.
    pub const fn lsn(&self) -> Lsn {
        self.lsn
    }

    /// Get the underlying storage location for the written value.
    /// Note that an blob write still has a pointer in the
    /// log at the provided lid location.
    pub const fn pointer(&self) -> DiskPtr {
        self.pointer
    }

    /// Returns the length of the on-log reservation.
    pub fn reservation_len(&self) -> usize {
        self.buf.len()
    }

    /// Refills the reservation buffer with new data.
    /// Must supply a buffer of an identical length
    /// as the one initially provided. Don't use this
    /// on messages subject to compression etc...
    ///
    /// # Panics
    ///
    /// Will panic if the reservation is not the correct
    /// size to hold a serialized Lsn.
    #[doc(hidden)]
    pub fn mark_writebatch(&mut self, lsn: Lsn) {
        trace!(
            "writing batch required stable lsn {} into \
             BatchManifest at lid {} lsn {}",
            lsn,
            self.pointer.lid(),
            self.lsn
        );

        self.buf[0] = MessageKind::BatchManifest.into();

        let buf = u64_to_arr(u64::try_from(lsn).unwrap());

        let dst = &mut self.buf[MSG_HEADER_LEN..];

        dst.copy_from_slice(&buf);
    }

    fn flush(&mut self, valid: bool) -> Result<(Lsn, DiskPtr)> {
        if self.flushed {
            panic!("flushing already-flushed reservation!");
        }

        self.flushed = true;

        if !valid {
            // don't actually zero the message, still check its hash
            // on recovery to find corruption.
            self.buf[0] = MessageKind::Cancelled.into();
        }

        // the order of hashing must be the
        // same here as during calls to
        // LogReader::read_message
        let mut hasher = crc32fast::Hasher::new();
        hasher.update(&self.buf[MSG_HEADER_LEN..]);
        hasher.update(&self.buf[..MSG_HEADER_LEN]);
        let crc32 = hasher.finalize();
        let crc32_arr = u32_to_arr(crc32 ^ 0xFFFF_FFFF);

        #[allow(unsafe_code)]
        unsafe {
            std::ptr::copy_nonoverlapping(
                crc32_arr.as_ptr(),
                self.buf
                    .as_mut_ptr()
                    .add(MSG_HEADER_LEN - std::mem::size_of::<u32>()),
                std::mem::size_of::<u32>(),
            );
        }
        self.log.exit_reservation(&self.iobuf)?;

        Ok((self.lsn(), self.pointer()))
    }
}
<|endoftext|>


<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/. */

//! Servo, the mighty web browser engine from the future.
//!
//! This is a very simple library that wires all of Servo's components
//! together as type `Browser`, along with a generic client
//! implementing the `WindowMethods` trait, to create a working web
//! browser.
//!
//! The `Browser` type is responsible for configuring a
//! `Constellation`, which does the heavy lifting of coordinating all
//! of Servo's internal subsystems, including the `ScriptThread` and the
//! `LayoutThread`, as well maintains the navigation context.
//!
//! The `Browser` is fed events from a generic type that implements the
//! `WindowMethods` trait.

#[cfg(not(target_os = "windows"))]
extern crate gaol;
#[macro_use]
extern crate util as _util;

mod export {
    extern crate canvas;
    extern crate canvas_traits;
    extern crate compositing;
    extern crate devtools;
    extern crate devtools_traits;
    extern crate euclid;
    extern crate gfx;
    extern crate gleam;
    extern crate ipc_channel;
    extern crate layers;
    extern crate layout;
    extern crate msg;
    extern crate net;
    extern crate net_traits;
    extern crate profile;
    extern crate profile_traits;
    extern crate script;
    extern crate script_traits;
    extern crate style;
    extern crate url;
}

#[cfg(feature = "webdriver")]
extern crate webdriver_server;

extern crate webrender;
extern crate webrender_traits;

#[cfg(feature = "webdriver")]
fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
    webdriver_server::start_server(port, constellation);
}

#[cfg(not(feature = "webdriver"))]
fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) { }

use compositing::CompositorEventListener;
use compositing::CompositorMsg as ConstellationMsg;
use compositing::compositor_thread::InitialCompositorState;
use compositing::constellation::InitialConstellationState;
use compositing::pipeline::UnprivilegedPipelineContent;
#[cfg(not(target_os = "windows"))]
use compositing::sandboxing;
use compositing::windowing::WindowEvent;
use compositing::windowing::WindowMethods;
use compositing::{CompositorProxy, CompositorThread, Constellation};
#[cfg(not(target_os = "windows"))]
use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc::{self, IpcSender};
use net::image_cache_thread::new_image_cache_thread;
use net::resource_thread::new_resource_thread;
use net::storage_thread::StorageThreadFactory;
use net_traits::storage_thread::StorageThread;
use profile::mem as profile_mem;
use profile::time as profile_time;
use profile_traits::mem;
use profile_traits::time;
use std::borrow::Borrow;
use std::rc::Rc;
use std::sync::mpsc::Sender;
use util::opts;
use util::resource_files::resources_dir_path;

pub use _util as util;
pub use export::canvas;
pub use export::canvas_traits;
pub use export::compositing;
pub use export::devtools;
pub use export::devtools_traits;
pub use export::euclid;
pub use export::gfx;
pub use export::gleam::gl;
pub use export::ipc_channel;
pub use export::layers;
pub use export::layout;
pub use export::msg;
pub use export::net;
pub use export::net_traits;
pub use export::profile;
pub use export::profile_traits;
pub use export::script;
pub use export::script_traits;
pub use export::style;
pub use export::url;

/// The in-process interface to Servo.
///
/// It does everything necessary to render the web, primarily
/// orchestrating the interaction between JavaScript, CSS layout,
/// rendering, and the client window.
///
/// Clients create a `Browser` for a given reference-counted type
/// implementing `WindowMethods`, which is the bridge to whatever
/// application Servo is embedded in. Clients then create an event
/// loop to pump messages between the embedding application and
/// various browser components.
pub struct Browser {
    compositor: Box<CompositorEventListener + 'static>,
}

impl Browser {
    pub fn new<Window>(window: Option<Rc<Window>>) -> Browser
                       where Window: WindowMethods + 'static {
        // Global configuration options, parsed from the command line.
        let opts = opts::get();

        script::init();

        // Get both endpoints of a special channel for communication between
        // the client window and the compositor. This channel is unique because
        // messages to client may need to pump a platform-specific event loop
        // to deliver the message.
        let (compositor_proxy, compositor_receiver) =
            WindowMethods::create_compositor_channel(&window);
        let supports_clipboard = match window {
            Some(ref win_rc) => {
                let win: &Window = win_rc.borrow();
                win.supports_clipboard()
            }
            None => false
        };
        let time_profiler_chan = profile_time::Profiler::create(opts.time_profiler_period);
        let mem_profiler_chan = profile_mem::Profiler::create(opts.mem_profiler_period);
        let devtools_chan = opts.devtools_port.map(|port| {
            devtools::start_server(port)
        });

        let (webrender, webrender_api_sender) = if opts::get().use_webrender {
            let mut resource_path = resources_dir_path();
            resource_path.push("shaders");

            // TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up!
            let hidpi_factor = window.as_ref()
                                     .map(|window| window.hidpi_factor().get())
                                     .unwrap_or(1.0);
            let device_pixel_ratio = match opts.device_pixels_per_px {
                Some(device_pixels_per_px) => device_pixels_per_px,
                None => match opts.output_file {
                    Some(_) => 1.0,
                    None => hidpi_factor,
                }
            };

            let (webrender, webrender_sender) =
                webrender::Renderer::new(webrender::RendererOptions {
                    device_pixel_ratio: device_pixel_ratio,
                    resource_path: resource_path,
                    enable_aa: opts.enable_text_antialiasing,
                    enable_msaa: opts.use_msaa,
                    enable_profiler: opts.webrender_stats,
                });
            (Some(webrender), Some(webrender_sender))
        } else {
            (None, None)
        };

        // Create the constellation, which maintains the engine
        // pipelines, including the script and layout threads, as well
        // as the navigation context.
        let constellation_chan = create_constellation(opts.clone(),
                                                      compositor_proxy.clone_compositor_proxy(),
                                                      time_profiler_chan.clone(),
                                                      mem_profiler_chan.clone(),
                                                      devtools_chan,
                                                      supports_clipboard,
                                                      webrender_api_sender.clone());

        if cfg!(feature = "webdriver") {
            if let Some(port) = opts.webdriver_port {
                webdriver(port, constellation_chan.clone());
            }
        }

        // The compositor coordinates with the client window to create the final
        // rendered page and display it somewhere.
        let compositor = CompositorThread::create(window, InitialCompositorState {
            sender: compositor_proxy,
            receiver: compositor_receiver,
            constellation_chan: constellation_chan,
            time_profiler_chan: time_profiler_chan,
            mem_profiler_chan: mem_profiler_chan,
            webrender: webrender,
            webrender_api_sender: webrender_api_sender,
        });

        Browser {
            compositor: compositor,
        }
    }

    pub fn handle_events(&mut self, events: Vec<WindowEvent>) -> bool {
        self.compositor.handle_events(events)
    }

    pub fn repaint_synchronously(&mut self) {
        self.compositor.repaint_synchronously()
    }

    pub fn pinch_zoom_level(&self) -> f32 {
        self.compositor.pinch_zoom_level()
    }

    pub fn request_title_for_main_frame(&self) {
        self.compositor.title_for_main_frame()
    }
}

fn create_constellation(opts: opts::Opts,
                        compositor_proxy: Box<CompositorProxy + Send>,
                        time_profiler_chan: time::ProfilerChan,
                        mem_profiler_chan: mem::ProfilerChan,
                        devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
                        supports_clipboard: bool,
                        webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Sender<ConstellationMsg> {
    let resource_thread = new_resource_thread(opts.user_agent.clone(), devtools_chan.clone());
    let image_cache_thread = new_image_cache_thread(resource_thread.clone(),
                                                    webrender_api_sender.as_ref().map(|wr| wr.create_api()));
    let font_cache_thread = FontCacheThread::new(resource_thread.clone(),
                                                 webrender_api_sender.as_ref().map(|wr| wr.create_api()));
    let storage_thread: StorageThread = StorageThreadFactory::new();

    let initial_state = InitialConstellationState {
        compositor_proxy: compositor_proxy,
        devtools_chan: devtools_chan,
        image_cache_thread: image_cache_thread,
        font_cache_thread: font_cache_thread,
        resource_thread: resource_thread,
        storage_thread: storage_thread,
        time_profiler_chan: time_profiler_chan,
        mem_profiler_chan: mem_profiler_chan,
        supports_clipboard: supports_clipboard,
        webrender_api_sender: webrender_api_sender,
    };
    let constellation_chan =
        Constellation::<layout::layout_thread::LayoutThread,
                        script::script_thread::ScriptThread>::start(initial_state);

    // Send the URL command to the constellation.
    match opts.url {
        Some(url) => {
            constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
        },
        None => ()
    };

    constellation_chan
}

/// Content process entry point.
pub fn run_content_process(token: String) {
    let (unprivileged_content_sender, unprivileged_content_receiver) =
        ipc::channel::<UnprivilegedPipelineContent>().unwrap();
    let connection_bootstrap: IpcSender<IpcSender<UnprivilegedPipelineContent>> =
        IpcSender::connect(token).unwrap();
    connection_bootstrap.send(unprivileged_content_sender).unwrap();

    let unprivileged_content = unprivileged_content_receiver.recv().unwrap();
    opts::set_defaults(unprivileged_content.opts());

    // Enter the sandbox if necessary.
    if opts::get().sandbox {
       create_sandbox();
    }

    script::init();

    unprivileged_content.start_all::<layout::layout_thread::LayoutThread,
                                     script::script_thread::ScriptThread>(true);
}

// This is a workaround for https://github.com/rust-lang/rust/pull/30175 until
// https://github.com/lfairy/rust-errno/pull/5 lands, and should be removed once
// we update Servo with the rust-errno crate.
#[cfg(target_os = "android")]
#[no_mangle]
pub unsafe extern fn __errno_location() -> *mut i32 {
    extern { fn __errno() -> *mut i32; }
    __errno()
}

#[cfg(not(target_os = "windows"))]
fn create_sandbox() {
    ChildSandbox::new(sandboxing::content_process_sandbox_profile()).activate().unwrap();
}

#[cfg(target_os = "windows")]
fn create_sandbox() {
    panic!("Sandboxing is not supported on Windows.");
}
<commit_msg>Auto merge of #9898 - nox:fix-private-in-public, r=Ms2ger<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/. */

//! Servo, the mighty web browser engine from the future.
//!
//! This is a very simple library that wires all of Servo's components
//! together as type `Browser`, along with a generic client
//! implementing the `WindowMethods` trait, to create a working web
//! browser.
//!
//! The `Browser` type is responsible for configuring a
//! `Constellation`, which does the heavy lifting of coordinating all
//! of Servo's internal subsystems, including the `ScriptThread` and the
//! `LayoutThread`, as well maintains the navigation context.
//!
//! The `Browser` is fed events from a generic type that implements the
//! `WindowMethods` trait.

#[cfg(not(target_os = "windows"))]
extern crate gaol;
#[macro_use]
extern crate gleam;

pub extern crate canvas;
pub extern crate canvas_traits;
pub extern crate compositing;
pub extern crate devtools;
pub extern crate devtools_traits;
pub extern crate euclid;
pub extern crate gfx;
pub extern crate ipc_channel;
pub extern crate layers;
pub extern crate layout;
pub extern crate msg;
pub extern crate net;
pub extern crate net_traits;
pub extern crate profile;
pub extern crate profile_traits;
pub extern crate script;
pub extern crate script_traits;
pub extern crate style;
pub extern crate url;
pub extern crate util;

#[cfg(feature = "webdriver")]
extern crate webdriver_server;

extern crate webrender;
extern crate webrender_traits;

#[cfg(feature = "webdriver")]
fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
    webdriver_server::start_server(port, constellation);
}

#[cfg(not(feature = "webdriver"))]
fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) { }

use compositing::CompositorEventListener;
use compositing::CompositorMsg as ConstellationMsg;
use compositing::compositor_thread::InitialCompositorState;
use compositing::constellation::InitialConstellationState;
use compositing::pipeline::UnprivilegedPipelineContent;
#[cfg(not(target_os = "windows"))]
use compositing::sandboxing;
use compositing::windowing::WindowEvent;
use compositing::windowing::WindowMethods;
use compositing::{CompositorProxy, CompositorThread, Constellation};
#[cfg(not(target_os = "windows"))]
use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc::{self, IpcSender};
use net::image_cache_thread::new_image_cache_thread;
use net::resource_thread::new_resource_thread;
use net::storage_thread::StorageThreadFactory;
use net_traits::storage_thread::StorageThread;
use profile::mem as profile_mem;
use profile::time as profile_time;
use profile_traits::mem;
use profile_traits::time;
use std::borrow::Borrow;
use std::rc::Rc;
use std::sync::mpsc::Sender;
use util::opts;
use util::resource_files::resources_dir_path;

pub use gleam::gl;

/// The in-process interface to Servo.
///
/// It does everything necessary to render the web, primarily
/// orchestrating the interaction between JavaScript, CSS layout,
/// rendering, and the client window.
///
/// Clients create a `Browser` for a given reference-counted type
/// implementing `WindowMethods`, which is the bridge to whatever
/// application Servo is embedded in. Clients then create an event
/// loop to pump messages between the embedding application and
/// various browser components.
pub struct Browser {
    compositor: Box<CompositorEventListener + 'static>,
}

impl Browser {
    pub fn new<Window>(window: Option<Rc<Window>>) -> Browser
                       where Window: WindowMethods + 'static {
        // Global configuration options, parsed from the command line.
        let opts = opts::get();

        script::init();

        // Get both endpoints of a special channel for communication between
        // the client window and the compositor. This channel is unique because
        // messages to client may need to pump a platform-specific event loop
        // to deliver the message.
        let (compositor_proxy, compositor_receiver) =
            WindowMethods::create_compositor_channel(&window);
        let supports_clipboard = match window {
            Some(ref win_rc) => {
                let win: &Window = win_rc.borrow();
                win.supports_clipboard()
            }
            None => false
        };
        let time_profiler_chan = profile_time::Profiler::create(opts.time_profiler_period);
        let mem_profiler_chan = profile_mem::Profiler::create(opts.mem_profiler_period);
        let devtools_chan = opts.devtools_port.map(|port| {
            devtools::start_server(port)
        });

        let (webrender, webrender_api_sender) = if opts::get().use_webrender {
            let mut resource_path = resources_dir_path();
            resource_path.push("shaders");

            // TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up!
            let hidpi_factor = window.as_ref()
                                     .map(|window| window.hidpi_factor().get())
                                     .unwrap_or(1.0);
            let device_pixel_ratio = match opts.device_pixels_per_px {
                Some(device_pixels_per_px) => device_pixels_per_px,
                None => match opts.output_file {
                    Some(_) => 1.0,
                    None => hidpi_factor,
                }
            };

            let (webrender, webrender_sender) =
                webrender::Renderer::new(webrender::RendererOptions {
                    device_pixel_ratio: device_pixel_ratio,
                    resource_path: resource_path,
                    enable_aa: opts.enable_text_antialiasing,
                    enable_msaa: opts.use_msaa,
                    enable_profiler: opts.webrender_stats,
                });
            (Some(webrender), Some(webrender_sender))
        } else {
            (None, None)
        };

        // Create the constellation, which maintains the engine
        // pipelines, including the script and layout threads, as well
        // as the navigation context.
        let constellation_chan = create_constellation(opts.clone(),
                                                      compositor_proxy.clone_compositor_proxy(),
                                                      time_profiler_chan.clone(),
                                                      mem_profiler_chan.clone(),
                                                      devtools_chan,
                                                      supports_clipboard,
                                                      webrender_api_sender.clone());

        if cfg!(feature = "webdriver") {
            if let Some(port) = opts.webdriver_port {
                webdriver(port, constellation_chan.clone());
            }
        }

        // The compositor coordinates with the client window to create the final
        // rendered page and display it somewhere.
        let compositor = CompositorThread::create(window, InitialCompositorState {
            sender: compositor_proxy,
            receiver: compositor_receiver,
            constellation_chan: constellation_chan,
            time_profiler_chan: time_profiler_chan,
            mem_profiler_chan: mem_profiler_chan,
            webrender: webrender,
            webrender_api_sender: webrender_api_sender,
        });

        Browser {
            compositor: compositor,
        }
    }

    pub fn handle_events(&mut self, events: Vec<WindowEvent>) -> bool {
        self.compositor.handle_events(events)
    }

    pub fn repaint_synchronously(&mut self) {
        self.compositor.repaint_synchronously()
    }

    pub fn pinch_zoom_level(&self) -> f32 {
        self.compositor.pinch_zoom_level()
    }

    pub fn request_title_for_main_frame(&self) {
        self.compositor.title_for_main_frame()
    }
}

fn create_constellation(opts: opts::Opts,
                        compositor_proxy: Box<CompositorProxy + Send>,
                        time_profiler_chan: time::ProfilerChan,
                        mem_profiler_chan: mem::ProfilerChan,
                        devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
                        supports_clipboard: bool,
                        webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Sender<ConstellationMsg> {
    let resource_thread = new_resource_thread(opts.user_agent.clone(), devtools_chan.clone());
    let image_cache_thread = new_image_cache_thread(resource_thread.clone(),
                                                    webrender_api_sender.as_ref().map(|wr| wr.create_api()));
    let font_cache_thread = FontCacheThread::new(resource_thread.clone(),
                                                 webrender_api_sender.as_ref().map(|wr| wr.create_api()));
    let storage_thread: StorageThread = StorageThreadFactory::new();

    let initial_state = InitialConstellationState {
        compositor_proxy: compositor_proxy,
        devtools_chan: devtools_chan,
        image_cache_thread: image_cache_thread,
        font_cache_thread: font_cache_thread,
        resource_thread: resource_thread,
        storage_thread: storage_thread,
        time_profiler_chan: time_profiler_chan,
        mem_profiler_chan: mem_profiler_chan,
        supports_clipboard: supports_clipboard,
        webrender_api_sender: webrender_api_sender,
    };
    let constellation_chan =
        Constellation::<layout::layout_thread::LayoutThread,
                        script::script_thread::ScriptThread>::start(initial_state);

    // Send the URL command to the constellation.
    match opts.url {
        Some(url) => {
            constellation_chan.send(ConstellationMsg::InitLoadUrl(url)).unwrap();
        },
        None => ()
    };

    constellation_chan
}

/// Content process entry point.
pub fn run_content_process(token: String) {
    let (unprivileged_content_sender, unprivileged_content_receiver) =
        ipc::channel::<UnprivilegedPipelineContent>().unwrap();
    let connection_bootstrap: IpcSender<IpcSender<UnprivilegedPipelineContent>> =
        IpcSender::connect(token).unwrap();
    connection_bootstrap.send(unprivileged_content_sender).unwrap();

    let unprivileged_content = unprivileged_content_receiver.recv().unwrap();
    opts::set_defaults(unprivileged_content.opts());

    // Enter the sandbox if necessary.
    if opts::get().sandbox {
       create_sandbox();
    }

    script::init();

    unprivileged_content.start_all::<layout::layout_thread::LayoutThread,
                                     script::script_thread::ScriptThread>(true);
}

// This is a workaround for https://github.com/rust-lang/rust/pull/30175 until
// https://github.com/lfairy/rust-errno/pull/5 lands, and should be removed once
// we update Servo with the rust-errno crate.
#[cfg(target_os = "android")]
#[no_mangle]
pub unsafe extern fn __errno_location() -> *mut i32 {
    extern { fn __errno() -> *mut i32; }
    __errno()
}

#[cfg(not(target_os = "windows"))]
fn create_sandbox() {
    ChildSandbox::new(sandboxing::content_process_sandbox_profile()).activate().unwrap();
}

#[cfg(target_os = "windows")]
fn create_sandbox() {
    panic!("Sandboxing is not supported on Windows.");
}
<|endoftext|>


<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/. */

//! Calculate [specified][specified] and [computed values][computed] from a
//! tree of DOM nodes and a set of stylesheets.
//!
//! [computed]: https://drafts.csswg.org/css-cascade/#computed
//! [specified]: https://drafts.csswg.org/css-cascade/#specified
//!
//! In particular, this crate contains the definitions of supported properties,
//! the code to parse them into specified values and calculate the computed
//! values based on the specified values, as well as the code to serialize both
//! specified and computed values.
//!
//! The main entry point is [`recalc_style_at`][recalc_style_at].
//!
//! [recalc_style_at]: traversal/fn.recalc_style_at.html
//!
//! Major dependencies are the [cssparser][cssparser] and [selectors][selectors]
//! crates.
//!
//! [cssparser]: ../cssparser/index.html
//! [selectors]: ../selectors/index.html

#![cfg_attr(feature = "servo", feature(proc_macro))]

#![deny(warnings)]

// FIXME(bholley): We need to blanket-allow unsafe code in order to make the
// gecko atom!() macro work. When Rust 1.14 is released [1], we can uncomment
// the commented-out attributes in regen_atoms.py and go back to denying unsafe
// code by default.
//
// [1] https://github.com/rust-lang/rust/issues/15701#issuecomment-251900615
//#![deny(unsafe_code)]
#![allow(unused_unsafe)]

#![recursion_limit = "500"]  // For define_css_keyword_enum! in -moz-appearance

extern crate app_units;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate bitflags;
#[macro_use] #[no_link]
extern crate cfg_if;
extern crate core;
#[macro_use]
extern crate cssparser;
extern crate encoding;
extern crate euclid;
extern crate fnv;
#[cfg(feature = "gecko")] #[macro_use] pub mod gecko_string_cache;
extern crate heapsize;
#[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
#[cfg(feature = "servo")] #[macro_use] extern crate html5ever_atoms;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate matches;
#[cfg(feature = "gecko")] extern crate nsstring_vendor as nsstring;
extern crate num_integer;
extern crate num_traits;
#[cfg(feature = "gecko")] extern crate num_cpus;
extern crate ordered_float;
extern crate owning_ref;
extern crate parking_lot;
extern crate phf;
extern crate quickersort;
extern crate rayon;
extern crate rustc_serialize;
extern crate selectors;
#[cfg(feature = "servo")]
extern crate serde;
#[cfg(feature = "servo")] #[macro_use] extern crate serde_derive;
#[cfg(feature = "servo")] #[macro_use] extern crate servo_atoms;
extern crate servo_config;
extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style_traits;
extern crate time;
#[allow(unused_extern_crates)]
extern crate unicode_segmentation;

pub mod animation;
pub mod atomic_refcell;
pub mod attr;
pub mod bezier;
pub mod bloom;
pub mod cache;
pub mod cascade_info;
pub mod context;
pub mod custom_properties;
pub mod data;
pub mod dom;
pub mod element_state;
pub mod error_reporting;
pub mod font_face;
pub mod font_metrics;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko_bindings;
pub mod keyframes;
#[allow(missing_docs)] // TODO.
pub mod logical_geometry;
pub mod matching;
#[allow(missing_docs)]
pub mod media_queries;
pub mod owning_handle;
pub mod parallel;
pub mod parser;
pub mod restyle_hints;
pub mod rule_tree;
pub mod scoped_tls;
pub mod selector_parser;
pub mod stylist;
#[cfg(feature = "servo")] #[allow(unsafe_code)] pub mod servo;
pub mod sequential;
pub mod sink;
pub mod str;
pub mod stylesheets;
pub mod thread_state;
pub mod timer;
pub mod traversal;
#[macro_use]
#[allow(non_camel_case_types)]
pub mod values;
pub mod viewport;

use std::fmt;
use std::sync::Arc;
use style_traits::ToCss;

#[cfg(feature = "gecko")] pub use gecko_string_cache as string_cache;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Namespace;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as Prefix;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as LocalName;

#[cfg(feature = "servo")] pub use servo_atoms::Atom;
#[cfg(feature = "servo")] pub use html5ever_atoms::Prefix;
#[cfg(feature = "servo")] pub use html5ever_atoms::LocalName;
#[cfg(feature = "servo")] pub use html5ever_atoms::Namespace;

/// The CSS properties supported by the style system.
// Generated from the properties.mako.rs template by build.rs
#[macro_use]
#[allow(unsafe_code)]
#[deny(missing_docs)]
pub mod properties {
    include!(concat!(env!("OUT_DIR"), "/properties.rs"));
}

#[cfg(feature = "gecko")]
#[allow(unsafe_code)]
pub mod gecko_properties {
    include!(concat!(env!("OUT_DIR"), "/gecko_properties.rs"));
}

macro_rules! reexport_computed_values {
    ( $( $name: ident )+ ) => {
        /// Types for [computed values][computed].
        ///
        /// [computed]: https://drafts.csswg.org/css-cascade/#computed
        pub mod computed_values {
            $(
                pub use properties::longhands::$name::computed_value as $name;
            )+
            // Don't use a side-specific name needlessly:
            pub use properties::longhands::border_top_style::computed_value as border_style;
        }
    }
}
longhand_properties_idents!(reexport_computed_values);

/// Returns whether the two arguments point to the same value.
#[inline]
pub fn arc_ptr_eq<T: 'static>(a: &Arc<T>, b: &Arc<T>) -> bool {
    let a: &T = &**a;
    let b: &T = &**b;
    (a as *const T) == (b as *const T)
}

/// Serializes as CSS a comma-separated list of any `T` that supports being
/// serialized as CSS.
pub fn serialize_comma_separated_list<W, T>(dest: &mut W,
                                            list: &[T])
                                            -> fmt::Result
    where W: fmt::Write,
          T: ToCss,
{
    if list.is_empty() {
        return Ok(());
    }

    try!(list[0].to_css(dest));

    for item in list.iter().skip(1) {
        try!(write!(dest, ", "));
        try!(item.to_css(dest));
    }

    Ok(())
}
<commit_msg>style: Allow the atomic_refcell module to be undocumented, for now.<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/. */

//! Calculate [specified][specified] and [computed values][computed] from a
//! tree of DOM nodes and a set of stylesheets.
//!
//! [computed]: https://drafts.csswg.org/css-cascade/#computed
//! [specified]: https://drafts.csswg.org/css-cascade/#specified
//!
//! In particular, this crate contains the definitions of supported properties,
//! the code to parse them into specified values and calculate the computed
//! values based on the specified values, as well as the code to serialize both
//! specified and computed values.
//!
//! The main entry point is [`recalc_style_at`][recalc_style_at].
//!
//! [recalc_style_at]: traversal/fn.recalc_style_at.html
//!
//! Major dependencies are the [cssparser][cssparser] and [selectors][selectors]
//! crates.
//!
//! [cssparser]: ../cssparser/index.html
//! [selectors]: ../selectors/index.html

#![cfg_attr(feature = "servo", feature(proc_macro))]

#![deny(warnings)]

// FIXME(bholley): We need to blanket-allow unsafe code in order to make the
// gecko atom!() macro work. When Rust 1.14 is released [1], we can uncomment
// the commented-out attributes in regen_atoms.py and go back to denying unsafe
// code by default.
//
// [1] https://github.com/rust-lang/rust/issues/15701#issuecomment-251900615
//#![deny(unsafe_code)]
#![allow(unused_unsafe)]

#![recursion_limit = "500"]  // For define_css_keyword_enum! in -moz-appearance

extern crate app_units;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate bitflags;
#[macro_use] #[no_link]
extern crate cfg_if;
extern crate core;
#[macro_use]
extern crate cssparser;
extern crate encoding;
extern crate euclid;
extern crate fnv;
#[cfg(feature = "gecko")] #[macro_use] pub mod gecko_string_cache;
extern crate heapsize;
#[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
#[cfg(feature = "servo")] #[macro_use] extern crate html5ever_atoms;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate matches;
#[cfg(feature = "gecko")] extern crate nsstring_vendor as nsstring;
extern crate num_integer;
extern crate num_traits;
#[cfg(feature = "gecko")] extern crate num_cpus;
extern crate ordered_float;
extern crate owning_ref;
extern crate parking_lot;
extern crate phf;
extern crate quickersort;
extern crate rayon;
extern crate rustc_serialize;
extern crate selectors;
#[cfg(feature = "servo")]
extern crate serde;
#[cfg(feature = "servo")] #[macro_use] extern crate serde_derive;
#[cfg(feature = "servo")] #[macro_use] extern crate servo_atoms;
extern crate servo_config;
extern crate servo_url;
extern crate smallvec;
#[macro_use]
extern crate style_traits;
extern crate time;
#[allow(unused_extern_crates)]
extern crate unicode_segmentation;

pub mod animation;
#[allow(missing_docs)] // TODO: Under a rewrite.
pub mod atomic_refcell;
pub mod attr;
pub mod bezier;
pub mod bloom;
pub mod cache;
pub mod cascade_info;
pub mod context;
pub mod custom_properties;
pub mod data;
pub mod dom;
pub mod element_state;
pub mod error_reporting;
pub mod font_face;
pub mod font_metrics;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko;
#[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko_bindings;
pub mod keyframes;
#[allow(missing_docs)] // TODO.
pub mod logical_geometry;
pub mod matching;
#[allow(missing_docs)]
pub mod media_queries;
pub mod owning_handle;
pub mod parallel;
pub mod parser;
pub mod restyle_hints;
pub mod rule_tree;
pub mod scoped_tls;
pub mod selector_parser;
pub mod stylist;
#[cfg(feature = "servo")] #[allow(unsafe_code)] pub mod servo;
pub mod sequential;
pub mod sink;
pub mod str;
pub mod stylesheets;
pub mod thread_state;
pub mod timer;
pub mod traversal;
#[macro_use]
#[allow(non_camel_case_types)]
pub mod values;
pub mod viewport;

use std::fmt;
use std::sync::Arc;
use style_traits::ToCss;

#[cfg(feature = "gecko")] pub use gecko_string_cache as string_cache;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Namespace;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as Prefix;
#[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as LocalName;

#[cfg(feature = "servo")] pub use servo_atoms::Atom;
#[cfg(feature = "servo")] pub use html5ever_atoms::Prefix;
#[cfg(feature = "servo")] pub use html5ever_atoms::LocalName;
#[cfg(feature = "servo")] pub use html5ever_atoms::Namespace;

/// The CSS properties supported by the style system.
// Generated from the properties.mako.rs template by build.rs
#[macro_use]
#[allow(unsafe_code)]
#[deny(missing_docs)]
pub mod properties {
    include!(concat!(env!("OUT_DIR"), "/properties.rs"));
}

#[cfg(feature = "gecko")]
#[allow(unsafe_code)]
pub mod gecko_properties {
    include!(concat!(env!("OUT_DIR"), "/gecko_properties.rs"));
}

macro_rules! reexport_computed_values {
    ( $( $name: ident )+ ) => {
        /// Types for [computed values][computed].
        ///
        /// [computed]: https://drafts.csswg.org/css-cascade/#computed
        pub mod computed_values {
            $(
                pub use properties::longhands::$name::computed_value as $name;
            )+
            // Don't use a side-specific name needlessly:
            pub use properties::longhands::border_top_style::computed_value as border_style;
        }
    }
}
longhand_properties_idents!(reexport_computed_values);

/// Returns whether the two arguments point to the same value.
#[inline]
pub fn arc_ptr_eq<T: 'static>(a: &Arc<T>, b: &Arc<T>) -> bool {
    let a: &T = &**a;
    let b: &T = &**b;
    (a as *const T) == (b as *const T)
}

/// Serializes as CSS a comma-separated list of any `T` that supports being
/// serialized as CSS.
pub fn serialize_comma_separated_list<W, T>(dest: &mut W,
                                            list: &[T])
                                            -> fmt::Result
    where W: fmt::Write,
          T: ToCss,
{
    if list.is_empty() {
        return Ok(());
    }

    try!(list[0].to_css(dest));

    for item in list.iter().skip(1) {
        try!(write!(dest, ", "));
        try!(item.to_css(dest));
    }

    Ok(())
}
<|endoftext|>


<commit_before>use crate::math::{Isometry, Point};
use crate::query::Contact;
use crate::shape::{Ball, FeatureId, Shape};
use na::{self, RealField, Unit};

/// Contact between a ball and a convex polyhedron.
///
/// This function panics if the input shape does not implement
/// both the ConvexPolyhedron and PointQuery traits.
#[inline]
pub fn contact_ball_convex_polyhedron<N: RealField>(
    ball_center1: &Point<N>,
    ball1: &Ball<N>,
    m2: &Isometry<N>,
    shape2: &(impl Shape<N> + ?Sized),
    prediction: N,
) -> Option<Contact<N>> {
    // NOTE: this code is mostly taken from the narrow-phase's BallConvexPolyhedronManifoldGenerator
    // after removal of all the code related to contact kinematics because it is not needed here
    // TODE: is there a way to refactor this to avoid duplication?.
    let poly2 = shape2
        .as_convex_polyhedron()
        .expect("The input shape does not implement the ConvexPolyhedron trait.");
    let pt_query2 = shape2
        .as_point_query()
        .expect("The input shape does not implement the PointQuery trait.");

    let (proj, f2) = pt_query2.project_point_with_feature(m2, &ball_center1);
    let world2 = proj.point;
    let dpt = world2 - ball_center1;

    let depth;
    let normal;
    if let Some((dir, dist)) = Unit::try_new_and_get(dpt, N::default_epsilon()) {
        if proj.is_inside {
            depth = dist + ball1.radius();
            normal = -dir;
        } else {
            depth = -dist + ball1.radius();
            normal = dir;
        }
    } else {
        if f2 == FeatureId::Unknown {
            // We cant do anything more at this point.
            return None;
        }

        depth = N::zero();
        normal = -poly2.feature_normal(f2);
    }

    if depth >= -prediction {
        let world1 = ball_center1 + normal.into_inner() * ball1.radius();
        return Some(Contact::new(world1, world2, normal, depth));
    }

    None
}

/// Contact between a convex polyhedron and a ball.
///
/// This function panics if the input shape does not implement
/// both the ConvexPolyhedron and PointQuery traits.
#[inline]
pub fn contact_convex_polyhedron_ball<N: RealField>(
    m1: &Isometry<N>,
    poly1: &(impl Shape<N> + ?Sized),
    ball_center2: &Point<N>,
    ball2: &Ball<N>,
    prediction: N,
) -> Option<Contact<N>> {
    let mut res = contact_ball_convex_polyhedron(ball_center2, ball2, m1, poly1, prediction);
    if let Some(c) = &mut res {
        c.flip()
    }
    res
}
<commit_msg>Fix a couple of warnings.<commit_after>use crate::math::{Isometry, Point};
use crate::query::Contact;
use crate::shape::{Ball, FeatureId, Shape};
use na::{self, RealField, Unit};

/// Contact between a ball and a convex polyhedron.
///
/// This function panics if the input shape does not implement
/// both the ConvexPolyhedron and PointQuery traits.
#[inline]
pub fn contact_ball_convex_polyhedron<N: RealField>(
    ball_center1: &Point<N>,
    ball1: &Ball<N>,
    m2: &Isometry<N>,
    shape2: &(impl Shape<N> + ?Sized),
    prediction: N,
) -> Option<Contact<N>> {
    // NOTE: this code is mostly taken from the narrow-phase's BallConvexPolyhedronManifoldGenerator
    // after removal of all the code related to contact kinematics because it is not needed here
    // TODE: is there a way to refactor this to avoid duplication?.
    let poly2 = shape2
        .as_convex_polyhedron()
        .expect("The input shape does not implement the ConvexPolyhedron trait.");
    let pt_query2 = shape2
        .as_point_query()
        .expect("The input shape does not implement the PointQuery trait.");

    let (proj, f2) = pt_query2.project_point_with_feature(m2, &ball_center1);
    let world2 = proj.point;
    let dpt = world2 - ball_center1;

    let depth;
    let normal;
    if let Some((dir, dist)) = Unit::try_new_and_get(dpt, N::default_epsilon()) {
        if proj.is_inside {
            depth = dist + ball1.radius;
            normal = -dir;
        } else {
            depth = -dist + ball1.radius;
            normal = dir;
        }
    } else {
        if f2 == FeatureId::Unknown {
            // We cant do anything more at this point.
            return None;
        }

        depth = N::zero();
        normal = -poly2.feature_normal(f2);
    }

    if depth >= -prediction {
        let world1 = ball_center1 + normal.into_inner() * ball1.radius;
        return Some(Contact::new(world1, world2, normal, depth));
    }

    None
}

/// Contact between a convex polyhedron and a ball.
///
/// This function panics if the input shape does not implement
/// both the ConvexPolyhedron and PointQuery traits.
#[inline]
pub fn contact_convex_polyhedron_ball<N: RealField>(
    m1: &Isometry<N>,
    poly1: &(impl Shape<N> + ?Sized),
    ball_center2: &Point<N>,
    ball2: &Ball<N>,
    prediction: N,
) -> Option<Contact<N>> {
    let mut res = contact_ball_convex_polyhedron(ball_center2, ball2, m1, poly1, prediction);
    if let Some(c) = &mut res {
        c.flip()
    }
    res
}
<|endoftext|>


<commit_before>#![feature(phase)]

extern crate baps3_protocol;
extern crate libc;
extern crate docopt;
#[phase(plugin)] extern crate docopt_macros;

use baps3_protocol::client::{Client, Request, Response};
use baps3_protocol::proto::{Unpacker, Message};

fn main() {
    let (int_request_tx, int_request_rx) = channel();

    std::thread::Thread::spawn(move || { stdin_loop(int_request_tx)})
                        .detach();

    println!("Disconnected");

    for msg in int_request_rx.iter() {
        match msg {
            Request::Quit => break,
            Request::SendMessage(msg) => match msg.as_str_vec().as_slice() {
                ["connect", dest] => match Client::new(dest) {
                    Ok(client) => {
                        client_main_loop(
                            client,
                            &int_request_rx,
                        );
                        println!("Disconnected");
                    },
                    Err(e) => println!("{}", e)
                },
                _ => println!("can't do that, disconnected!")
            }
        }
    }

    println!("Quitting");
}

fn stdin_loop(
    request_tx: Sender<Request>
) {
    let mut u = Unpacker::new();

    for line in std::io::stdin().lock().lines() {
        match line {
            Ok(l) => send_message(&request_tx, &mut u, l.as_slice()),
            Err(e) => {
                println!("{}", e);
                return;
            }
        }
    }

    request_tx.send(Request::Quit);
}

fn send_message(
    request_tx: &Sender<Request>,
    unpacker: &mut Unpacker,
    message: &str
) {
    for pline in unpacker.feed(message.as_slice()).iter() {
        if let [ref cmd, args..] = pline.as_slice() {
            request_tx.send(Request::SendMessage(Message::new(cmd, args)));
        }
    }
}

fn client_main_loop(Client {
    request_tx,
    response_rx
}: Client, int_request_rx: &Receiver<Request>) {
    let (int_response_tx, int_response_rx) = channel();

    std::thread::Thread::spawn(move || { response_iter(int_response_rx) })
                        .detach();

    let sel = std::comm::Select::new();

    let mut reqh = sel.handle(int_request_rx);
    unsafe { reqh.add(); }

    let mut resh = sel.handle(&response_rx);
    unsafe { resh.add(); }

    loop {
        let id = sel.wait();
        if id == reqh.id() {
            match reqh.recv_opt() {
                Ok(Request::SendMessage(msg)) =>
                  match msg.as_str_vec().as_slice() {
                    ["disconnect"] => {
                        request_tx.send(Request::Quit);
                        return;
                    },
                    [word, args..] => {
                        println!("> {} {}", word, args);
                        request_tx.send(Request::SendMessage(Message::new(word, args)));
                    },
                    [] => ()
                },
                Ok(req) => request_tx.send(req),
                Err(_) => return
            }
        } else {
            match resh.recv_opt() {
                Ok(Response::Gone) => {
                    int_response_tx.send(Response::Gone);
                    return;
                },
                Ok(r) => int_response_tx.send(r),
                Err(_) => {
                    int_response_tx.send(Response::Gone);
                    return;
                }
            }
        }
    }
}

fn response_iter(response_rx: Receiver<Response>) {
    for m in response_rx.iter() {
        match m {
            Response::Message(m) => println!("< {} {}", m.word(), m.args()),
            Response::ClientError(e) => {
                println!("! {}", e);
                return;
            }
            Response::Gone => return
        }
    }
}
<commit_msg>Bang-qualify CLI commands; format time.<commit_after>#![feature(phase)]

extern crate baps3_protocol;
extern crate libc;
extern crate docopt;
#[phase(plugin)] extern crate docopt_macros;

use baps3_protocol::client::{Client, Request, Response};
use baps3_protocol::proto::{Unpacker, Message};

fn main() {
    let (int_request_tx, int_request_rx) = channel();

    std::thread::Thread::spawn(move || { stdin_loop(int_request_tx)})
                        .detach();

    println!("Disconnected");

    for msg in int_request_rx.iter() {
        match msg {
            Request::Quit => break,
            Request::SendMessage(msg) => match msg.as_str_vec().as_slice() {
                ["!connect", dest] => match Client::new(dest) {
                    Ok(client) => {
                        client_main_loop(
                            client,
                            &int_request_rx,
                        );
                        println!("Disconnected");
                    },
                    Err(e) => println!("{}", e)
                },
                _ => println!("can't do that, disconnected!")
            }
        }
    }

    println!("Quitting");
}

fn stdin_loop(
    request_tx: Sender<Request>
) {
    let mut u = Unpacker::new();

    for line in std::io::stdin().lock().lines() {
        match line {
            Ok(l) => send_message(&request_tx, &mut u, l.as_slice()),
            Err(e) => {
                println!("{}", e);
                return;
            }
        }
    }

    request_tx.send(Request::Quit);
}

fn send_message(
    request_tx: &Sender<Request>,
    unpacker: &mut Unpacker,
    message: &str
) {
    for pline in unpacker.feed(message.as_slice()).iter() {
        if let [ref cmd, args..] = pline.as_slice() {
            request_tx.send(Request::SendMessage(Message::new(cmd, args)));
        }
    }
}

fn client_main_loop(Client {
    request_tx,
    response_rx
}: Client, int_request_rx: &Receiver<Request>) {
    let (int_response_tx, int_response_rx) = channel();

    std::thread::Thread::spawn(move || { response_iter(int_response_rx) })
                        .detach();

    let sel = std::comm::Select::new();

    let mut reqh = sel.handle(int_request_rx);
    unsafe { reqh.add(); }

    let mut resh = sel.handle(&response_rx);
    unsafe { resh.add(); }

    loop {
        let id = sel.wait();
        if id == reqh.id() {
            match reqh.recv_opt() {
                Ok(Request::SendMessage(msg)) =>
                  match msg.as_str_vec().as_slice() {
                    ["!disconnect"] => {
                        request_tx.send(Request::Quit);
                        return;
                    },
                    [word, args..] => {
                        println!("> {} {}", word, args);
                        request_tx.send(Request::SendMessage(Message::new(word, args)));
                    },
                    [] => ()
                },
                Ok(req) => request_tx.send(req),
                Err(_) => return
            }
        } else {
            match resh.recv_opt() {
                Ok(Response::Gone) => {
                    int_response_tx.send(Response::Gone);
                    return;
                },
                Ok(r) => int_response_tx.send(r),
                Err(_) => {
                    int_response_tx.send(Response::Gone);
                    return;
                }
            }
        }
    }
}

fn response_iter(response_rx: Receiver<Response>) {
    for m in response_rx.iter() {
        match m {
            Response::Message(m) => match &*m.as_str_vec() {
                [ "TIME", t ] => if let Some(ti) = t.parse::<i64>() {
                    let d = std::time::Duration::microseconds(ti);
                    println!("T {}:{:02}:{:02}",
                         d.num_hours(),
                         d.num_minutes() % 60,
                         d.num_seconds() % 60);
                },
                [ word, args.. ] => println!("< {} {}", word, args),
                [] => ()
            },
            Response::ClientError(e) => {
                println!("! {}", e);
                return;
            }
            Response::Gone => return
        }
    }
}
<|endoftext|>


<commit_before>use cargo::core::features;
use cargo::{self, drop_print, drop_println, CliResult, Config};
use clap::{AppSettings, Arg, ArgMatches};

use super::commands;
use super::list_commands;
use crate::command_prelude::*;

pub fn main(config: &mut Config) -> CliResult {
    // CAUTION: Be careful with using `config` until it is configured below.
    // In general, try to avoid loading config values unless necessary (like
    // the [alias] table).

    if commands::help::handle_embedded_help(config) {
        return Ok(());
    }

    let args = match cli().get_matches_safe() {
        Ok(args) => args,
        Err(e) => {
            if e.kind == clap::ErrorKind::UnrecognizedSubcommand {
                // An unrecognized subcommand might be an external subcommand.
                let cmd = &e.info.as_ref().unwrap()[0].to_owned();
                return super::execute_external_subcommand(config, cmd, &[cmd, "--help"])
                    .map_err(|_| e.into());
            } else {
                return Err(e.into());
            }
        }
    };

    if args.value_of("unstable-features") == Some("help") {
        drop_println!(
            config,
            "
Available unstable (nightly-only) flags:

    -Z avoid-dev-deps      -- Avoid installing dev-dependencies if possible
    -Z minimal-versions    -- Install minimal dependency versions instead of maximum
    -Z no-index-update     -- Do not update the registry, avoids a network request for benchmarking
    -Z unstable-options    -- Allow the usage of unstable options
    -Z timings             -- Display concurrency information
    -Z doctest-xcompile    -- Compile and run doctests for non-host target using runner config
    -Z terminal-width      -- Provide a terminal width to rustc for error truncation
    -Z namespaced-features -- Allow features with `dep:` prefix
    -Z weak-dep-features    -- Allow `dep_name?/feature` feature syntax

Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
        );
        if !features::nightly_features_allowed() {
            drop_println!(
                config,
                "\nUnstable flags are only available on the nightly channel \
                 of Cargo, but this is the `{}` channel.\n\
                 {}",
                features::channel(),
                features::SEE_CHANNELS
            );
        }
        drop_println!(
            config,
            "\nSee https://doc.rust-lang.org/nightly/cargo/reference/unstable.html \
             for more information about these flags."
        );
        return Ok(());
    }

    let is_verbose = args.occurrences_of("verbose") > 0;
    if args.is_present("version") {
        let version = get_version_string(is_verbose);
        drop_print!(config, "{}", version);
        return Ok(());
    }

    if let Some(code) = args.value_of("explain") {
        let mut procss = config.load_global_rustc(None)?.process();
        procss.arg("--explain").arg(code).exec()?;
        return Ok(());
    }

    if args.is_present("list") {
        drop_println!(config, "Installed Commands:");
        for command in list_commands(config) {
            match command {
                CommandInfo::BuiltIn { name, about } => {
                    let summary = about.unwrap_or_default();
                    let summary = summary.lines().next().unwrap_or(&summary); // display only the first line
                    drop_println!(config, "    {:<20} {}", name, summary);
                }
                CommandInfo::External { name, path } => {
                    if is_verbose {
                        drop_println!(config, "    {:<20} {}", name, path.display());
                    } else {
                        drop_println!(config, "    {}", name);
                    }
                }
            }
        }
        return Ok(());
    }

    // Global args need to be extracted before expanding aliases because the
    // clap code for extracting a subcommand discards global options
    // (appearing before the subcommand).
    let (expanded_args, global_args) = expand_aliases(config, args)?;
    let (cmd, subcommand_args) = match expanded_args.subcommand() {
        (cmd, Some(args)) => (cmd, args),
        _ => {
            // No subcommand provided.
            cli().print_help()?;
            return Ok(());
        }
    };
    config_configure(config, &expanded_args, subcommand_args, global_args)?;
    super::init_git_transports(config);

    execute_subcommand(config, cmd, subcommand_args)
}

pub fn get_version_string(is_verbose: bool) -> String {
    let version = cargo::version();
    let mut version_string = version.to_string();
    version_string.push('\n');
    if is_verbose {
        version_string.push_str(&format!(
            "release: {}.{}.{}\n",
            version.major, version.minor, version.patch
        ));
        if let Some(ref cfg) = version.cfg_info {
            if let Some(ref ci) = cfg.commit_info {
                version_string.push_str(&format!("commit-hash: {}\n", ci.commit_hash));
                version_string.push_str(&format!("commit-date: {}\n", ci.commit_date));
            }
        }
    }
    version_string
}

fn expand_aliases(
    config: &mut Config,
    args: ArgMatches<'static>,
) -> Result<(ArgMatches<'static>, GlobalArgs), CliError> {
    if let (cmd, Some(args)) = args.subcommand() {
        match (
            commands::builtin_exec(cmd),
            super::aliased_command(config, cmd)?,
        ) {
            (Some(_), Some(_)) => {
                // User alias conflicts with a built-in subcommand
                config.shell().warn(format!(
                    "user-defined alias `{}` is ignored, because it is shadowed by a built-in command",
                    cmd,
                ))?;
            }
            (_, Some(mut alias)) => {
                alias.extend(
                    args.values_of("")
                        .unwrap_or_default()
                        .map(|s| s.to_string()),
                );
                // new_args strips out everything before the subcommand, so
                // capture those global options now.
                // Note that an alias to an external command will not receive
                // these arguments. That may be confusing, but such is life.
                let global_args = GlobalArgs::new(args);
                let new_args = cli()
                    .setting(AppSettings::NoBinaryName)
                    .get_matches_from_safe(alias)?;
                let (expanded_args, _) = expand_aliases(config, new_args)?;
                return Ok((expanded_args, global_args));
            }
            (_, None) => {}
        }
    };

    Ok((args, GlobalArgs::default()))
}

fn config_configure(
    config: &mut Config,
    args: &ArgMatches<'_>,
    subcommand_args: &ArgMatches<'_>,
    global_args: GlobalArgs,
) -> CliResult {
    let arg_target_dir = &subcommand_args.value_of_path("target-dir", config);
    let verbose = global_args.verbose + args.occurrences_of("verbose") as u32;
    // quiet is unusual because it is redefined in some subcommands in order
    // to provide custom help text.
    let quiet =
        args.is_present("quiet") || subcommand_args.is_present("quiet") || global_args.quiet;
    let global_color = global_args.color; // Extract so it can take reference.
    let color = args.value_of("color").or_else(|| global_color.as_deref());
    let frozen = args.is_present("frozen") || global_args.frozen;
    let locked = args.is_present("locked") || global_args.locked;
    let offline = args.is_present("offline") || global_args.offline;
    let mut unstable_flags = global_args.unstable_flags;
    if let Some(values) = args.values_of("unstable-features") {
        unstable_flags.extend(values.map(|s| s.to_string()));
    }
    let mut config_args = global_args.config_args;
    if let Some(values) = args.values_of("config") {
        config_args.extend(values.map(|s| s.to_string()));
    }
    config.configure(
        verbose,
        quiet,
        color,
        frozen,
        locked,
        offline,
        arg_target_dir,
        &unstable_flags,
        &config_args,
    )?;
    Ok(())
}

fn execute_subcommand(
    config: &mut Config,
    cmd: &str,
    subcommand_args: &ArgMatches<'_>,
) -> CliResult {
    if let Some(exec) = commands::builtin_exec(cmd) {
        return exec(config, subcommand_args);
    }

    let mut ext_args: Vec<&str> = vec![cmd];
    ext_args.extend(subcommand_args.values_of("").unwrap_or_default());
    super::execute_external_subcommand(config, cmd, &ext_args)
}

#[derive(Default)]
struct GlobalArgs {
    verbose: u32,
    quiet: bool,
    color: Option<String>,
    frozen: bool,
    locked: bool,
    offline: bool,
    unstable_flags: Vec<String>,
    config_args: Vec<String>,
}

impl GlobalArgs {
    fn new(args: &ArgMatches<'_>) -> GlobalArgs {
        GlobalArgs {
            verbose: args.occurrences_of("verbose") as u32,
            quiet: args.is_present("quiet"),
            color: args.value_of("color").map(|s| s.to_string()),
            frozen: args.is_present("frozen"),
            locked: args.is_present("locked"),
            offline: args.is_present("offline"),
            unstable_flags: args
                .values_of_lossy("unstable-features")
                .unwrap_or_default(),
            config_args: args
                .values_of("config")
                .unwrap_or_default()
                .map(|s| s.to_string())
                .collect(),
        }
    }
}

fn cli() -> App {
    let is_rustup = std::env::var_os("RUSTUP_HOME").is_some();
    let usage = if is_rustup {
        "cargo [+toolchain] [OPTIONS] [SUBCOMMAND]"
    } else {
        "cargo [OPTIONS] [SUBCOMMAND]"
    };
    App::new("cargo")
        .settings(&[
            AppSettings::UnifiedHelpMessage,
            AppSettings::DeriveDisplayOrder,
            AppSettings::VersionlessSubcommands,
            AppSettings::AllowExternalSubcommands,
        ])
        .usage(usage)
        .template(
            "\
Rust's package manager

USAGE:
    {usage}

OPTIONS:
{unified}

Some common cargo commands are (see all commands with --list):
    build, b    Compile the current package
    check, c    Analyze the current package and report errors, but don't build object files
    clean       Remove the target directory
    doc         Build this package's and its dependencies' documentation
    new         Create a new cargo package
    init        Create a new cargo package in an existing directory
    run, r      Run a binary or example of the local package
    test, t     Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates
    publish     Package and upload this package to the registry
    install     Install a Rust binary. Default location is $HOME/.cargo/bin
    uninstall   Uninstall a Rust binary

See 'cargo help <command>' for more information on a specific command.\n",
        )
        .arg(opt("version", "Print version info and exit").short("V"))
        .arg(opt("list", "List installed commands"))
        .arg(opt("explain", "Run `rustc --explain CODE`").value_name("CODE"))
        .arg(
            opt(
                "verbose",
                "Use verbose output (-vv very verbose/build.rs output)",
            )
            .short("v")
            .multiple(true)
            .global(true),
        )
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(
            opt("color", "Coloring: auto, always, never")
                .value_name("WHEN")
                .global(true),
        )
        .arg(opt("frozen", "Require Cargo.lock and cache are up to date").global(true))
        .arg(opt("locked", "Require Cargo.lock is up to date").global(true))
        .arg(opt("offline", "Run without accessing the network").global(true))
        .arg(
            multi_opt("config", "KEY=VALUE", "Override a configuration value")
                .global(true)
                .hidden(true),
        )
        .arg(
            Arg::with_name("unstable-features")
                .help("Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details")
                .short("Z")
                .value_name("FLAG")
                .multiple(true)
                .number_of_values(1)
                .global(true),
        )
        .subcommands(commands::builtin())
}
<commit_msg>Auto merge of #8924 - gdoenlen:patch-1, r=ehuss<commit_after>use cargo::core::features;
use cargo::{self, drop_print, drop_println, CliResult, Config};
use clap::{AppSettings, Arg, ArgMatches};

use super::commands;
use super::list_commands;
use crate::command_prelude::*;

pub fn main(config: &mut Config) -> CliResult {
    // CAUTION: Be careful with using `config` until it is configured below.
    // In general, try to avoid loading config values unless necessary (like
    // the [alias] table).

    if commands::help::handle_embedded_help(config) {
        return Ok(());
    }

    let args = match cli().get_matches_safe() {
        Ok(args) => args,
        Err(e) => {
            if e.kind == clap::ErrorKind::UnrecognizedSubcommand {
                // An unrecognized subcommand might be an external subcommand.
                let cmd = &e.info.as_ref().unwrap()[0].to_owned();
                return super::execute_external_subcommand(config, cmd, &[cmd, "--help"])
                    .map_err(|_| e.into());
            } else {
                return Err(e.into());
            }
        }
    };

    if args.value_of("unstable-features") == Some("help") {
        drop_println!(
            config,
            "
Available unstable (nightly-only) flags:

    -Z avoid-dev-deps      -- Avoid installing dev-dependencies if possible
    -Z minimal-versions    -- Install minimal dependency versions instead of maximum
    -Z no-index-update     -- Do not update the registry, avoids a network request for benchmarking
    -Z unstable-options    -- Allow the usage of unstable options
    -Z timings             -- Display concurrency information
    -Z doctest-xcompile    -- Compile and run doctests for non-host target using runner config
    -Z terminal-width      -- Provide a terminal width to rustc for error truncation
    -Z namespaced-features -- Allow features with `dep:` prefix
    -Z weak-dep-features   -- Allow `dep_name?/feature` feature syntax

Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
        );
        if !features::nightly_features_allowed() {
            drop_println!(
                config,
                "\nUnstable flags are only available on the nightly channel \
                 of Cargo, but this is the `{}` channel.\n\
                 {}",
                features::channel(),
                features::SEE_CHANNELS
            );
        }
        drop_println!(
            config,
            "\nSee https://doc.rust-lang.org/nightly/cargo/reference/unstable.html \
             for more information about these flags."
        );
        return Ok(());
    }

    let is_verbose = args.occurrences_of("verbose") > 0;
    if args.is_present("version") {
        let version = get_version_string(is_verbose);
        drop_print!(config, "{}", version);
        return Ok(());
    }

    if let Some(code) = args.value_of("explain") {
        let mut procss = config.load_global_rustc(None)?.process();
        procss.arg("--explain").arg(code).exec()?;
        return Ok(());
    }

    if args.is_present("list") {
        drop_println!(config, "Installed Commands:");
        for command in list_commands(config) {
            match command {
                CommandInfo::BuiltIn { name, about } => {
                    let summary = about.unwrap_or_default();
                    let summary = summary.lines().next().unwrap_or(&summary); // display only the first line
                    drop_println!(config, "    {:<20} {}", name, summary);
                }
                CommandInfo::External { name, path } => {
                    if is_verbose {
                        drop_println!(config, "    {:<20} {}", name, path.display());
                    } else {
                        drop_println!(config, "    {}", name);
                    }
                }
            }
        }
        return Ok(());
    }

    // Global args need to be extracted before expanding aliases because the
    // clap code for extracting a subcommand discards global options
    // (appearing before the subcommand).
    let (expanded_args, global_args) = expand_aliases(config, args)?;
    let (cmd, subcommand_args) = match expanded_args.subcommand() {
        (cmd, Some(args)) => (cmd, args),
        _ => {
            // No subcommand provided.
            cli().print_help()?;
            return Ok(());
        }
    };
    config_configure(config, &expanded_args, subcommand_args, global_args)?;
    super::init_git_transports(config);

    execute_subcommand(config, cmd, subcommand_args)
}

pub fn get_version_string(is_verbose: bool) -> String {
    let version = cargo::version();
    let mut version_string = version.to_string();
    version_string.push('\n');
    if is_verbose {
        version_string.push_str(&format!(
            "release: {}.{}.{}\n",
            version.major, version.minor, version.patch
        ));
        if let Some(ref cfg) = version.cfg_info {
            if let Some(ref ci) = cfg.commit_info {
                version_string.push_str(&format!("commit-hash: {}\n", ci.commit_hash));
                version_string.push_str(&format!("commit-date: {}\n", ci.commit_date));
            }
        }
    }
    version_string
}

fn expand_aliases(
    config: &mut Config,
    args: ArgMatches<'static>,
) -> Result<(ArgMatches<'static>, GlobalArgs), CliError> {
    if let (cmd, Some(args)) = args.subcommand() {
        match (
            commands::builtin_exec(cmd),
            super::aliased_command(config, cmd)?,
        ) {
            (Some(_), Some(_)) => {
                // User alias conflicts with a built-in subcommand
                config.shell().warn(format!(
                    "user-defined alias `{}` is ignored, because it is shadowed by a built-in command",
                    cmd,
                ))?;
            }
            (_, Some(mut alias)) => {
                alias.extend(
                    args.values_of("")
                        .unwrap_or_default()
                        .map(|s| s.to_string()),
                );
                // new_args strips out everything before the subcommand, so
                // capture those global options now.
                // Note that an alias to an external command will not receive
                // these arguments. That may be confusing, but such is life.
                let global_args = GlobalArgs::new(args);
                let new_args = cli()
                    .setting(AppSettings::NoBinaryName)
                    .get_matches_from_safe(alias)?;
                let (expanded_args, _) = expand_aliases(config, new_args)?;
                return Ok((expanded_args, global_args));
            }
            (_, None) => {}
        }
    };

    Ok((args, GlobalArgs::default()))
}

fn config_configure(
    config: &mut Config,
    args: &ArgMatches<'_>,
    subcommand_args: &ArgMatches<'_>,
    global_args: GlobalArgs,
) -> CliResult {
    let arg_target_dir = &subcommand_args.value_of_path("target-dir", config);
    let verbose = global_args.verbose + args.occurrences_of("verbose") as u32;
    // quiet is unusual because it is redefined in some subcommands in order
    // to provide custom help text.
    let quiet =
        args.is_present("quiet") || subcommand_args.is_present("quiet") || global_args.quiet;
    let global_color = global_args.color; // Extract so it can take reference.
    let color = args.value_of("color").or_else(|| global_color.as_deref());
    let frozen = args.is_present("frozen") || global_args.frozen;
    let locked = args.is_present("locked") || global_args.locked;
    let offline = args.is_present("offline") || global_args.offline;
    let mut unstable_flags = global_args.unstable_flags;
    if let Some(values) = args.values_of("unstable-features") {
        unstable_flags.extend(values.map(|s| s.to_string()));
    }
    let mut config_args = global_args.config_args;
    if let Some(values) = args.values_of("config") {
        config_args.extend(values.map(|s| s.to_string()));
    }
    config.configure(
        verbose,
        quiet,
        color,
        frozen,
        locked,
        offline,
        arg_target_dir,
        &unstable_flags,
        &config_args,
    )?;
    Ok(())
}

fn execute_subcommand(
    config: &mut Config,
    cmd: &str,
    subcommand_args: &ArgMatches<'_>,
) -> CliResult {
    if let Some(exec) = commands::builtin_exec(cmd) {
        return exec(config, subcommand_args);
    }

    let mut ext_args: Vec<&str> = vec![cmd];
    ext_args.extend(subcommand_args.values_of("").unwrap_or_default());
    super::execute_external_subcommand(config, cmd, &ext_args)
}

#[derive(Default)]
struct GlobalArgs {
    verbose: u32,
    quiet: bool,
    color: Option<String>,
    frozen: bool,
    locked: bool,
    offline: bool,
    unstable_flags: Vec<String>,
    config_args: Vec<String>,
}

impl GlobalArgs {
    fn new(args: &ArgMatches<'_>) -> GlobalArgs {
        GlobalArgs {
            verbose: args.occurrences_of("verbose") as u32,
            quiet: args.is_present("quiet"),
            color: args.value_of("color").map(|s| s.to_string()),
            frozen: args.is_present("frozen"),
            locked: args.is_present("locked"),
            offline: args.is_present("offline"),
            unstable_flags: args
                .values_of_lossy("unstable-features")
                .unwrap_or_default(),
            config_args: args
                .values_of("config")
                .unwrap_or_default()
                .map(|s| s.to_string())
                .collect(),
        }
    }
}

fn cli() -> App {
    let is_rustup = std::env::var_os("RUSTUP_HOME").is_some();
    let usage = if is_rustup {
        "cargo [+toolchain] [OPTIONS] [SUBCOMMAND]"
    } else {
        "cargo [OPTIONS] [SUBCOMMAND]"
    };
    App::new("cargo")
        .settings(&[
            AppSettings::UnifiedHelpMessage,
            AppSettings::DeriveDisplayOrder,
            AppSettings::VersionlessSubcommands,
            AppSettings::AllowExternalSubcommands,
        ])
        .usage(usage)
        .template(
            "\
Rust's package manager

USAGE:
    {usage}

OPTIONS:
{unified}

Some common cargo commands are (see all commands with --list):
    build, b    Compile the current package
    check, c    Analyze the current package and report errors, but don't build object files
    clean       Remove the target directory
    doc         Build this package's and its dependencies' documentation
    new         Create a new cargo package
    init        Create a new cargo package in an existing directory
    run, r      Run a binary or example of the local package
    test, t     Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates
    publish     Package and upload this package to the registry
    install     Install a Rust binary. Default location is $HOME/.cargo/bin
    uninstall   Uninstall a Rust binary

See 'cargo help <command>' for more information on a specific command.\n",
        )
        .arg(opt("version", "Print version info and exit").short("V"))
        .arg(opt("list", "List installed commands"))
        .arg(opt("explain", "Run `rustc --explain CODE`").value_name("CODE"))
        .arg(
            opt(
                "verbose",
                "Use verbose output (-vv very verbose/build.rs output)",
            )
            .short("v")
            .multiple(true)
            .global(true),
        )
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(
            opt("color", "Coloring: auto, always, never")
                .value_name("WHEN")
                .global(true),
        )
        .arg(opt("frozen", "Require Cargo.lock and cache are up to date").global(true))
        .arg(opt("locked", "Require Cargo.lock is up to date").global(true))
        .arg(opt("offline", "Run without accessing the network").global(true))
        .arg(
            multi_opt("config", "KEY=VALUE", "Override a configuration value")
                .global(true)
                .hidden(true),
        )
        .arg(
            Arg::with_name("unstable-features")
                .help("Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details")
                .short("Z")
                .value_name("FLAG")
                .multiple(true)
                .number_of_values(1)
                .global(true),
        )
        .subcommands(commands::builtin())
}
<|endoftext|>


<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/. */

use std::env;
use std::fs::File;
use std::path::Path;

extern crate csv_checker;

fn report_errors_for_file(file: File) -> i32 {
    let mut exit = 0;

    let rx = csv_checker::publish_errors_for_csv(file);

    for error in rx {
        exit = 1;
        println!("error at line {}, col {}: {}",
                 error.line,
                 error.col,
                 error.text);
    }

    exit
}

fn errors_for_args() -> i32 {
    let mut exit_code: i32 = 0;

    // Skip the first arg since it's the program itself
    let paths = env::args().skip(1);

    if paths.len() == 0 {
        panic!("Provide some paths!");
    }

    for arg in paths {
        println!("= {} =", arg);

        let path = Path::new(&arg);

        exit_code += match File::open(&path) {
            Err(_) => {
                println!("!!! Not found");
                1
            }
            Ok(file) => report_errors_for_file(file),
        };
    }

    exit_code
}

fn main() {
    let exit_code = errors_for_args();
    std::process::exit(exit_code);
}
<commit_msg>Use a buffered reader (much, much, much faster)<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/. */

use std::env;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;

extern crate csv_checker;

fn report_errors_for_file(file: File) -> i32 {
    let mut exit = 0;

    let reader = BufReader::new(file);

    let rx = csv_checker::publish_errors_for_csv(reader);

    for error in rx {
        exit = 1;
        println!("error at line {}, col {}: {}",
                 error.line,
                 error.col,
                 error.text);
    }

    exit
}

fn errors_for_args() -> i32 {
    let mut exit_code: i32 = 0;

    // Skip the first arg since it's the program itself
    let paths = env::args().skip(1);

    if paths.len() == 0 {
        panic!("Provide some paths!");
    }

    for arg in paths {
        println!("= {} =", arg);

        let path = Path::new(&arg);

        exit_code += match File::open(&path) {
            Err(_) => {
                println!("!!! Not found");
                1
            }
            Ok(file) => report_errors_for_file(file),
        };
    }

    exit_code
}

fn main() {
    let exit_code = errors_for_args();
    std::process::exit(exit_code);
}
<|endoftext|>


<commit_before>extern crate mpi;
extern crate num;

use mpi::traits::*;
use mpi::topology::{Universe, SystemCommunicator};
use num::pow;
use mpi::collective::SystemOperation;
use std::process;

const MAX_MSG_SIZE: usize = (1<<22);
const MAX_ALIGNMENT: usize = 16384;
const BUF_SIZE: usize = MAX_MSG_SIZE + MAX_ALIGNMENT;
const LARGE_MSG_SIZE: isize = 8192 - 1;
const LOOP_SMALL: isize = 10000;
const LOOP_LARGE: isize = 1000;
const SKIP_SMALL: isize = 100;
const SKIP_LARGE: isize = 10;

fn main() {
  let universe = mpi::initialize().unwrap();
  let world = universe.world();
  let size = world.size();
  let rank = world.rank();
  let pairs = size/2;

  if size < 2 {
    println!("ERROR: This test requires at least 2 processes");
    process::exit(1);
  }

  if rank == 0 {
    println!("# RUST OSU MPI Multi Latency Test v1.0");
    println!("# Size               Latency (us)");
  }

  world.barrier();
  multi_latency(rank, pairs, universe, world);
  world.barrier();
}

fn multi_latency(rank: i32, pairs: i32,
                 universe: Universe, world: SystemCommunicator) {
  let s_buf = vec![0;BUF_SIZE];
  let root_process = world.process_at_rank(0);

  for size in (0..1).chain((0..23).map(|x| pow(2, x))) {
    let mut t_start = 0.0f64;

    world.barrier();

    let (range, extra) = match size {
      x @ _ if x > LARGE_MSG_SIZE => (LOOP_LARGE, SKIP_LARGE),
      _ => (LOOP_SMALL, SKIP_SMALL)
    };

    match rank {
      _ if rank < pairs => {
        let peer_rank = rank + pairs;

        for iter in (0 .. range + extra) {
          if iter == extra {
            t_start = universe.get_time();
            world.barrier();
          }

          world.process_at_rank(peer_rank).send(&s_buf[0.. size as usize]);
          // XXX: This will probabaly hurt performance in comarison to C.
          let (_, _) = world.receive_vec::<u32>();
        }
      },
      _ => {
        let peer_rank = rank - pairs;

        for iter in (0 .. range + extra) {
          if iter == extra {
            t_start = universe.get_time();
            world.barrier();
          }

          // XXX: This will probabaly hurt performance in comarison to C.
          let (_, _) = world.receive_vec::<u32>();
          world.process_at_rank(peer_rank).send(&s_buf[0.. size as usize]);
        }
      }
    }

    let t_end = universe.get_time();
    let latency = ((t_end - t_start) * 1.0e6) / (2.0 * range as f64);

    let mut latency_sum = 0.0f64;
    root_process.reduce_into(&latency, Some(&mut latency_sum), SystemOperation::sum());

    if world.rank() == 0 {
      let avg_latency: f64 = latency_sum / (pairs * 2) as f64;
      println!("{:<28} {1:.2}", size, avg_latency);
    }
  }
}
<commit_msg>Borrow world and universe and world in function.<commit_after>extern crate mpi;
extern crate num;

use mpi::traits::*;
use mpi::topology::{Universe, SystemCommunicator};
use num::pow;
use mpi::collective::SystemOperation;
use std::process;

const MAX_MSG_SIZE: usize = (1<<22);
const MAX_ALIGNMENT: usize = 16384;
const BUF_SIZE: usize = MAX_MSG_SIZE + MAX_ALIGNMENT;
const LARGE_MSG_SIZE: isize = 8192 - 1;
const LOOP_SMALL: isize = 10000;
const LOOP_LARGE: isize = 1000;
const SKIP_SMALL: isize = 100;
const SKIP_LARGE: isize = 10;

fn main() {
  let universe = mpi::initialize().unwrap();
  let world = universe.world();
  let size = world.size();
  let rank = world.rank();
  let pairs = size/2;

  if size < 2 {
    println!("ERROR: This test requires at least 2 processes");
    process::exit(1);
  }

  if rank == 0 {
    println!("# RUST OSU MPI Multi Latency Test v1.0");
    println!("# Size               Latency (us)");
  }

  world.barrier();
  multi_latency(rank, pairs, &universe, &world);
  world.barrier();
}

fn multi_latency(rank: i32, pairs: i32,
                 universe: &Universe, world: &SystemCommunicator) {
  let s_buf = vec![0;BUF_SIZE];
  let root_process = world.process_at_rank(0);

  for size in (0..1).chain((0..23).map(|x| pow(2, x))) {
    let mut t_start = 0.0f64;

    world.barrier();

    let (range, extra) = match size {
      x @ _ if x > LARGE_MSG_SIZE => (LOOP_LARGE, SKIP_LARGE),
      _ => (LOOP_SMALL, SKIP_SMALL)
    };

    match rank {
      _ if rank < pairs => {
        let peer_rank = rank + pairs;

        for iter in (0 .. range + extra) {
          if iter == extra {
            t_start = universe.get_time();
            world.barrier();
          }

          world.process_at_rank(peer_rank).send(&s_buf[0.. size as usize]);
          // XXX: This will probabaly hurt performance in comarison to C.
          let (_, _) = world.receive_vec::<u32>();
        }
      },
      _ => {
        let peer_rank = rank - pairs;

        for iter in (0 .. range + extra) {
          if iter == extra {
            t_start = universe.get_time();
            world.barrier();
          }

          // XXX: This will probabaly hurt performance in comarison to C.
          let (_, _) = world.receive_vec::<u32>();
          world.process_at_rank(peer_rank).send(&s_buf[0.. size as usize]);
        }
      }
    }

    let t_end = universe.get_time();
    let latency = ((t_end - t_start) * 1.0e6) / (2.0 * range as f64);

    let mut latency_sum = 0.0f64;
    root_process.reduce_into(&latency, Some(&mut latency_sum), SystemOperation::sum());

    if world.rank() == 0 {
      let avg_latency: f64 = latency_sum / (pairs * 2) as f64;
      println!("{:<28} {1:.2}", size, avg_latency);
    }
  }
}
<|endoftext|>