<commit_before>#![feature(cell_update)]

use super::*;
use std::cell::Cell;

#[test]
fn allocator_param() {
    use crate::alloc::AllocErr;

    // Writing a test of integration between third-party
    // allocators and `RawVec` is a little tricky because the `RawVec`
    // API does not expose fallible allocation methods, so we
    // cannot check what happens when allocator is exhausted
    // (beyond detecting a panic).
    //
    // Instead, this just checks that the `RawVec` methods do at
    // least go through the Allocator API when it reserves
    // storage.

    // A dumb allocator that consumes a fixed amount of fuel
    // before allocation attempts start failing.
    struct BoundedAlloc {
        fuel: Cell<usize>,
    }
    unsafe impl AllocRef for BoundedAlloc {
        fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
            let size = layout.size();
            if size > self.fuel.get() {
                return Err(AllocErr);
            }
            match Global.alloc(layout) {
                ok @ Ok(_) => {
                    self.fuel.update(|old| old - size);
                    ok
                }
                err @ Err(_) => err,
            }
        }
        unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
            unsafe { Global.dealloc(ptr, layout) }
        }
    }

    let a = BoundedAlloc { fuel: Cell::new(500) };
    let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a);
    assert_eq!(v.alloc.fuel.get(), 450);
    v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel)
    assert_eq!(v.alloc.fuel.get(), 250);
}

#[test]
fn reserve_does_not_overallocate() {
    {
        let mut v: RawVec<u32> = RawVec::new();
        // First, `reserve` allocates like `reserve_exact`.
        v.reserve(0, 9);
        assert_eq!(9, v.capacity());
    }

    {
        let mut v: RawVec<u32> = RawVec::new();
        v.reserve(0, 7);
        assert_eq!(7, v.capacity());
        // 97 is more than double of 7, so `reserve` should work
        // like `reserve_exact`.
        v.reserve(7, 90);
        assert_eq!(97, v.capacity());
    }

    {
        let mut v: RawVec<u32> = RawVec::new();
        v.reserve(0, 12);
        assert_eq!(12, v.capacity());
        v.reserve(12, 3);
        // 3 is less than half of 12, so `reserve` must grow
        // exponentially. At the time of writing this test grow
        // factor is 2, so new capacity is 24, however, grow factor
        // of 1.5 is OK too. Hence `>= 18` in assert.
        assert!(v.capacity() >= 12 + 12 / 2);
    }
}
<commit_msg>replaced cell::update with cell::[g|s]et<commit_after>use super::*;
use std::cell::Cell;

#[test]
fn allocator_param() {
    use crate::alloc::AllocErr;

    // Writing a test of integration between third-party
    // allocators and `RawVec` is a little tricky because the `RawVec`
    // API does not expose fallible allocation methods, so we
    // cannot check what happens when allocator is exhausted
    // (beyond detecting a panic).
    //
    // Instead, this just checks that the `RawVec` methods do at
    // least go through the Allocator API when it reserves
    // storage.

    // A dumb allocator that consumes a fixed amount of fuel
    // before allocation attempts start failing.
    struct BoundedAlloc {
        fuel: Cell<usize>,
    }
    unsafe impl AllocRef for BoundedAlloc {
        fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErr> {
            let size = layout.size();
            if size > self.fuel.get() {
                return Err(AllocErr);
            }
            match Global.alloc(layout) {
                ok @ Ok(_) => {
                    self.fuel.set(self.fuel.get() - size);
                    ok
                }
                err @ Err(_) => err,
            }
        }
        unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
            unsafe { Global.dealloc(ptr, layout) }
        }
    }

    let a = BoundedAlloc { fuel: Cell::new(500) };
    let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a);
    assert_eq!(v.alloc.fuel.get(), 450);
    v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel)
    assert_eq!(v.alloc.fuel.get(), 250);
}

#[test]
fn reserve_does_not_overallocate() {
    {
        let mut v: RawVec<u32> = RawVec::new();
        // First, `reserve` allocates like `reserve_exact`.
        v.reserve(0, 9);
        assert_eq!(9, v.capacity());
    }

    {
        let mut v: RawVec<u32> = RawVec::new();
        v.reserve(0, 7);
        assert_eq!(7, v.capacity());
        // 97 is more than double of 7, so `reserve` should work
        // like `reserve_exact`.
        v.reserve(7, 90);
        assert_eq!(97, v.capacity());
    }

    {
        let mut v: RawVec<u32> = RawVec::new();
        v.reserve(0, 12);
        assert_eq!(12, v.capacity());
        v.reserve(12, 3);
        // 3 is less than half of 12, so `reserve` must grow
        // exponentially. At the time of writing this test grow
        // factor is 2, so new capacity is 24, however, grow factor
        // of 1.5 is OK too. Hence `>= 18` in assert.
        assert!(v.capacity() >= 12 + 12 / 2);
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2019 Guillaume Desmottes <guillaume.desmottes@collabora.com>
//
// 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.

#![crate_type = "cdylib"]

#[macro_use]
extern crate glib;
#[macro_use]
extern crate gstreamer as gst;

mod cdgdec;
mod cdgparse;
mod constants;

use constants::{CDG_COMMAND, CDG_MASK, CDG_PACKET_SIZE};

const TYPEFIND_SEARCH_WINDOW: i64 = 100000; /* in bytes */

/* Return the percentage of CDG packets in the first @len bytes of @typefind */
fn cdg_packets_ratio(typefind: &mut gst::TypeFind, len: i64) -> i64 {
    let mut count = 0;
    let total = len / CDG_PACKET_SIZE as i64;

    for offset in (0..len).step_by(CDG_PACKET_SIZE as usize) {
        match typefind.peek(offset, CDG_PACKET_SIZE as u32) {
            Some(data) => {
                if data[0] & CDG_MASK == CDG_COMMAND {
                    count += 1;
                }
            }
            None => break,
        }
    }
    (count * 100) / total
}

fn typefind_register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    use gst::{Caps, TypeFind, TypeFindProbability};

    TypeFind::register(
        Some(plugin),
        "cdg_typefind",
        gst::Rank::None,
        Some("cdg"),
        Some(&Caps::new_simple("video/x-cdg", &[])),
        |mut typefind| {
            let proba = match cdg_packets_ratio(&mut typefind, TYPEFIND_SEARCH_WINDOW) {
                0...5 => TypeFindProbability::None,
                6...10 => TypeFindProbability::Possible,
                _ => TypeFindProbability::Likely,
            };

            if proba != gst::TypeFindProbability::None {
                typefind.suggest(proba, &Caps::new_simple("video/x-cdg", &[]));
            }
        },
    )
}

fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    cdgdec::register(plugin)?;
    cdgparse::register(plugin)?;
    typefind_register(plugin)?;
    Ok(())
}

gst_plugin_define!(
    cdg,
    env!("CARGO_PKG_DESCRIPTION"),
    plugin_init,
    concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")),
    "MIT/X11",
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_REPOSITORY"),
    env!("BUILD_REL_DATE")
);
<commit_msg>cdg: `...` ranges (inclusive) are deprecated in favour of `...=`<commit_after>// Copyright (C) 2019 Guillaume Desmottes <guillaume.desmottes@collabora.com>
//
// 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.

#![crate_type = "cdylib"]

#[macro_use]
extern crate glib;
#[macro_use]
extern crate gstreamer as gst;

mod cdgdec;
mod cdgparse;
mod constants;

use constants::{CDG_COMMAND, CDG_MASK, CDG_PACKET_SIZE};

const TYPEFIND_SEARCH_WINDOW: i64 = 100000; /* in bytes */

/* Return the percentage of CDG packets in the first @len bytes of @typefind */
fn cdg_packets_ratio(typefind: &mut gst::TypeFind, len: i64) -> i64 {
    let mut count = 0;
    let total = len / CDG_PACKET_SIZE as i64;

    for offset in (0..len).step_by(CDG_PACKET_SIZE as usize) {
        match typefind.peek(offset, CDG_PACKET_SIZE as u32) {
            Some(data) => {
                if data[0] & CDG_MASK == CDG_COMMAND {
                    count += 1;
                }
            }
            None => break,
        }
    }
    (count * 100) / total
}

fn typefind_register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    use gst::{Caps, TypeFind, TypeFindProbability};

    TypeFind::register(
        Some(plugin),
        "cdg_typefind",
        gst::Rank::None,
        Some("cdg"),
        Some(&Caps::new_simple("video/x-cdg", &[])),
        |mut typefind| {
            let proba = match cdg_packets_ratio(&mut typefind, TYPEFIND_SEARCH_WINDOW) {
                0..=5 => TypeFindProbability::None,
                6..=10 => TypeFindProbability::Possible,
                _ => TypeFindProbability::Likely,
            };

            if proba != gst::TypeFindProbability::None {
                typefind.suggest(proba, &Caps::new_simple("video/x-cdg", &[]));
            }
        },
    )
}

fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
    cdgdec::register(plugin)?;
    cdgparse::register(plugin)?;
    typefind_register(plugin)?;
    Ok(())
}

gst_plugin_define!(
    cdg,
    env!("CARGO_PKG_DESCRIPTION"),
    plugin_init,
    concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")),
    "MIT/X11",
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_NAME"),
    env!("CARGO_PKG_REPOSITORY"),
    env!("BUILD_REL_DATE")
);
<|endoftext|>


<commit_before>// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::ptr;
use std::mem;

use libc;

use glib_ffi;
use gobject_ffi;
use gst_ffi;

use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;

use object::*;
use anyimpl::*;

pub trait ElementImpl<T: ElementBase>
    : ObjectImpl<T> + AnyImpl + Send + Sync + 'static {
    fn change_state(&self, element: &T, transition: gst::StateChange) -> gst::StateChangeReturn {
        element.parent_change_state(transition)
    }

    fn request_new_pad(
        &self,
        _element: &T,
        _templ: &gst::PadTemplate,
        _name: Option<String>,
        _caps: Option<&gst::CapsRef>,
    ) -> Option<gst::Pad> {
        None
    }

    fn release_pad(&self, _element: &T, _pad: &gst::Pad) {}

    fn send_event(&self, element: &T, event: gst::Event) -> bool {
        element.parent_send_event(event)
    }

    fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
        element.parent_query(query)
    }

    fn set_context(&self, element: &T, context: &gst::Context) {
        element.parent_set_context(context)
    }
}

any_impl!(ElementBase, ElementImpl);

pub unsafe trait ElementBase: IsA<gst::Element> + ObjectType {
    fn parent_change_state(&self, transition: gst::StateChange) -> gst::StateChangeReturn {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
            (*parent_klass)
                .change_state
                .map(|f| {
                    from_glib(f(self.to_glib_none().0, transition.to_glib()))
                })
                .unwrap_or(gst::StateChangeReturn::Success)
        }
    }

    fn parent_send_event(&self, event: gst::Event) -> bool {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
            (*parent_klass)
                .send_event
                .map(|f| from_glib(f(self.to_glib_none().0, event.into_ptr())))
                .unwrap_or(false)
        }
    }

    fn parent_query(&self, query: &mut gst::QueryRef) -> bool {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
            (*parent_klass)
                .query
                .map(|f| from_glib(f(self.to_glib_none().0, query.as_mut_ptr())))
                .unwrap_or(false)
        }
    }

    fn parent_set_context(&self, context: &gst::Context) {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
            (*parent_klass)
                .set_context
                .map(|f| f(self.to_glib_none().0, context.to_glib_none().0))
                .unwrap_or(())
        }
    }

    fn catch_panic<F: FnOnce(&Self) -> T, T>(&self, fallback: T, f: F) -> T {
        let panicked = unsafe { &(*self.get_instance()).panicked };
        panic_to_error!(self, panicked, fallback, { f(self) })
    }
}

pub unsafe trait ElementClassExt<T: ElementBase>
where
    T::ImplType: ElementImpl<T>,
{
    fn add_pad_template(&mut self, pad_template: gst::PadTemplate) {
        unsafe {
            gst_ffi::gst_element_class_add_pad_template(
                self as *const Self as *mut gst_ffi::GstElementClass,
                pad_template.to_glib_full(),
            );
        }
    }

    fn set_metadata(
        &mut self,
        long_name: &str,
        classification: &str,
        description: &str,
        author: &str,
    ) {
        unsafe {
            gst_ffi::gst_element_class_set_metadata(
                self as *const Self as *mut gst_ffi::GstElementClass,
                long_name.to_glib_none().0,
                classification.to_glib_none().0,
                description.to_glib_none().0,
                author.to_glib_none().0,
            );
        }
    }

    fn override_vfuncs(&mut self, _: &ClassInitToken) {
        unsafe {
            let klass = &mut *(self as *const Self as *mut gst_ffi::GstElementClass);
            klass.change_state = Some(element_change_state::<T>);
            klass.request_new_pad = Some(element_request_new_pad::<T>);
            klass.release_pad = Some(element_release_pad::<T>);
            klass.send_event = Some(element_send_event::<T>);
            klass.query = Some(element_query::<T>);
            klass.set_context = Some(element_set_context::<T>);
        }
    }
}

glib_wrapper! {
    pub struct Element(Object<InstanceStruct<Element>>): [gst::Element => gst_ffi::GstElement,
                                                          gst::Object => gst_ffi::GstObject];

    match fn {
        get_type => || get_type::<Element>(),
    }
}

unsafe impl<T: IsA<gst::Element> + ObjectType> ElementBase for T {}
pub type ElementClass = ClassStruct<Element>;

// FIXME: Boilerplate
unsafe impl ElementClassExt<Element> for ElementClass {}

#[macro_export]
macro_rules! box_element_impl(
    ($name:ident) => {
        box_object_impl!($name);

        impl<T: ElementBase> ElementImpl<T> for Box<$name<T>> {
            fn change_state(
                &self,
                element: &T,
                transition: gst::StateChange,
            ) -> gst::StateChangeReturn {
                let imp: &$name<T> = self.as_ref();
                imp.change_state(element, transition)
            }

            fn request_new_pad(&self, element: &T, templ: &gst::PadTemplate, name: Option<String>, caps: Option<&gst::CapsRef>) -> Option<gst::Pad> {
                let imp: &$name<T> = self.as_ref();
                imp.request_new_pad(element, templ, name, caps)
            }

            fn release_pad(&self, element: &T, pad: &gst::Pad) {
                let imp: &$name<T> = self.as_ref();
                imp.release_pad(element, pad)
            }

            fn send_event(&self, element: &T, event: gst::Event) -> bool {
                let imp: &$name<T> = self.as_ref();
                imp.send_event(element, event)
            }

            fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
                let imp: &$name<T> = self.as_ref();
                ElementImpl::query(imp, element, query)
            }

            fn set_context(&self, element: &T, context: &gst::Context) {
                let imp: &$name<T> = self.as_ref();
                imp.set_context(element, context)
            }
        }
    };
);

box_element_impl!(ElementImpl);

impl ObjectType for Element {
    const NAME: &'static str = "RsElement";
    type GlibType = gst_ffi::GstElement;
    type GlibClassType = gst_ffi::GstElementClass;
    type ImplType = Box<ElementImpl<Self>>;

    fn glib_type() -> glib::Type {
        unsafe { from_glib(gst_ffi::gst_element_get_type()) }
    }

    fn class_init(token: &ClassInitToken, klass: &mut ElementClass) {
        klass.override_vfuncs(token);
    }

    object_type_fns!();
}

unsafe extern "C" fn element_change_state<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    transition: gst_ffi::GstStateChange,
) -> gst_ffi::GstStateChangeReturn
where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;

    panic_to_error!(&wrap, &element.panicked, gst::StateChangeReturn::Failure, {
        imp.change_state(&wrap, from_glib(transition))
    }).to_glib()
}

unsafe extern "C" fn element_request_new_pad<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    templ: *mut gst_ffi::GstPadTemplate,
    name: *const libc::c_char,
    caps: *const gst_ffi::GstCaps,
) -> *mut gst_ffi::GstPad
where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;
    let caps = if caps.is_null() {
        None
    } else {
        Some(gst::CapsRef::from_ptr(caps))
    };

    // XXX: This is effectively unsafe but the best we can do
    // See https://bugzilla.gnome.org/show_bug.cgi?id=791193
    let pad = panic_to_error!(&wrap, &element.panicked, None, {
        imp.request_new_pad(&wrap, &from_glib_borrow(templ), from_glib_none(name), caps)
    });

    // Ensure that the pad is owned by the element now, if a pad was returned
    if let Some(ref pad) = pad {
        assert_eq!(
            pad.get_parent(),
            Some(gst::Object::from_glib_borrow(
                ptr as *mut gst_ffi::GstObject
            ))
        );
    }

    pad.to_glib_none().0
}

unsafe extern "C" fn element_release_pad<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    pad: *mut gst_ffi::GstPad,
) where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;

    panic_to_error!(&wrap, &element.panicked, (), {
        imp.release_pad(&wrap, &from_glib_borrow(pad))
    })
}

unsafe extern "C" fn element_send_event<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    event: *mut gst_ffi::GstEvent,
) -> glib_ffi::gboolean
where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;

    panic_to_error!(&wrap, &element.panicked, false, {
        imp.send_event(&wrap, from_glib_full(event))
    }).to_glib()
}

unsafe extern "C" fn element_query<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    query: *mut gst_ffi::GstQuery,
) -> glib_ffi::gboolean
where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;
    let query = gst::QueryRef::from_mut_ptr(query);

    panic_to_error!(&wrap, &element.panicked, false, { imp.query(&wrap, query) }).to_glib()
}

unsafe extern "C" fn element_set_context<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    context: *mut gst_ffi::GstContext,
) where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;

    panic_to_error!(&wrap, &element.panicked, (), {
        imp.set_context(&wrap, &from_glib_borrow(context))
    })
}
<commit_msg>Never fail downwards state changes<commit_after>// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::ptr;
use std::mem;

use libc;

use glib_ffi;
use gobject_ffi;
use gst_ffi;

use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;

use object::*;
use anyimpl::*;

pub trait ElementImpl<T: ElementBase>
    : ObjectImpl<T> + AnyImpl + Send + Sync + 'static {
    fn change_state(&self, element: &T, transition: gst::StateChange) -> gst::StateChangeReturn {
        element.parent_change_state(transition)
    }

    fn request_new_pad(
        &self,
        _element: &T,
        _templ: &gst::PadTemplate,
        _name: Option<String>,
        _caps: Option<&gst::CapsRef>,
    ) -> Option<gst::Pad> {
        None
    }

    fn release_pad(&self, _element: &T, _pad: &gst::Pad) {}

    fn send_event(&self, element: &T, event: gst::Event) -> bool {
        element.parent_send_event(event)
    }

    fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
        element.parent_query(query)
    }

    fn set_context(&self, element: &T, context: &gst::Context) {
        element.parent_set_context(context)
    }
}

any_impl!(ElementBase, ElementImpl);

pub unsafe trait ElementBase: IsA<gst::Element> + ObjectType {
    fn parent_change_state(&self, transition: gst::StateChange) -> gst::StateChangeReturn {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
            (*parent_klass)
                .change_state
                .map(|f| {
                    from_glib(f(self.to_glib_none().0, transition.to_glib()))
                })
                .unwrap_or(gst::StateChangeReturn::Success)
        }
    }

    fn parent_send_event(&self, event: gst::Event) -> bool {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
            (*parent_klass)
                .send_event
                .map(|f| from_glib(f(self.to_glib_none().0, event.into_ptr())))
                .unwrap_or(false)
        }
    }

    fn parent_query(&self, query: &mut gst::QueryRef) -> bool {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
            (*parent_klass)
                .query
                .map(|f| from_glib(f(self.to_glib_none().0, query.as_mut_ptr())))
                .unwrap_or(false)
        }
    }

    fn parent_set_context(&self, context: &gst::Context) {
        unsafe {
            let klass = self.get_class();
            let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstElementClass;
            (*parent_klass)
                .set_context
                .map(|f| f(self.to_glib_none().0, context.to_glib_none().0))
                .unwrap_or(())
        }
    }

    fn catch_panic<F: FnOnce(&Self) -> T, T>(&self, fallback: T, f: F) -> T {
        let panicked = unsafe { &(*self.get_instance()).panicked };
        panic_to_error!(self, panicked, fallback, { f(self) })
    }
}

pub unsafe trait ElementClassExt<T: ElementBase>
where
    T::ImplType: ElementImpl<T>,
{
    fn add_pad_template(&mut self, pad_template: gst::PadTemplate) {
        unsafe {
            gst_ffi::gst_element_class_add_pad_template(
                self as *const Self as *mut gst_ffi::GstElementClass,
                pad_template.to_glib_full(),
            );
        }
    }

    fn set_metadata(
        &mut self,
        long_name: &str,
        classification: &str,
        description: &str,
        author: &str,
    ) {
        unsafe {
            gst_ffi::gst_element_class_set_metadata(
                self as *const Self as *mut gst_ffi::GstElementClass,
                long_name.to_glib_none().0,
                classification.to_glib_none().0,
                description.to_glib_none().0,
                author.to_glib_none().0,
            );
        }
    }

    fn override_vfuncs(&mut self, _: &ClassInitToken) {
        unsafe {
            let klass = &mut *(self as *const Self as *mut gst_ffi::GstElementClass);
            klass.change_state = Some(element_change_state::<T>);
            klass.request_new_pad = Some(element_request_new_pad::<T>);
            klass.release_pad = Some(element_release_pad::<T>);
            klass.send_event = Some(element_send_event::<T>);
            klass.query = Some(element_query::<T>);
            klass.set_context = Some(element_set_context::<T>);
        }
    }
}

glib_wrapper! {
    pub struct Element(Object<InstanceStruct<Element>>): [gst::Element => gst_ffi::GstElement,
                                                          gst::Object => gst_ffi::GstObject];

    match fn {
        get_type => || get_type::<Element>(),
    }
}

unsafe impl<T: IsA<gst::Element> + ObjectType> ElementBase for T {}
pub type ElementClass = ClassStruct<Element>;

// FIXME: Boilerplate
unsafe impl ElementClassExt<Element> for ElementClass {}

#[macro_export]
macro_rules! box_element_impl(
    ($name:ident) => {
        box_object_impl!($name);

        impl<T: ElementBase> ElementImpl<T> for Box<$name<T>> {
            fn change_state(
                &self,
                element: &T,
                transition: gst::StateChange,
            ) -> gst::StateChangeReturn {
                let imp: &$name<T> = self.as_ref();
                imp.change_state(element, transition)
            }

            fn request_new_pad(&self, element: &T, templ: &gst::PadTemplate, name: Option<String>, caps: Option<&gst::CapsRef>) -> Option<gst::Pad> {
                let imp: &$name<T> = self.as_ref();
                imp.request_new_pad(element, templ, name, caps)
            }

            fn release_pad(&self, element: &T, pad: &gst::Pad) {
                let imp: &$name<T> = self.as_ref();
                imp.release_pad(element, pad)
            }

            fn send_event(&self, element: &T, event: gst::Event) -> bool {
                let imp: &$name<T> = self.as_ref();
                imp.send_event(element, event)
            }

            fn query(&self, element: &T, query: &mut gst::QueryRef) -> bool {
                let imp: &$name<T> = self.as_ref();
                ElementImpl::query(imp, element, query)
            }

            fn set_context(&self, element: &T, context: &gst::Context) {
                let imp: &$name<T> = self.as_ref();
                imp.set_context(element, context)
            }
        }
    };
);

box_element_impl!(ElementImpl);

impl ObjectType for Element {
    const NAME: &'static str = "RsElement";
    type GlibType = gst_ffi::GstElement;
    type GlibClassType = gst_ffi::GstElementClass;
    type ImplType = Box<ElementImpl<Self>>;

    fn glib_type() -> glib::Type {
        unsafe { from_glib(gst_ffi::gst_element_get_type()) }
    }

    fn class_init(token: &ClassInitToken, klass: &mut ElementClass) {
        klass.override_vfuncs(token);
    }

    object_type_fns!();
}

unsafe extern "C" fn element_change_state<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    transition: gst_ffi::GstStateChange,
) -> gst_ffi::GstStateChangeReturn
where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;

    // *Never* fail downwards state changes, this causes bugs in GStreamer
    // and leads to crashes and deadlocks.
    let transition = from_glib(transition);
    let fallback = match transition {
        gst::StateChange::PlayingToPaused
        | gst::StateChange::PausedToReady
        | gst::StateChange::ReadyToNull => gst::StateChangeReturn::Success,
        _ => gst::StateChangeReturn::Failure,
    };

    panic_to_error!(&wrap, &element.panicked, fallback, {
        imp.change_state(&wrap, transition)
    }).to_glib()
}

unsafe extern "C" fn element_request_new_pad<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    templ: *mut gst_ffi::GstPadTemplate,
    name: *const libc::c_char,
    caps: *const gst_ffi::GstCaps,
) -> *mut gst_ffi::GstPad
where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;
    let caps = if caps.is_null() {
        None
    } else {
        Some(gst::CapsRef::from_ptr(caps))
    };

    // XXX: This is effectively unsafe but the best we can do
    // See https://bugzilla.gnome.org/show_bug.cgi?id=791193
    let pad = panic_to_error!(&wrap, &element.panicked, None, {
        imp.request_new_pad(&wrap, &from_glib_borrow(templ), from_glib_none(name), caps)
    });

    // Ensure that the pad is owned by the element now, if a pad was returned
    if let Some(ref pad) = pad {
        assert_eq!(
            pad.get_parent(),
            Some(gst::Object::from_glib_borrow(
                ptr as *mut gst_ffi::GstObject
            ))
        );
    }

    pad.to_glib_none().0
}

unsafe extern "C" fn element_release_pad<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    pad: *mut gst_ffi::GstPad,
) where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;

    panic_to_error!(&wrap, &element.panicked, (), {
        imp.release_pad(&wrap, &from_glib_borrow(pad))
    })
}

unsafe extern "C" fn element_send_event<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    event: *mut gst_ffi::GstEvent,
) -> glib_ffi::gboolean
where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;

    panic_to_error!(&wrap, &element.panicked, false, {
        imp.send_event(&wrap, from_glib_full(event))
    }).to_glib()
}

unsafe extern "C" fn element_query<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    query: *mut gst_ffi::GstQuery,
) -> glib_ffi::gboolean
where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;
    let query = gst::QueryRef::from_mut_ptr(query);

    panic_to_error!(&wrap, &element.panicked, false, { imp.query(&wrap, query) }).to_glib()
}

unsafe extern "C" fn element_set_context<T: ElementBase>(
    ptr: *mut gst_ffi::GstElement,
    context: *mut gst_ffi::GstContext,
) where
    T::ImplType: ElementImpl<T>,
{
    callback_guard!();
    floating_reference_guard!(ptr);
    let element = &*(ptr as *mut InstanceStruct<T>);
    let wrap: T = from_glib_borrow(ptr as *mut InstanceStruct<T>);
    let imp = &*element.imp;

    panic_to_error!(&wrap, &element.panicked, (), {
        imp.set_context(&wrap, &from_glib_borrow(context))
    })
}
<|endoftext|>


<commit_before>use ::nalgebra::{
    base::allocator::Allocator,
    base::{dimension::DimName, MatrixN, VectorN},
    DefaultAllocator, Dim, DimMin, U1,
};
use ::num_traits::float::Float;

const STEPS: usize = 1_000;

/// The `Min` trait specifies than an object has a minimum value
pub trait Min<T> {
    /// Returns the minimum value in the domain of a given distribution
    /// if it exists, otherwise `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Min;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.min());
    /// ```
    fn min(&self) -> T;
}

/// The `Max` trait specifies that an object has a maximum value
pub trait Max<T> {
    /// Returns the maximum value in the domain of a given distribution
    /// if it exists, otherwise `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Max;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0, n.max());
    /// ```
    fn max(&self) -> T;
}
pub trait DiscreteDistribution<T: Float>: ::rand::distributions::Distribution<u64> {
    /// Returns the mean, if it exists.
    fn mean(&self) -> Option<T> {
        None
    }
    /// Returns the variance, if it exists.
    fn variance(&self) -> Option<T> {
        None
    }
    /// Returns the standard deviation, if it exists.
    fn std_dev(&self) -> Option<T> {
        self.variance().map(|var| var.sqrt())
    }
    /// Returns the entropy, if it exists.
    fn entropy(&self) -> Option<T> {
        None
    }
    /// Returns the skewness, if it exists.
    fn skewness(&self) -> Option<T> {
        None
    }
}

pub trait Distribution<T: Float>: ::rand::distributions::Distribution<T> {
    /// Returns the mean, if it exists.
    /// The default implementation returns an estimation
    /// based on random samples. This is a crude estimate
    /// for when no further information is known about the
    /// distribution. More accurate statements about the
    /// mean can and should be given by overriding the
    /// default implementation.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Distribution;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.mean().unwrap());
    /// ```
    fn mean(&self) -> Option<T> {
        let mut rng = ::rand::rngs::OsRng;
        let mut mean = T::zero();
        let mut steps = T::zero();
        for _ in 0..STEPS {
            steps = steps + T::one();
            mean = mean + Self::sample(self, &mut rng);
        }
        Some(mean / steps)
    }
    /// Returns the variance, if it exists.
    /// The default implementation returns an estimation
    /// based on random samples. This is a crude estimate
    /// for when no further information is known about the
    /// distribution. More accurate statements about the
    /// variance can and should be given by overriding the
    /// default implementation.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Distribution;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0 / 12.0, n.variance().unwrap());
    /// ```
    fn variance(&self) -> Option<T> {
        let mut rng = ::rand::rngs::OsRng;
        let mut mean = T::zero();
        let mut variance = T::zero();
        let mut steps = T::zero();
        for _ in 0..STEPS {
            steps = steps + T::one();
            let sample = Self::sample(self, &mut rng);
            variance = variance + (steps - T::one()) * (sample - mean) * (sample - mean) / steps;
            mean = mean + (sample - mean) / steps;
        }
        steps = steps - T::one();
        Some(variance / steps)
    }
    /// Returns the standard deviation, if it exists.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Distribution;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!((1f64 / 12f64).sqrt(), n.std_dev().unwrap());
    /// ```
    fn std_dev(&self) -> Option<T> {
        self.variance().map(|var| var.sqrt())
    }
    /// Returns the entropy, if it exists.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Distribution;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.entropy().unwrap());
    /// ```
    fn entropy(&self) -> Option<T> {
        None
    }
    /// Returns the skewness, if it exists.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Distribution;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.skewness().unwrap());
    /// ```
    fn skewness(&self) -> Option<T> {
        None
    }
}

/// The `MeanN` trait is the multivariable version of the `Mean` trait.
pub trait MeanN<N>
where
    N: Dim + DimMin<N, Output = N> + DimName,
    DefaultAllocator: Allocator<f64, N>,
    DefaultAllocator: Allocator<f64, N, N>,
    DefaultAllocator: Allocator<f64, U1, N>,
    DefaultAllocator: Allocator<(usize, usize), <N as DimMin<N>>::Output>,
{
    fn mean(&self) -> VectorN<f64, N>;
}

pub trait Covariance<N>: MeanN<N>
where
    N: Dim + DimMin<N, Output = N> + DimName,
    DefaultAllocator: Allocator<f64, N>,
    DefaultAllocator: Allocator<f64, N, N>,
    DefaultAllocator: Allocator<f64, U1, N>,
    DefaultAllocator: Allocator<(usize, usize), <N as DimMin<N>>::Output>,
{
    fn variance(&self) -> MatrixN<f64, N>;
}

/// The `Median` trait specifies than an object has a closed form solution
/// for its median
pub trait Median<T> {
    /// Returns the median.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Median;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.median());
    /// ```
    fn median(&self) -> T;
}

/// The `Mode` trait specifies that an object has a closed form solution
/// for its mode(s)
pub trait Mode<T> {
    /// Returns the mode, if one exists.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Mode;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(Some(0.5), n.mode());
    /// ```
    fn mode(&self) -> T;
}
<commit_msg>api: redo multivariate distribution traits<commit_after>use ::nalgebra::{
    base::allocator::Allocator,
    base::{dimension::DimName, MatrixN, VectorN},
    DefaultAllocator, Dim, DimMin, U1,
};
use ::num_traits::float::Float;

const STEPS: usize = 1_000;

/// The `Min` trait specifies than an object has a minimum value
pub trait Min<T> {
    /// Returns the minimum value in the domain of a given distribution
    /// if it exists, otherwise `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Min;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.min());
    /// ```
    fn min(&self) -> T;
}

/// The `Max` trait specifies that an object has a maximum value
pub trait Max<T> {
    /// Returns the maximum value in the domain of a given distribution
    /// if it exists, otherwise `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Max;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0, n.max());
    /// ```
    fn max(&self) -> T;
}
pub trait DiscreteDistribution<T: Float>: ::rand::distributions::Distribution<u64> {
    /// Returns the mean, if it exists.
    fn mean(&self) -> Option<T> {
        None
    }
    /// Returns the variance, if it exists.
    fn variance(&self) -> Option<T> {
        None
    }
    /// Returns the standard deviation, if it exists.
    fn std_dev(&self) -> Option<T> {
        self.variance().map(|var| var.sqrt())
    }
    /// Returns the entropy, if it exists.
    fn entropy(&self) -> Option<T> {
        None
    }
    /// Returns the skewness, if it exists.
    fn skewness(&self) -> Option<T> {
        None
    }
}

pub trait Distribution<T: Float>: ::rand::distributions::Distribution<T> {
    /// Returns the mean, if it exists.
    /// The default implementation returns an estimation
    /// based on random samples. This is a crude estimate
    /// for when no further information is known about the
    /// distribution. More accurate statements about the
    /// mean can and should be given by overriding the
    /// default implementation.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Distribution;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.mean().unwrap());
    /// ```
    fn mean(&self) -> Option<T> {
        // TODO: Does not need cryptographic rng
        let mut rng = ::rand::rngs::OsRng;
        let mut mean = T::zero();
        let mut steps = T::zero();
        for _ in 0..STEPS {
            steps = steps + T::one();
            mean = mean + Self::sample(self, &mut rng);
        }
        Some(mean / steps)
    }
    /// Returns the variance, if it exists.
    /// The default implementation returns an estimation
    /// based on random samples. This is a crude estimate
    /// for when no further information is known about the
    /// distribution. More accurate statements about the
    /// variance can and should be given by overriding the
    /// default implementation.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Distribution;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(1.0 / 12.0, n.variance().unwrap());
    /// ```
    fn variance(&self) -> Option<T> {
        // TODO: Does not need cryptographic rng
        let mut rng = ::rand::rngs::OsRng;
        let mut mean = T::zero();
        let mut variance = T::zero();
        let mut steps = T::zero();
        for _ in 0..STEPS {
            steps = steps + T::one();
            let sample = Self::sample(self, &mut rng);
            variance = variance + (steps - T::one()) * (sample - mean) * (sample - mean) / steps;
            mean = mean + (sample - mean) / steps;
        }
        steps = steps - T::one();
        Some(variance / steps)
    }
    /// Returns the standard deviation, if it exists.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Distribution;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!((1f64 / 12f64).sqrt(), n.std_dev().unwrap());
    /// ```
    fn std_dev(&self) -> Option<T> {
        self.variance().map(|var| var.sqrt())
    }
    /// Returns the entropy, if it exists.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Distribution;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.entropy().unwrap());
    /// ```
    fn entropy(&self) -> Option<T> {
        None
    }
    /// Returns the skewness, if it exists.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Distribution;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.0, n.skewness().unwrap());
    /// ```
    fn skewness(&self) -> Option<T> {
        None
    }
}

/// The `Mean` trait implements the calculation of a mean.
// TODO: Clarify the traits of multidimensional distributions
pub trait MeanN<T> {
    fn mean(&self) -> Option<T>;
}

// TODO: Clarify the traits of multidimensional distributions
pub trait VarianceN<T> {
    fn variance(&self) -> Option<T>;
}

/// The `Median` trait returns the median of the distribution.
pub trait Median<T> {
    /// Returns the median.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Median;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(0.5, n.median());
    /// ```
    fn median(&self) -> T;
}

/// The `Mode` trait specifies that an object has a closed form solution
/// for its mode(s)
pub trait Mode<T> {
    /// Returns the mode, if one exists.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::statistics::Mode;
    /// use statrs::distribution::Uniform;
    ///
    /// let n = Uniform::new(0.0, 1.0).unwrap();
    /// assert_eq!(Some(0.5), n.mode());
    /// ```
    fn mode(&self) -> T;
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use walkdir::{WalkDir, WalkDirIterator};

use config;
use repository::*;
use error::GhqError;
use vcs;

pub struct Workspace {
  config: config::Config,
  repos: BTreeMap<String, Vec<Repository>>,
}

impl Workspace {
  pub fn new(config: config::Config) -> Workspace {
    let mut repos = BTreeMap::new();
    for root in &config.roots {
      repos.insert(root.to_owned(), Self::collect_local_repos(&root));
    }

    Workspace {
      config: config,
      repos: repos,
    }
  }

  fn collect_local_repos(root: &str) -> Vec<Repository> {
    WalkDir::new(&root)
      .follow_links(true)
      .into_iter()
      .filter_entry(|entry| is_vcs_root(entry.path()))
      .filter_map(|entry| entry.ok())
      .filter_map(|entry| relative_path(entry.path(), root).ok())
      .filter_map(|path| Repository::from_local(&path).ok())
      .collect()
  }

  pub fn show_roots(&self, all: bool) {
    if all {
      for root in &self.config.roots {
        println!("{}", root);
      }
    } else if let Some(ref root) = self.config.roots.iter().next() {
      println!("{}", root);
    }
  }

  pub fn show_repositories(&self) {
    for (root, repos) in &self.repos {
      for repo in repos {
        println!("{}", repo.local_path(root).display());
      }
    }
  }

  // clone a remote repository into the workspace.
  pub fn clone_from(&self, s: &str, root: Option<&str>) -> Result<(), GhqError> {
    // get the path of root directory
    let root = root.or(self.config.roots.iter().next().map(|s| s.as_str())).unwrap_or("");
    if !Path::new(root).exists() {
      println!("The root directory does not exist: {}", root);
      return Ok(());
    }

    Repository::from_remote(s)?.clone_into(root)
  }
}

// make relative path from `root`
fn relative_path(path: &Path, root: &str) -> Result<PathBuf, GhqError> {
  Ok(path.strip_prefix(root)?.to_path_buf())
}

fn is_vcs_root(path: &Path) -> bool {
  path.is_dir() && !vcs::is_vcs_subdir(path)
}
<commit_msg>fix predicate<commit_after>use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use walkdir::{WalkDir, WalkDirIterator};

use config;
use repository::*;
use error::GhqError;
use vcs;

pub struct Workspace {
  config: config::Config,
  repos: BTreeMap<String, Vec<Repository>>,
}

impl Workspace {
  pub fn new(config: config::Config) -> Workspace {
    let mut repos = BTreeMap::new();
    for root in &config.roots {
      repos.insert(root.to_owned(), Self::collect_local_repos(&root));
    }

    Workspace {
      config: config,
      repos: repos,
    }
  }

  fn collect_local_repos(root: &str) -> Vec<Repository> {
    WalkDir::new(&root)
      .follow_links(true)
      .into_iter()
      .filter_entry(|entry| !is_vcs_component(entry.path()))
      .filter_map(|entry| entry.ok())
      .filter_map(|entry| relative_path(entry.path(), root).ok())
      .filter_map(|path| Repository::from_local(&path).ok())
      .collect()
  }

  pub fn show_roots(&self, all: bool) {
    if all {
      for root in &self.config.roots {
        println!("{}", root);
      }
    } else if let Some(ref root) = self.config.roots.iter().next() {
      println!("{}", root);
    }
  }

  pub fn show_repositories(&self) {
    for (root, repos) in &self.repos {
      for repo in repos {
        println!("{}", repo.local_path(root).display());
      }
    }
  }

  // clone a remote repository into the workspace.
  pub fn clone_from(&self, s: &str, root: Option<&str>) -> Result<(), GhqError> {
    // get the path of root directory
    let root = root.or(self.config.roots.iter().next().map(|s| s.as_str())).unwrap_or("");
    if !Path::new(root).exists() {
      println!("The root directory does not exist: {}", root);
      return Ok(());
    }

    Repository::from_remote(s)?.clone_into(root)
  }
}

// make relative path from `root`
fn relative_path(path: &Path, root: &str) -> Result<PathBuf, GhqError> {
  Ok(path.strip_prefix(root)?.to_path_buf())
}

fn is_vcs_component(path: &Path) -> bool {
  if let Some(path) = path.parent() {
    [".git", ".svn", ".hg", "_dacrs"].into_iter().any(|v| vcs::is_vcs_subdir(&path.join(v)))
  } else {
    false
  }
}
<|endoftext|>


<commit_before>// Tests for the serializer and deserializer are located in tests/serde_/mod.rs.
// They can be run with `cargo test --features serde_tests`.

use serde::de::{Deserializer as SerdeDeserializer, Error as SerdeError, Visitor, SeqVisitor,
                MapVisitor, VariantVisitor, Deserialize, EnumVisitor};
use std::iter::Peekable;

use {Error, PlistEvent, u64_option_to_usize};

macro_rules! expect {
    ($next:expr, $pat:pat) => {
        match $next {
            Some(Ok(v@$pat)) => v,
            None => return Err(Error::UnexpectedEof),
            _ => return return Err(event_mismatch_error())
        }
    };
    ($next:expr, $pat:pat => $save:expr) => {
        match $next {
            Some(Ok($pat)) => $save,
            None => return Err(Error::UnexpectedEof),
            _ => return Err(event_mismatch_error())
        }
    };
}

macro_rules! try_next {
    ($next:expr) => {
        match $next {
            Some(Ok(v)) => v,
            Some(Err(_)) => return Err(event_mismatch_error()),
            None => return Err(Error::UnexpectedEof)
        }
    }
}

fn event_mismatch_error() -> Error {
    Error::InvalidData
}

impl SerdeError for Error {
    fn custom<T: Into<String>>(msg: T) -> Self {
        Error::Serde(msg.into())
    }

    fn end_of_stream() -> Self {
        Error::UnexpectedEof
    }
}

pub struct Deserializer<I>
    where I: IntoIterator<Item = Result<PlistEvent, Error>>
{
    events: Peekable<<I as IntoIterator>::IntoIter>,
}

impl<I> Deserializer<I> where I: IntoIterator<Item = Result<PlistEvent, Error>>
{
    pub fn new(iter: I) -> Deserializer<I> {
        Deserializer { events: iter.into_iter().peekable() }
    }
}

impl<I> SerdeDeserializer for Deserializer<I>
    where I: IntoIterator<Item = Result<PlistEvent, Error>>
{
    type Error = Error;

    fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        match try_next!(self.events.next()) {
            PlistEvent::StartArray(len) => {
                let len = try!(u64_option_to_usize(len));
                visitor.visit_seq(MapSeq::new(self, len))
            }
            PlistEvent::EndArray => return Err(event_mismatch_error()),

            PlistEvent::StartDictionary(len) => {
                let len = try!(u64_option_to_usize(len));
                visitor.visit_map(MapSeq::new(self, len))
            }
            PlistEvent::EndDictionary => return Err(event_mismatch_error()),

            PlistEvent::BooleanValue(v) => visitor.visit_bool(v),
            PlistEvent::DataValue(v) => visitor.visit_byte_buf(v),
            PlistEvent::DateValue(v) => visitor.visit_string(v.to_rfc3339()),
            PlistEvent::IntegerValue(v) if v.is_positive() => visitor.visit_u64(v as u64),
            PlistEvent::IntegerValue(v) => visitor.visit_i64(v as i64),
            PlistEvent::RealValue(v) => visitor.visit_f64(v),
            PlistEvent::StringValue(v) => visitor.visit_string(v),
        }
    }

    fn deserialize_unit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        expect!(self.events.next(), PlistEvent::StringValue(_));
        visitor.visit_unit()
    }

    fn deserialize_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        expect!(self.events.next(), PlistEvent::StartDictionary(_));

        let ret = match try_next!(self.events.next()) {
            PlistEvent::StringValue(ref s) if &s[..] == "None" => {
                let ret = match visitor.visit_none() {
                    Ok(ret) => ret,
                    Err(e) => return Err(e),
                };
                // For some reason the try! below doesn't work - probably a macro hygene issue
                // with Error and ::Error
                // let ret = try!(visitor.visit_none());
                expect!(self.events.next(), PlistEvent::StringValue(_));
                ret
            }
            PlistEvent::StringValue(ref s) if &s[..] == "Some" => try!(visitor.visit_some(self)),
            _ => return Err(event_mismatch_error()),
        };

        expect!(self.events.next(), PlistEvent::EndDictionary);

        Ok(ret)
    }

    fn deserialize_newtype_struct<V>(&mut self,
                               _name: &'static str,
                               mut visitor: V)
                               -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        visitor.visit_newtype_struct(self)
    }

    fn deserialize_enum<V>(&mut self,
                     _enum: &'static str,
                     _variants: &'static [&'static str],
                     mut visitor: V)
                     -> Result<V::Value, Self::Error>
        where V: EnumVisitor
    {
        expect!(self.events.next(), PlistEvent::StartDictionary(_));
        let ret = try!(visitor.visit(&mut *self));
        expect!(self.events.next(), PlistEvent::EndDictionary);
        Ok(ret)
    }
}

impl<I> VariantVisitor for Deserializer<I> where I: IntoIterator<Item = Result<PlistEvent, Error>>
{
    type Error = Error;

    fn visit_variant<V>(&mut self) -> Result<V, Self::Error>
        where V: Deserialize
    {
        <V as Deserialize>::deserialize(self)
    }

    fn visit_unit(&mut self) -> Result<(), Self::Error> {
        <() as Deserialize>::deserialize(self)
    }

    fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
        where T: Deserialize
    {
        <T as Deserialize>::deserialize(self)
    }

    fn visit_tuple<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        <Self as SerdeDeserializer>::deserialize_tuple(self, len, visitor)
    }

    fn visit_struct<V>(&mut self,
                       fields: &'static [&'static str],
                       visitor: V)
                       -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        let name = "";
        <Self as SerdeDeserializer>::deserialize_struct(self, name, fields, visitor)
    }
}

struct MapSeq<'a, I>
    where I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>
{
    de: &'a mut Deserializer<I>,
    remaining: Option<usize>,
    finished: bool,
}

impl<'a, I> MapSeq<'a, I> where I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>
{
    fn new(de: &'a mut Deserializer<I>, len: Option<usize>) -> MapSeq<'a, I> {
        MapSeq {
            de: de,
            remaining: len,
            finished: false,
        }
    }
}

impl<'a, I> SeqVisitor for MapSeq<'a, I>
    where I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>
{
    type Error = Error;

    fn visit<T>(&mut self) -> Result<Option<T>, Self::Error>
        where T: Deserialize
    {
        match self.de.events.peek() {
            Some(&Ok(PlistEvent::EndArray)) => {
                self.de.events.next();
                self.finished = true;
                return Ok(None);
            }
            _ => <T as Deserialize>::deserialize(self.de).map(|k| Some(k)),
        }
    }

    fn end(&mut self) -> Result<(), Self::Error> {
        if !self.finished {
            self.finished = true;
            expect!(self.de.events.next(), PlistEvent::EndArray);
        }
        Ok(())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        <Self as MapVisitor>::size_hint(self)
    }
}

impl<'a, I> MapVisitor for MapSeq<'a, I>
    where I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>
{
    type Error = Error;

    fn visit_key<K>(&mut self) -> Result<Option<K>, Self::Error>
        where K: Deserialize
    {
        match self.de.events.peek() {
            Some(&Ok(PlistEvent::EndDictionary)) => {
                self.de.events.next();
                self.finished = true;
                return Ok(None);
            }
            _ => <K as Deserialize>::deserialize(self.de).map(|k| Some(k)),
        }
    }

    fn visit_value<V>(&mut self) -> Result<V, Self::Error>
        where V: Deserialize
    {
        <V as Deserialize>::deserialize(self.de)
    }

    fn end(&mut self) -> Result<(), Self::Error> {
        if !self.finished {
            self.finished = true;
            expect!(self.de.events.next(), PlistEvent::EndDictionary);
        }
        Ok(())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.remaining {
            Some(len) => (len, Some(len)),
            None => (0, None),
        }
    }
}
<commit_msg>Fix warning coming from double return statement<commit_after>// Tests for the serializer and deserializer are located in tests/serde_/mod.rs.
// They can be run with `cargo test --features serde_tests`.

use serde::de::{Deserializer as SerdeDeserializer, Error as SerdeError, Visitor, SeqVisitor,
                MapVisitor, VariantVisitor, Deserialize, EnumVisitor};
use std::iter::Peekable;

use {Error, PlistEvent, u64_option_to_usize};

macro_rules! expect {
    ($next:expr, $pat:pat) => {
        match $next {
            Some(Ok(v@$pat)) => v,
            None => return Err(Error::UnexpectedEof),
            _ => return Err(event_mismatch_error())
        }
    };
    ($next:expr, $pat:pat => $save:expr) => {
        match $next {
            Some(Ok($pat)) => $save,
            None => return Err(Error::UnexpectedEof),
            _ => return Err(event_mismatch_error())
        }
    };
}

macro_rules! try_next {
    ($next:expr) => {
        match $next {
            Some(Ok(v)) => v,
            Some(Err(_)) => return Err(event_mismatch_error()),
            None => return Err(Error::UnexpectedEof)
        }
    }
}

fn event_mismatch_error() -> Error {
    Error::InvalidData
}

impl SerdeError for Error {
    fn custom<T: Into<String>>(msg: T) -> Self {
        Error::Serde(msg.into())
    }

    fn end_of_stream() -> Self {
        Error::UnexpectedEof
    }
}

pub struct Deserializer<I>
    where I: IntoIterator<Item = Result<PlistEvent, Error>>
{
    events: Peekable<<I as IntoIterator>::IntoIter>,
}

impl<I> Deserializer<I> where I: IntoIterator<Item = Result<PlistEvent, Error>>
{
    pub fn new(iter: I) -> Deserializer<I> {
        Deserializer { events: iter.into_iter().peekable() }
    }
}

impl<I> SerdeDeserializer for Deserializer<I>
    where I: IntoIterator<Item = Result<PlistEvent, Error>>
{
    type Error = Error;

    fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        match try_next!(self.events.next()) {
            PlistEvent::StartArray(len) => {
                let len = try!(u64_option_to_usize(len));
                visitor.visit_seq(MapSeq::new(self, len))
            }
            PlistEvent::EndArray => return Err(event_mismatch_error()),

            PlistEvent::StartDictionary(len) => {
                let len = try!(u64_option_to_usize(len));
                visitor.visit_map(MapSeq::new(self, len))
            }
            PlistEvent::EndDictionary => return Err(event_mismatch_error()),

            PlistEvent::BooleanValue(v) => visitor.visit_bool(v),
            PlistEvent::DataValue(v) => visitor.visit_byte_buf(v),
            PlistEvent::DateValue(v) => visitor.visit_string(v.to_rfc3339()),
            PlistEvent::IntegerValue(v) if v.is_positive() => visitor.visit_u64(v as u64),
            PlistEvent::IntegerValue(v) => visitor.visit_i64(v as i64),
            PlistEvent::RealValue(v) => visitor.visit_f64(v),
            PlistEvent::StringValue(v) => visitor.visit_string(v),
        }
    }

    fn deserialize_unit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        expect!(self.events.next(), PlistEvent::StringValue(_));
        visitor.visit_unit()
    }

    fn deserialize_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        expect!(self.events.next(), PlistEvent::StartDictionary(_));

        let ret = match try_next!(self.events.next()) {
            PlistEvent::StringValue(ref s) if &s[..] == "None" => {
                let ret = match visitor.visit_none() {
                    Ok(ret) => ret,
                    Err(e) => return Err(e),
                };
                // For some reason the try! below doesn't work - probably a macro hygene issue
                // with Error and ::Error
                // let ret = try!(visitor.visit_none());
                expect!(self.events.next(), PlistEvent::StringValue(_));
                ret
            }
            PlistEvent::StringValue(ref s) if &s[..] == "Some" => try!(visitor.visit_some(self)),
            _ => return Err(event_mismatch_error()),
        };

        expect!(self.events.next(), PlistEvent::EndDictionary);

        Ok(ret)
    }

    fn deserialize_newtype_struct<V>(&mut self,
                               _name: &'static str,
                               mut visitor: V)
                               -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        visitor.visit_newtype_struct(self)
    }

    fn deserialize_enum<V>(&mut self,
                     _enum: &'static str,
                     _variants: &'static [&'static str],
                     mut visitor: V)
                     -> Result<V::Value, Self::Error>
        where V: EnumVisitor
    {
        expect!(self.events.next(), PlistEvent::StartDictionary(_));
        let ret = try!(visitor.visit(&mut *self));
        expect!(self.events.next(), PlistEvent::EndDictionary);
        Ok(ret)
    }
}

impl<I> VariantVisitor for Deserializer<I> where I: IntoIterator<Item = Result<PlistEvent, Error>>
{
    type Error = Error;

    fn visit_variant<V>(&mut self) -> Result<V, Self::Error>
        where V: Deserialize
    {
        <V as Deserialize>::deserialize(self)
    }

    fn visit_unit(&mut self) -> Result<(), Self::Error> {
        <() as Deserialize>::deserialize(self)
    }

    fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
        where T: Deserialize
    {
        <T as Deserialize>::deserialize(self)
    }

    fn visit_tuple<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        <Self as SerdeDeserializer>::deserialize_tuple(self, len, visitor)
    }

    fn visit_struct<V>(&mut self,
                       fields: &'static [&'static str],
                       visitor: V)
                       -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        let name = "";
        <Self as SerdeDeserializer>::deserialize_struct(self, name, fields, visitor)
    }
}

struct MapSeq<'a, I>
    where I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>
{
    de: &'a mut Deserializer<I>,
    remaining: Option<usize>,
    finished: bool,
}

impl<'a, I> MapSeq<'a, I> where I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>
{
    fn new(de: &'a mut Deserializer<I>, len: Option<usize>) -> MapSeq<'a, I> {
        MapSeq {
            de: de,
            remaining: len,
            finished: false,
        }
    }
}

impl<'a, I> SeqVisitor for MapSeq<'a, I>
    where I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>
{
    type Error = Error;

    fn visit<T>(&mut self) -> Result<Option<T>, Self::Error>
        where T: Deserialize
    {
        match self.de.events.peek() {
            Some(&Ok(PlistEvent::EndArray)) => {
                self.de.events.next();
                self.finished = true;
                return Ok(None);
            }
            _ => <T as Deserialize>::deserialize(self.de).map(|k| Some(k)),
        }
    }

    fn end(&mut self) -> Result<(), Self::Error> {
        if !self.finished {
            self.finished = true;
            expect!(self.de.events.next(), PlistEvent::EndArray);
        }
        Ok(())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        <Self as MapVisitor>::size_hint(self)
    }
}

impl<'a, I> MapVisitor for MapSeq<'a, I>
    where I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>
{
    type Error = Error;

    fn visit_key<K>(&mut self) -> Result<Option<K>, Self::Error>
        where K: Deserialize
    {
        match self.de.events.peek() {
            Some(&Ok(PlistEvent::EndDictionary)) => {
                self.de.events.next();
                self.finished = true;
                return Ok(None);
            }
            _ => <K as Deserialize>::deserialize(self.de).map(|k| Some(k)),
        }
    }

    fn visit_value<V>(&mut self) -> Result<V, Self::Error>
        where V: Deserialize
    {
        <V as Deserialize>::deserialize(self.de)
    }

    fn end(&mut self) -> Result<(), Self::Error> {
        if !self.finished {
            self.finished = true;
            expect!(self.de.events.next(), PlistEvent::EndDictionary);
        }
        Ok(())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        match self.remaining {
            Some(len) => (len, Some(len)),
            None => (0, None),
        }
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::io::{self, Read, Write};
use std::net::Shutdown;

use futures::prelude::*;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::io::shutdown;
use bytes::{BytesMut, Bytes, BufMut, IntoBuf};
use h2::{self, server as h2s, client as h2c};
use tokio_core::net::TcpStream;

const BUF_SIZE: usize = 2048;

#[async]
pub fn copy_from_h2<
    W: AsyncWrite + 'static,
    B: Stream<Item = Bytes, Error = h2::Error> + 'static,
>(
    src: B,
    mut dst: W,
) -> Result<usize, h2::Error> {
    let mut counter = 0;
    #[async]
    for buf in src {
        let mut buf = buf.into_buf();
        let n = poll!(dst.write_buf(&mut buf))?;
        counter += n;
    }
    await!(shutdown(dst))?;
    Ok(counter)
}

pub trait H2Stream<B: IntoBuf> {
    fn reserve_capacity(&mut self, capacity: usize);
    fn capacity(&self) -> usize;
    fn poll_capacity(&mut self) -> Poll<Option<usize>, h2::Error>;
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error>;
}

impl<B: IntoBuf> H2Stream<B> for h2c::Stream<B> {
    fn reserve_capacity(&mut self, capacity: usize) {
        h2c::Stream::reserve_capacity(self, capacity)
    }
    fn capacity(&self) -> usize {
        h2c::Stream::capacity(self)
    }
    fn poll_capacity(&mut self) -> Poll<Option<usize>, h2::Error> {
        h2c::Stream::poll_capacity(self)
    }
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error> {
        h2c::Stream::send_data(self, data, end_of_stream)
    }
}
impl<B: IntoBuf> H2Stream<B> for h2s::Stream<B> {
    fn reserve_capacity(&mut self, capacity: usize) {
        h2s::Stream::reserve_capacity(self, capacity)
    }
    fn capacity(&self) -> usize {
        h2s::Stream::capacity(self)
    }
    fn poll_capacity(&mut self) -> Poll<Option<usize>, h2::Error> {
        h2s::Stream::poll_capacity(self)
    }
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error> {
        h2s::Stream::send_data(self, data, end_of_stream)
    }
}

#[async]
pub fn copy_to_h2<R: AsyncRead + 'static, H: H2Stream<Bytes> + 'static>(
    mut src: R,
    mut dst: H,
) -> Result<usize, h2::Error> {
    let mut counter = 0;
    let mut buf = BytesMut::with_capacity(BUF_SIZE);
    loop {
        let n = poll!(src.read_buf(&mut buf))?;
        if n == 0 {
            dst.send_data(buf.take().freeze(), true)?;
            break;
        } else {
            loop {
                dst.reserve_capacity(buf.len());
                let cap = dst.capacity();
                if cap == 0 {
                    poll!(dst.poll_capacity())?; // TODO: handle value
                    continue;
                }
                let chunk = buf.split_to(cap).freeze();
                dst.send_data(chunk, false)?;
                if buf.is_empty() {
                    break;
                }
            }
        }
        counter += n;
        let rem = buf.remaining_mut();
        if rem < BUF_SIZE {
            buf.reserve(BUF_SIZE - rem);
        }
    }
    Ok(counter)
}

// This is a custom type used to have a custom implementation of the
// `AsyncWrite::shutdown` method which actually calls `TcpStream::shutdown` to
// notify the remote end that we're done writing.
#[derive(Clone)]
pub struct Socket(Rc<TcpStream>);

impl Socket {
    pub fn new(s: TcpStream) -> Socket {
        Socket(Rc::new(s))
    }
}

impl Read for Socket {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (&*self.0).read(buf)
    }
}

impl Write for Socket {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        (&*self.0).write(buf)
    }

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

impl AsyncRead for Socket {}

impl AsyncWrite for Socket {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        try!(self.0.shutdown(Shutdown::Write));
        Ok(().into())
    }
}

#[cfg(test)]
mod test {
    use std::io::Cursor;
    use std::rc::Rc;
    use std::cell::RefCell;

    use futures::prelude::*;
    use futures::stream::iter_ok;

    use super::*;

    #[derive(Clone)]
    struct Dst(Rc<RefCell<Cursor<Vec<u8>>>>);
    impl Write for Dst {
        fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
            self.0.borrow_mut().write(buf)
        }
        fn flush(&mut self) -> ::std::io::Result<()> {
            self.0.borrow_mut().flush()
        }
    }
    impl AsyncWrite for Dst {
        fn shutdown(&mut self) -> Poll<(), ::std::io::Error> {
            Ok(().into())
        }
    }
    impl H2Stream<Bytes> for Dst {
        fn reserve_capacity(&mut self, capacity: usize) {
            self.0.borrow_mut().get_mut().reserve(capacity)
        }
        fn capacity(&self) -> usize {
            self.0.borrow().get_ref().capacity()
        }
        fn poll_capacity(&mut self) -> Poll<Option<usize>, h2::Error> {
            Ok(Async::Ready(Some(self.capacity())))
        }
        fn send_data(&mut self, data: Bytes, _end_of_stream: bool) -> Result<(), h2::Error> {
            self.0.borrow_mut().get_mut().extend(data);
            Ok(())
        }
    }

    #[test]
    fn test_copy_from_h2() {
        let dst = Dst(Rc::new(RefCell::new(Cursor::new(Vec::new()))));
        let src = iter_ok(vec![
            Bytes::from("123"),
            Bytes::from("456"),
            Bytes::from("789"),
        ]);
        let r = copy_from_h2(src, dst.clone()).wait().unwrap();
        assert_eq!(r, 9);
        assert_eq!(dst.0.borrow().get_ref(), b"123456789");
    }

    #[test]
    fn test_copy_to_h2() {
        let dst = Dst(Rc::new(RefCell::new(Cursor::new(Vec::new()))));
        let src: &[u8] = b"123456789";
        let r = copy_to_h2(src, dst.clone()).wait().unwrap();
        assert_eq!(r, 9);
        assert_eq!(dst.0.borrow().get_ref(), b"123456789");
    }
}
<commit_msg>Fix 'assertion failed: end <= self.cap' at `copy_to_h2`<commit_after>use std::rc::Rc;
use std::io::{self, Read, Write};
use std::net::Shutdown;

use futures::prelude::*;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::io::shutdown;
use bytes::{BytesMut, Bytes, BufMut, IntoBuf};
use h2::{self, server as h2s, client as h2c};
use tokio_core::net::TcpStream;

const BUF_SIZE: usize = 2048;

#[async]
pub fn copy_from_h2<
    W: AsyncWrite + 'static,
    B: Stream<Item = Bytes, Error = h2::Error> + 'static,
>(
    src: B,
    mut dst: W,
) -> Result<usize, h2::Error> {
    let mut counter = 0;
    #[async]
    for buf in src {
        let mut buf = buf.into_buf();
        let n = poll!(dst.write_buf(&mut buf))?;
        counter += n;
    }
    await!(shutdown(dst))?;
    Ok(counter)
}

pub trait H2Stream<B: IntoBuf> {
    fn reserve_capacity(&mut self, capacity: usize);
    fn capacity(&self) -> usize;
    fn poll_capacity(&mut self) -> Poll<Option<usize>, h2::Error>;
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error>;
}

impl<B: IntoBuf> H2Stream<B> for h2c::Stream<B> {
    fn reserve_capacity(&mut self, capacity: usize) {
        h2c::Stream::reserve_capacity(self, capacity)
    }
    fn capacity(&self) -> usize {
        h2c::Stream::capacity(self)
    }
    fn poll_capacity(&mut self) -> Poll<Option<usize>, h2::Error> {
        h2c::Stream::poll_capacity(self)
    }
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error> {
        h2c::Stream::send_data(self, data, end_of_stream)
    }
}
impl<B: IntoBuf> H2Stream<B> for h2s::Stream<B> {
    fn reserve_capacity(&mut self, capacity: usize) {
        h2s::Stream::reserve_capacity(self, capacity)
    }
    fn capacity(&self) -> usize {
        h2s::Stream::capacity(self)
    }
    fn poll_capacity(&mut self) -> Poll<Option<usize>, h2::Error> {
        h2s::Stream::poll_capacity(self)
    }
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error> {
        h2s::Stream::send_data(self, data, end_of_stream)
    }
}

#[async]
pub fn copy_to_h2<R: AsyncRead + 'static, H: H2Stream<Bytes> + 'static>(
    mut src: R,
    mut dst: H,
) -> Result<usize, h2::Error> {
    let mut counter = 0;
    let mut buf = BytesMut::with_capacity(BUF_SIZE);
    loop {
        let n = poll!(src.read_buf(&mut buf))?;
        if n == 0 {
            dst.send_data(buf.take().freeze(), true)?;
            break;
        } else {
            loop {
                let dst_cap = dst.capacity();
                let src_len = buf.len();
                if src_len > dst_cap {
                    dst.reserve_capacity(src_len);
                    if dst_cap == 0 {
                        poll!(dst.poll_capacity())?; // TODO: handle value
                        continue;
                    }
                    let chunk = buf.split_to(dst_cap).freeze();
                    dst.send_data(chunk, false)?;
                } else {
                    dst.send_data(buf.take().freeze(), false)?;
                }
                if buf.is_empty() {
                    break;
                }
            }
        }
        counter += n;
        let rem = buf.remaining_mut();
        if rem < BUF_SIZE {
            buf.reserve(BUF_SIZE - rem);
        }
    }
    Ok(counter)
}

// This is a custom type used to have a custom implementation of the
// `AsyncWrite::shutdown` method which actually calls `TcpStream::shutdown` to
// notify the remote end that we're done writing.
#[derive(Clone)]
pub struct Socket(Rc<TcpStream>);

impl Socket {
    pub fn new(s: TcpStream) -> Socket {
        Socket(Rc::new(s))
    }
}

impl Read for Socket {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (&*self.0).read(buf)
    }
}

impl Write for Socket {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        (&*self.0).write(buf)
    }

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

impl AsyncRead for Socket {}

impl AsyncWrite for Socket {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        try!(self.0.shutdown(Shutdown::Write));
        Ok(().into())
    }
}

#[cfg(test)]
mod test {
    use std::io::Cursor;
    use std::rc::Rc;
    use std::cell::RefCell;

    use futures::prelude::*;
    use futures::stream::iter_ok;

    use super::*;

    #[derive(Clone)]
    struct Dst(Rc<RefCell<Cursor<Vec<u8>>>>);
    impl Write for Dst {
        fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
            self.0.borrow_mut().write(buf)
        }
        fn flush(&mut self) -> ::std::io::Result<()> {
            self.0.borrow_mut().flush()
        }
    }
    impl AsyncWrite for Dst {
        fn shutdown(&mut self) -> Poll<(), ::std::io::Error> {
            Ok(().into())
        }
    }
    impl H2Stream<Bytes> for Dst {
        fn reserve_capacity(&mut self, capacity: usize) {
            self.0.borrow_mut().get_mut().reserve(capacity)
        }
        fn capacity(&self) -> usize {
            self.0.borrow().get_ref().capacity()
        }
        fn poll_capacity(&mut self) -> Poll<Option<usize>, h2::Error> {
            Ok(Async::Ready(Some(self.capacity())))
        }
        fn send_data(&mut self, data: Bytes, _end_of_stream: bool) -> Result<(), h2::Error> {
            self.0.borrow_mut().get_mut().extend(data);
            Ok(())
        }
    }

    #[test]
    fn test_copy_from_h2() {
        let dst = Dst(Rc::new(RefCell::new(Cursor::new(Vec::new()))));
        let src = iter_ok(vec![
            Bytes::from("123"),
            Bytes::from("456"),
            Bytes::from("789"),
        ]);
        let r = copy_from_h2(src, dst.clone()).wait().unwrap();
        assert_eq!(r, 9);
        assert_eq!(dst.0.borrow().get_ref(), b"123456789");

        let data: &[u8] = &[0; BUF_SIZE * 2];
        let dst = Dst(Rc::new(RefCell::new(Cursor::new(Vec::new()))));
        let src = iter_ok(vec![Bytes::from(data)]);
        let r = copy_from_h2(src, dst.clone()).wait().unwrap();
        assert_eq!(r, data.len());
        assert_eq!(dst.0.borrow().get_ref().as_slice(), data);
    }

    #[test]
    fn test_copy_to_h2() {
        let dst = Dst(Rc::new(RefCell::new(Cursor::new(Vec::new()))));
        let src: &[u8] = b"123456789";
        let r = copy_to_h2(src, dst.clone()).wait().unwrap();
        assert_eq!(r, 9);
        assert_eq!(dst.0.borrow().get_ref(), b"123456789");

        let data: &[u8] = &[0; BUF_SIZE * 2];
        let dst = Dst(Rc::new(RefCell::new(Cursor::new(Vec::new()))));
        let src: &[u8] = data;
        let r = copy_to_h2(src, dst.clone()).wait().unwrap();
        assert_eq!(r, data.len());
        assert_eq!(dst.0.borrow().get_ref().as_slice(), data);
    }
}
<|endoftext|>


<commit_before>const JS_DOM_EVENT_ATTRS: &[&str] = &[
    // Input
    "onfocus",
    "onblur",
    "onselect",
    "onchange",
    "onsubmit",
    "onreset",
    "onkeydown",
    "onkeypress",
    "onkeyup",
    // Mouse
    "onmouseover",
    "onmouseout",
    "onmousedown",
    "onmouseup",
    "onmousemove",
    // Click
    "onclick",
    "ondblclick",
    // Load
    "onload",
    "onunload",
    "onabort",
    "onerror",
    "onresize",
];

// Returns true if DOM attribute name matches a native JavaScript event handler
pub fn attr_is_event_handler(attr_name: &str) -> bool {
    JS_DOM_EVENT_ATTRS
        .iter()
        .find(|a| attr_name.eq_ignore_ascii_case(a))
        .is_some()
}
<commit_msg>use complete list of DOM event handlers<commit_after>const JS_DOM_EVENT_ATTRS: &[&str] = &[
    // From WhatWG HTML spec 8.1.5.2 Event handlers on elements, Document objects, and Window objects:
    //   https://html.spec.whatwg.org/#event-handlers-on-elements,-document-objects,-and-window-objects
    //   https://html.spec.whatwg.org/#attributes-3 (table 'List of event handler content attributes')

    // Global handlers
    "onabort",
    "onauxclick",
    "onblur",
    "oncancel",
    "oncanplay",
    "oncanplaythrough",
    "onchange",
    "onclick",
    "onclose",
    "oncontextmenu",
    "oncuechange",
    "ondblclick",
    "ondrag",
    "ondragend",
    "ondragenter",
    "ondragexit",
    "ondragleave",
    "ondragover",
    "ondragstart",
    "ondrop",
    "ondurationchange",
    "onemptied",
    "onended",
    "onerror",
    "onfocus",
    "onformdata",
    "oninput",
    "oninvalid",
    "onkeydown",
    "onkeypress",
    "onkeyup",
    "onload",
    "onloadeddata",
    "onloadedmetadata",
    "onloadstart",
    "onmousedown",
    "onmouseenter",
    "onmouseleave",
    "onmousemove",
    "onmouseout",
    "onmouseover",
    "onmouseup",
    "onwheel",
    "onpause",
    "onplay",
    "onplaying",
    "onprogress",
    "onratechange",
    "onreset",
    "onresize",
    "onscroll",
    "onsecuritypolicyviolation",
    "onseeked",
    "onseeking",
    "onselect",
    "onslotchange",
    "onstalled",
    "onsubmit",
    "onsuspend",
    "ontimeupdate",
    "ontoggle",
    "onvolumechange",
    "onwaiting",
    "onwebkitanimationend",
    "onwebkitanimationiteration",
    "onwebkitanimationstart",
    "onwebkittransitionend",
    // body and frameset elements
    "onafterprint",
    "onbeforeprint",
    "onbeforeunload",
    "onhashchange",
    "onlanguagechange",
    "onmessage",
    "onmessageerror",
    "onoffline",
    "ononline",
    "onpagehide",
    "onpageshow",
    "onpopstate",
    "onrejectionhandled",
    "onstorage",
    "onunhandledrejection",
    "onunload",
    // html element
    "oncut",
    "oncopy",
    "onpaste",
];

// Returns true if DOM attribute name matches a native JavaScript event handler
pub fn attr_is_event_handler(attr_name: &str) -> bool {
    JS_DOM_EVENT_ATTRS
        .iter()
        .find(|a| attr_name.eq_ignore_ascii_case(a))
        .is_some()
}
<|endoftext|>


<commit_before>//! Allocator shim
// Adapted from rustc

use crate::prelude::*;

use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
use rustc_span::symbol::sym;

/// Returns whether an allocator shim was created
pub(crate) fn codegen(
    tcx: TyCtxt<'_>,
    module: &mut impl Module,
    unwind_context: &mut UnwindContext,
) -> bool {
    let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| {
        use rustc_middle::middle::dependency_format::Linkage;
        list.iter().any(|&linkage| linkage == Linkage::Dynamic)
    });
    if any_dynamic_crate {
        false
    } else if let Some(kind) = tcx.allocator_kind() {
        codegen_inner(module, unwind_context, kind);
        true
    } else {
        false
    }
}

fn codegen_inner(
    module: &mut impl Module,
    unwind_context: &mut UnwindContext,
    kind: AllocatorKind,
) {
    let usize_ty = module.target_config().pointer_type();

    for method in ALLOCATOR_METHODS {
        let mut arg_tys = Vec::with_capacity(method.inputs.len());
        for ty in method.inputs.iter() {
            match *ty {
                AllocatorTy::Layout => {
                    arg_tys.push(usize_ty); // size
                    arg_tys.push(usize_ty); // align
                }
                AllocatorTy::Ptr => arg_tys.push(usize_ty),
                AllocatorTy::Usize => arg_tys.push(usize_ty),

                AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
            }
        }
        let output = match method.output {
            AllocatorTy::ResultPtr => Some(usize_ty),
            AllocatorTy::Unit => None,

            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
                panic!("invalid allocator output")
            }
        };

        let sig = Signature {
            call_conv: CallConv::triple_default(module.isa().triple()),
            params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
            returns: output.into_iter().map(AbiParam::new).collect(),
        };

        let caller_name = format!("__rust_{}", method.name);
        let callee_name = kind.fn_name(method.name);
        //eprintln!("Codegen allocator shim {} -> {} ({:?} -> {:?})", caller_name, callee_name, sig.params, sig.returns);

        let func_id = module.declare_function(&caller_name, Linkage::Export, &sig).unwrap();

        let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap();

        let mut ctx = Context::new();
        ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig.clone());
        {
            let mut func_ctx = FunctionBuilderContext::new();
            let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);

            let block = bcx.create_block();
            bcx.switch_to_block(block);
            let args = arg_tys
                .into_iter()
                .map(|ty| bcx.append_block_param(block, ty))
                .collect::<Vec<Value>>();

            let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);
            let call_inst = bcx.ins().call(callee_func_ref, &args);
            let results = bcx.inst_results(call_inst).to_vec(); // Clone to prevent borrow error

            bcx.ins().return_(&results);
            bcx.seal_all_blocks();
            bcx.finalize();
        }
        module
            .define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
            .unwrap();
        unwind_context.add_function(func_id, &ctx, module.isa());
    }

    let sig = Signature {
        call_conv: CallConv::triple_default(module.isa().triple()),
        params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
        returns: vec![],
    };

    let callee_name = kind.fn_name(sym::oom);
    //eprintln!("Codegen allocator shim {} -> {} ({:?} -> {:?})", caller_name, callee_name, sig.params, sig.returns);

    let func_id =
        module.declare_function("__rust_alloc_error_handler", Linkage::Export, &sig).unwrap();

    let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap();

    let mut ctx = Context::new();
    ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig);
    {
        let mut func_ctx = FunctionBuilderContext::new();
        let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);

        let block = bcx.create_block();
        bcx.switch_to_block(block);
        let args = (&[usize_ty, usize_ty])
            .iter()
            .map(|&ty| bcx.append_block_param(block, ty))
            .collect::<Vec<Value>>();

        let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);
        bcx.ins().call(callee_func_ref, &args);

        bcx.ins().trap(TrapCode::UnreachableCodeReached);
        bcx.seal_all_blocks();
        bcx.finalize();
    }
    module
        .define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
        .unwrap();
    unwind_context.add_function(func_id, &ctx, module.isa());
}
<commit_msg>Make allocator_kind a query.<commit_after>//! Allocator shim
// Adapted from rustc

use crate::prelude::*;

use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
use rustc_span::symbol::sym;

/// Returns whether an allocator shim was created
pub(crate) fn codegen(
    tcx: TyCtxt<'_>,
    module: &mut impl Module,
    unwind_context: &mut UnwindContext,
) -> bool {
    let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| {
        use rustc_middle::middle::dependency_format::Linkage;
        list.iter().any(|&linkage| linkage == Linkage::Dynamic)
    });
    if any_dynamic_crate {
        false
    } else if let Some(kind) = tcx.allocator_kind(()) {
        codegen_inner(module, unwind_context, kind);
        true
    } else {
        false
    }
}

fn codegen_inner(
    module: &mut impl Module,
    unwind_context: &mut UnwindContext,
    kind: AllocatorKind,
) {
    let usize_ty = module.target_config().pointer_type();

    for method in ALLOCATOR_METHODS {
        let mut arg_tys = Vec::with_capacity(method.inputs.len());
        for ty in method.inputs.iter() {
            match *ty {
                AllocatorTy::Layout => {
                    arg_tys.push(usize_ty); // size
                    arg_tys.push(usize_ty); // align
                }
                AllocatorTy::Ptr => arg_tys.push(usize_ty),
                AllocatorTy::Usize => arg_tys.push(usize_ty),

                AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
            }
        }
        let output = match method.output {
            AllocatorTy::ResultPtr => Some(usize_ty),
            AllocatorTy::Unit => None,

            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
                panic!("invalid allocator output")
            }
        };

        let sig = Signature {
            call_conv: CallConv::triple_default(module.isa().triple()),
            params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
            returns: output.into_iter().map(AbiParam::new).collect(),
        };

        let caller_name = format!("__rust_{}", method.name);
        let callee_name = kind.fn_name(method.name);
        //eprintln!("Codegen allocator shim {} -> {} ({:?} -> {:?})", caller_name, callee_name, sig.params, sig.returns);

        let func_id = module.declare_function(&caller_name, Linkage::Export, &sig).unwrap();

        let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap();

        let mut ctx = Context::new();
        ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig.clone());
        {
            let mut func_ctx = FunctionBuilderContext::new();
            let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);

            let block = bcx.create_block();
            bcx.switch_to_block(block);
            let args = arg_tys
                .into_iter()
                .map(|ty| bcx.append_block_param(block, ty))
                .collect::<Vec<Value>>();

            let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);
            let call_inst = bcx.ins().call(callee_func_ref, &args);
            let results = bcx.inst_results(call_inst).to_vec(); // Clone to prevent borrow error

            bcx.ins().return_(&results);
            bcx.seal_all_blocks();
            bcx.finalize();
        }
        module
            .define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
            .unwrap();
        unwind_context.add_function(func_id, &ctx, module.isa());
    }

    let sig = Signature {
        call_conv: CallConv::triple_default(module.isa().triple()),
        params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
        returns: vec![],
    };

    let callee_name = kind.fn_name(sym::oom);
    //eprintln!("Codegen allocator shim {} -> {} ({:?} -> {:?})", caller_name, callee_name, sig.params, sig.returns);

    let func_id =
        module.declare_function("__rust_alloc_error_handler", Linkage::Export, &sig).unwrap();

    let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap();

    let mut ctx = Context::new();
    ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig);
    {
        let mut func_ctx = FunctionBuilderContext::new();
        let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);

        let block = bcx.create_block();
        bcx.switch_to_block(block);
        let args = (&[usize_ty, usize_ty])
            .iter()
            .map(|&ty| bcx.append_block_param(block, ty))
            .collect::<Vec<Value>>();

        let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);
        bcx.ins().call(callee_func_ref, &args);

        bcx.ins().trap(TrapCode::UnreachableCodeReached);
        bcx.seal_all_blocks();
        bcx.finalize();
    }
    module
        .define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
        .unwrap();
    unwind_context.add_function(func_id, &ctx, module.isa());
}
<|endoftext|>