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

//! Generic implementations of some DOM APIs so they can be shared between Servo
//! and Gecko.

use context::QuirksMode;
use dom::{TElement, TNode};
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
use selectors::{Element, NthIndexCache, SelectorList};
use selectors::matching::{self, MatchingContext, MatchingMode};
use smallvec::SmallVec;

/// <https://dom.spec.whatwg.org/#dom-element-matches>
pub fn element_matches<E>(
    element: &E,
    selector_list: &SelectorList<E::Impl>,
    quirks_mode: QuirksMode,
) -> bool
where
    E: Element,
{
    let mut context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        None,
        quirks_mode,
    );
    context.scope_element = Some(element.opaque());
    matching::matches_selector_list(selector_list, element, &mut context)
}

/// <https://dom.spec.whatwg.org/#dom-element-closest>
pub fn element_closest<E>(
    element: E,
    selector_list: &SelectorList<E::Impl>,
    quirks_mode: QuirksMode,
) -> Option<E>
where
    E: Element,
{
    let mut nth_index_cache = NthIndexCache::default();

    let mut context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        Some(&mut nth_index_cache),
        quirks_mode,
    );
    context.scope_element = Some(element.opaque());

    let mut current = Some(element);
    while let Some(element) = current.take() {
        if matching::matches_selector_list(selector_list, &element, &mut context) {
            return Some(element);
        }
        current = element.parent_element();
    }

    return None;
}

/// A selector query abstraction, in order to be generic over QuerySelector and
/// QuerySelectorAll.
pub trait SelectorQuery<E: TElement> {
    /// The output of the query.
    type Output;

    /// Whether the query should stop after the first element has been matched.
    fn should_stop_after_first_match() -> bool;

    /// Append an element matching after the first query.
    fn append_element(output: &mut Self::Output, element: E);

    /// Returns true if the output is empty.
    fn is_empty(output: &Self::Output) -> bool;
}

/// The result of a querySelectorAll call.
pub type QuerySelectorAllResult<E> = SmallVec<[E; 128]>;

/// A query for all the elements in a subtree.
pub struct QueryAll;

impl<E: TElement> SelectorQuery<E> for QueryAll {
    type Output = QuerySelectorAllResult<E>;

    fn should_stop_after_first_match() -> bool { false }

    fn append_element(output: &mut Self::Output, element: E) {
        output.push(element);
    }

    fn is_empty(output: &Self::Output) -> bool {
        output.is_empty()
    }
}

/// A query for the first in-tree match of all the elements in a subtree.
pub struct QueryFirst;

impl<E: TElement> SelectorQuery<E> for QueryFirst {
    type Output = Option<E>;

    fn should_stop_after_first_match() -> bool { true }

    fn append_element(output: &mut Self::Output, element: E) {
        if output.is_none() {
            *output = Some(element)
        }
    }

    fn is_empty(output: &Self::Output) -> bool {
        output.is_none()
    }
}

struct QuerySelectorProcessor<'a, E, Q>
where
    E: TElement + 'a,
    Q: SelectorQuery<E>,
    Q::Output: 'a,
{
    results: &'a mut Q::Output,
    matching_context: MatchingContext<'a, E::Impl>,
    selector_list: &'a SelectorList<E::Impl>,
}

impl<'a, E, Q> InvalidationProcessor<'a, E> for QuerySelectorProcessor<'a, E, Q>
where
    E: TElement + 'a,
    Q: SelectorQuery<E>,
    Q::Output: 'a,
{
    fn collect_invalidations(
        &mut self,
        element: E,
        self_invalidations: &mut InvalidationVector<'a>,
        descendant_invalidations: &mut InvalidationVector<'a>,
        _sibling_invalidations: &mut InvalidationVector<'a>,
    ) -> bool {
        // TODO(emilio): If the element is not a root element, and
        // selector_list has any descendant combinator, we need to do extra work
        // in order to handle properly things like:
        //
        //

        //

        //

        //

        //

        //
        // b.querySelector('#a div'); // Should return "c".
        //
        // For now, assert it's a root element.
        debug_assert!(element.parent_element().is_none());

        let target_vector =
            if self.matching_context.scope_element.is_some() {
                descendant_invalidations
            } else {
                self_invalidations
            };

        for selector in self.selector_list.0.iter() {
            target_vector.push(Invalidation::new(selector, 0))
        }

        false
    }

    fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
        &mut self.matching_context
    }

    fn should_process_descendants(&mut self, _: E) -> bool {
        if Q::should_stop_after_first_match() {
            return Q::is_empty(&self.results)
        }

        true
    }

    fn invalidated_self(&mut self, e: E) {
        Q::append_element(self.results, e);
    }

    fn recursion_limit_exceeded(&mut self, _e: E) {}
    fn invalidated_descendants(&mut self, _e: E, _child: E) {}
}

fn collect_all_elements<E, Q, F>(
    root: E::ConcreteNode,
    results: &mut Q::Output,
    mut filter: F,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
    F: FnMut(E) -> bool,
{
    for node in root.dom_descendants() {
        let element = match node.as_element() {
            Some(e) => e,
            None => continue,
        };

        if !filter(element) {
            continue;
        }

        Q::append_element(results, element);
        if Q::should_stop_after_first_match() {
            return;
        }
    }
}

/// Fast paths for a given selector query.
///
/// FIXME(emilio, nbp): This may very well be a good candidate for code to be
/// replaced by HolyJit :)
fn query_selector_fast<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
    quirks_mode: QuirksMode,
) -> Result<(), ()>
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    use selectors::parser::{Component, LocalName};
    use std::borrow::Borrow;

    // We need to return elements in document order, and reordering them
    // afterwards is kinda silly.
    if selector_list.0.len() > 1 {
        return Err(());
    }

    let selector = &selector_list.0[0];

    // Let's just care about the easy cases for now.
    //
    // FIXME(emilio): Blink has a fast path for classes in ancestor combinators
    // that may be worth stealing.
    if selector.len() > 1 {
        return Err(());
    }

    let component = selector.iter().next().unwrap();
    match *component {
        Component::ExplicitUniversalType => {
            collect_all_elements::<E, Q, _>(root, results, |_| true)
        }
        Component::ID(ref id) => {
            // TODO(emilio): We may want to reuse Gecko's document ID table.
            let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
            collect_all_elements::<E, Q, _>(root, results, |element| {
                element.has_id(id, case_sensitivity)
            })
        }
        Component::Class(ref class) => {
            let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
            collect_all_elements::<E, Q, _>(root, results, |element| {
                element.has_class(class, case_sensitivity)
            })
        }
        Component::LocalName(LocalName { ref name, ref lower_name }) => {
            collect_all_elements::<E, Q, _>(root, results, |element| {
                if element.is_html_element_in_html_document() {
                    element.get_local_name() == lower_name.borrow()
                } else {
                    element.get_local_name() == name.borrow()
                }
            })
        }
        // TODO(emilio): More fast paths?
        _ => {
            return Err(())
        }
    }

    Ok(())
}

// Slow path for a given selector query.
fn query_selector_slow<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
    matching_context: &mut MatchingContext<E::Impl>,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    collect_all_elements::<E, Q, _>(root, results, |element| {
        matching::matches_selector_list(selector_list, &element, matching_context)
    });
}

/// <https://dom.spec.whatwg.org/#dom-parentnode-queryselector>
pub fn query_selector<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
    quirks_mode: QuirksMode,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    use invalidation::element::invalidator::TreeStyleInvalidator;

    let fast_result = query_selector_fast::<E, Q>(
        root,
        selector_list,
        results,
        quirks_mode,
    );

    if fast_result.is_ok() {
        return;
    }

    // Slow path: Use the invalidation machinery if we're a root, and tree
    // traversal otherwise.
    //
    // See the comment in collect_invalidations to see why only if we're a root.
    let mut nth_index_cache = NthIndexCache::default();
    let mut matching_context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        Some(&mut nth_index_cache),
        quirks_mode,
    );

    let root_element = root.as_element();
    matching_context.scope_element = root_element.map(|e| e.opaque());

    if root_element.is_some() {
        query_selector_slow::<E, Q>(
            root,
            selector_list,
            results,
            &mut matching_context,
        );
    } else {
        let mut processor = QuerySelectorProcessor::<E, Q> {
            results,
            matching_context,
            selector_list,
        };

        for node in root.dom_children() {
            if let Some(e) = node.as_element() {
                TreeStyleInvalidator::new(
                    e,
                    /* stack_limit_checker = */ None,
                    &mut processor,
                ).invalidate();
            }
        }
    }
}
<commit_msg>style: Don't use the invalidation machinery unless we may get some benefit from it.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Generic implementations of some DOM APIs so they can be shared between Servo
//! and Gecko.

use context::QuirksMode;
use dom::{TElement, TNode};
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
use selectors::{Element, NthIndexCache, SelectorList};
use selectors::matching::{self, MatchingContext, MatchingMode};
use smallvec::SmallVec;

/// <https://dom.spec.whatwg.org/#dom-element-matches>
pub fn element_matches<E>(
    element: &E,
    selector_list: &SelectorList<E::Impl>,
    quirks_mode: QuirksMode,
) -> bool
where
    E: Element,
{
    let mut context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        None,
        quirks_mode,
    );
    context.scope_element = Some(element.opaque());
    matching::matches_selector_list(selector_list, element, &mut context)
}

/// <https://dom.spec.whatwg.org/#dom-element-closest>
pub fn element_closest<E>(
    element: E,
    selector_list: &SelectorList<E::Impl>,
    quirks_mode: QuirksMode,
) -> Option<E>
where
    E: Element,
{
    let mut nth_index_cache = NthIndexCache::default();

    let mut context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        Some(&mut nth_index_cache),
        quirks_mode,
    );
    context.scope_element = Some(element.opaque());

    let mut current = Some(element);
    while let Some(element) = current.take() {
        if matching::matches_selector_list(selector_list, &element, &mut context) {
            return Some(element);
        }
        current = element.parent_element();
    }

    return None;
}

/// A selector query abstraction, in order to be generic over QuerySelector and
/// QuerySelectorAll.
pub trait SelectorQuery<E: TElement> {
    /// The output of the query.
    type Output;

    /// Whether the query should stop after the first element has been matched.
    fn should_stop_after_first_match() -> bool;

    /// Append an element matching after the first query.
    fn append_element(output: &mut Self::Output, element: E);

    /// Returns true if the output is empty.
    fn is_empty(output: &Self::Output) -> bool;
}

/// The result of a querySelectorAll call.
pub type QuerySelectorAllResult<E> = SmallVec<[E; 128]>;

/// A query for all the elements in a subtree.
pub struct QueryAll;

impl<E: TElement> SelectorQuery<E> for QueryAll {
    type Output = QuerySelectorAllResult<E>;

    fn should_stop_after_first_match() -> bool { false }

    fn append_element(output: &mut Self::Output, element: E) {
        output.push(element);
    }

    fn is_empty(output: &Self::Output) -> bool {
        output.is_empty()
    }
}

/// A query for the first in-tree match of all the elements in a subtree.
pub struct QueryFirst;

impl<E: TElement> SelectorQuery<E> for QueryFirst {
    type Output = Option<E>;

    fn should_stop_after_first_match() -> bool { true }

    fn append_element(output: &mut Self::Output, element: E) {
        if output.is_none() {
            *output = Some(element)
        }
    }

    fn is_empty(output: &Self::Output) -> bool {
        output.is_none()
    }
}

struct QuerySelectorProcessor<'a, E, Q>
where
    E: TElement + 'a,
    Q: SelectorQuery<E>,
    Q::Output: 'a,
{
    results: &'a mut Q::Output,
    matching_context: MatchingContext<'a, E::Impl>,
    selector_list: &'a SelectorList<E::Impl>,
}

impl<'a, E, Q> InvalidationProcessor<'a, E> for QuerySelectorProcessor<'a, E, Q>
where
    E: TElement + 'a,
    Q: SelectorQuery<E>,
    Q::Output: 'a,
{
    fn collect_invalidations(
        &mut self,
        element: E,
        self_invalidations: &mut InvalidationVector<'a>,
        descendant_invalidations: &mut InvalidationVector<'a>,
        _sibling_invalidations: &mut InvalidationVector<'a>,
    ) -> bool {
        // TODO(emilio): If the element is not a root element, and
        // selector_list has any descendant combinator, we need to do extra work
        // in order to handle properly things like:
        //
        //

        //

        //

        //

        //

        //
        // b.querySelector('#a div'); // Should return "c".
        //
        // For now, assert it's a root element.
        debug_assert!(element.parent_element().is_none());

        let target_vector =
            if self.matching_context.scope_element.is_some() {
                descendant_invalidations
            } else {
                self_invalidations
            };

        for selector in self.selector_list.0.iter() {
            target_vector.push(Invalidation::new(selector, 0))
        }

        false
    }

    fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
        &mut self.matching_context
    }

    fn should_process_descendants(&mut self, _: E) -> bool {
        if Q::should_stop_after_first_match() {
            return Q::is_empty(&self.results)
        }

        true
    }

    fn invalidated_self(&mut self, e: E) {
        Q::append_element(self.results, e);
    }

    fn recursion_limit_exceeded(&mut self, _e: E) {}
    fn invalidated_descendants(&mut self, _e: E, _child: E) {}
}

fn collect_all_elements<E, Q, F>(
    root: E::ConcreteNode,
    results: &mut Q::Output,
    mut filter: F,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
    F: FnMut(E) -> bool,
{
    for node in root.dom_descendants() {
        let element = match node.as_element() {
            Some(e) => e,
            None => continue,
        };

        if !filter(element) {
            continue;
        }

        Q::append_element(results, element);
        if Q::should_stop_after_first_match() {
            return;
        }
    }
}

/// Fast paths for a given selector query.
///
/// FIXME(emilio, nbp): This may very well be a good candidate for code to be
/// replaced by HolyJit :)
fn query_selector_fast<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
    quirks_mode: QuirksMode,
) -> Result<(), ()>
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    use selectors::parser::{Component, LocalName};
    use std::borrow::Borrow;

    // We need to return elements in document order, and reordering them
    // afterwards is kinda silly.
    if selector_list.0.len() > 1 {
        return Err(());
    }

    let selector = &selector_list.0[0];

    // Let's just care about the easy cases for now.
    //
    // FIXME(emilio): Blink has a fast path for classes in ancestor combinators
    // that may be worth stealing.
    if selector.len() > 1 {
        return Err(());
    }

    let component = selector.iter().next().unwrap();
    match *component {
        Component::ExplicitUniversalType => {
            collect_all_elements::<E, Q, _>(root, results, |_| true)
        }
        Component::ID(ref id) => {
            // TODO(emilio): We may want to reuse Gecko's document ID table.
            let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
            collect_all_elements::<E, Q, _>(root, results, |element| {
                element.has_id(id, case_sensitivity)
            })
        }
        Component::Class(ref class) => {
            let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
            collect_all_elements::<E, Q, _>(root, results, |element| {
                element.has_class(class, case_sensitivity)
            })
        }
        Component::LocalName(LocalName { ref name, ref lower_name }) => {
            collect_all_elements::<E, Q, _>(root, results, |element| {
                if element.is_html_element_in_html_document() {
                    element.get_local_name() == lower_name.borrow()
                } else {
                    element.get_local_name() == name.borrow()
                }
            })
        }
        // TODO(emilio): More fast paths?
        _ => {
            return Err(())
        }
    }

    Ok(())
}

// Slow path for a given selector query.
fn query_selector_slow<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
    matching_context: &mut MatchingContext<E::Impl>,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    collect_all_elements::<E, Q, _>(root, results, |element| {
        matching::matches_selector_list(selector_list, &element, matching_context)
    });
}

/// <https://dom.spec.whatwg.org/#dom-parentnode-queryselector>
pub fn query_selector<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
    quirks_mode: QuirksMode,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    use invalidation::element::invalidator::TreeStyleInvalidator;

    let fast_result = query_selector_fast::<E, Q>(
        root,
        selector_list,
        results,
        quirks_mode,
    );

    if fast_result.is_ok() {
        return;
    }

    // Slow path: Use the invalidation machinery if we're a root, and tree
    // traversal otherwise.
    //
    // See the comment in collect_invalidations to see why only if we're a root.
    let mut nth_index_cache = NthIndexCache::default();
    let mut matching_context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        Some(&mut nth_index_cache),
        quirks_mode,
    );

    let root_element = root.as_element();
    matching_context.scope_element = root_element.map(|e| e.opaque());

    // The invalidation mechanism is only useful in presence of combinators.
    //
    // We could do that check properly here, though checking the length of the
    // selectors is a good heuristic.
    let invalidation_may_be_useful =
        selector_list.0.iter().any(|s| s.len() > 1);

    if root_element.is_some() || !invalidation_may_be_useful {
        query_selector_slow::<E, Q>(
            root,
            selector_list,
            results,
            &mut matching_context,
        );
    } else {
        let mut processor = QuerySelectorProcessor::<E, Q> {
            results,
            matching_context,
            selector_list,
        };

        for node in root.dom_children() {
            if let Some(e) = node.as_element() {
                TreeStyleInvalidator::new(
                    e,
                    /* stack_limit_checker = */ None,
                    &mut processor,
                ).invalidate();
            }
        }
    }
}
<|endoftext|>


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

// ensures that public symbols are not removed completely
#![crate_type = "lib"]
// we can compile to a variety of platforms, because we don't need
// cross-compiled standard libraries.
#![feature(no_core)]
#![no_core]

#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items)]

#[repr(C)]
#[derive(Copy)]
#[repr(simd)]
pub struct f32x4(f32, f32, f32, f32);

extern {
    #[link_name = "llvm.sqrt.v4f32"]
    fn vsqrt(x: f32x4) -> f32x4;
}

pub fn foo(x: f32x4) -> f32x4 {
    unsafe {vsqrt(x)}
}

#[repr(C)]
#[derive(Copy)]
#[repr(simd)]
pub struct i32x4(i32, i32, i32, i32);

extern {
    // _mm_sll_epi32
    #[cfg(any(target_arch = "x86",
              target_arch = "x86-64"))]
    #[link_name = "llvm.x86.sse2.psll.d"]
    fn integer(a: i32x4, b: i32x4) -> i32x4;

    // vmaxq_s32
    #[cfg(any(target_arch = "arm"))]
    #[link_name = "llvm.arm.neon.vmaxs.v4i32"]
    fn integer(a: i32x4, b: i32x4) -> i32x4;
    // vmaxq_s32
    #[cfg(any(target_arch = "aarch64"))]
    #[link_name = "llvm.aarch64.neon.maxs.v4i32"]
    fn integer(a: i32x4, b: i32x4) -> i32x4;

    // just some substitute foreign symbol, not an LLVM intrinsic; so
    // we still get type checking, but not as detailed as (ab)using
    // LLVM.
    #[cfg(not(any(target_arch = "x86",
                  target_arch = "x86-64",
                  target_arch = "arm",
                  target_arch = "aarch64")))]
    fn integer(a: i32x4, b: i32x4) -> i32x4;
}

pub fn bar(a: i32x4, b: i32x4) -> i32x4 {
    unsafe {integer(a, b)}
}

#[lang = "sized"]
pub trait Sized { }

#[lang = "copy"]
pub trait Copy { }

pub mod marker {
    pub use Copy;
}
<commit_msg>Simply two cfg attributes<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ensures that public symbols are not removed completely
#![crate_type = "lib"]
// we can compile to a variety of platforms, because we don't need
// cross-compiled standard libraries.
#![feature(no_core)]
#![no_core]

#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items)]

#[repr(C)]
#[derive(Copy)]
#[repr(simd)]
pub struct f32x4(f32, f32, f32, f32);

extern {
    #[link_name = "llvm.sqrt.v4f32"]
    fn vsqrt(x: f32x4) -> f32x4;
}

pub fn foo(x: f32x4) -> f32x4 {
    unsafe {vsqrt(x)}
}

#[repr(C)]
#[derive(Copy)]
#[repr(simd)]
pub struct i32x4(i32, i32, i32, i32);

extern {
    // _mm_sll_epi32
    #[cfg(any(target_arch = "x86",
              target_arch = "x86-64"))]
    #[link_name = "llvm.x86.sse2.psll.d"]
    fn integer(a: i32x4, b: i32x4) -> i32x4;

    // vmaxq_s32
    #[cfg(target_arch = "arm")]
    #[link_name = "llvm.arm.neon.vmaxs.v4i32"]
    fn integer(a: i32x4, b: i32x4) -> i32x4;
    // vmaxq_s32
    #[cfg(target_arch = "aarch64")]
    #[link_name = "llvm.aarch64.neon.maxs.v4i32"]
    fn integer(a: i32x4, b: i32x4) -> i32x4;

    // just some substitute foreign symbol, not an LLVM intrinsic; so
    // we still get type checking, but not as detailed as (ab)using
    // LLVM.
    #[cfg(not(any(target_arch = "x86",
                  target_arch = "x86-64",
                  target_arch = "arm",
                  target_arch = "aarch64")))]
    fn integer(a: i32x4, b: i32x4) -> i32x4;
}

pub fn bar(a: i32x4, b: i32x4) -> i32x4 {
    unsafe {integer(a, b)}
}

#[lang = "sized"]
pub trait Sized { }

#[lang = "copy"]
pub trait Copy { }

pub mod marker {
    pub use Copy;
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use structopt::StructOpt;

fn part1(tape: &[isize]) -> isize {
    let output = intcode::Interpreter::new(tape.to_vec())
        .with_input(&[1])
        .run()
        .unwrap_or_else(|err| panic!("Error running intcode: {:?}", err));
    let (final_result, test_results) = output.output().split_last().expect("No output produced");
    for res in test_results {
        assert_eq!(*res, 0, "test failed with output: {}", res);
    }
    *final_result
}

fn main() {
    let input: Vec<_> = std::fs::read_to_string(Opt::from_args().input)
        .expect("error reading file")
        .split(',')
        .map(|num| {
            num.trim()
                .parse::<isize>()
                .unwrap_or_else(|err| panic!("could not parse token \"{}\": {:?}", num, err))
        })
        .collect();
    println!("Part 1: {}", part1(&input));
}

#[derive(StructOpt)]
struct Opt {
    #[structopt(parse(from_os_str))]
    input: PathBuf,
}
<commit_msg>2019 day 09 part 2<commit_after>use std::path::PathBuf;
use structopt::StructOpt;

fn part1(tape: &[isize]) -> isize {
    let output = intcode::Interpreter::new(tape.to_vec())
        .with_input(&[1])
        .run()
        .unwrap_or_else(|err| panic!("Error running intcode: {:?}", err));
    let (final_result, test_results) = output.output().split_last().expect("No output produced");
    for res in test_results {
        assert_eq!(*res, 0, "test failed with output: {}", res);
    }
    *final_result
}

fn part2(tape: &[isize]) -> isize {
    let output = intcode::Interpreter::new(tape.to_vec())
        .with_input(&[2])
        .run()
        .unwrap_or_else(|err| panic!("Error running intcode: {:?}", err));
    assert_eq!(output.output().len(), 1);
    output.output()[0]
}

fn main() {
    let input: Vec<_> = std::fs::read_to_string(Opt::from_args().input)
        .expect("error reading file")
        .split(',')
        .map(|num| {
            num.trim()
                .parse::<isize>()
                .unwrap_or_else(|err| panic!("could not parse token \"{}\": {:?}", num, err))
        })
        .collect();
    println!("Part 1: {}", part1(&input));
    println!("Part 2: {}", part2(&input));
}

#[derive(StructOpt)]
struct Opt {
    #[structopt(parse(from_os_str))]
    input: PathBuf,
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate revord;

use revord::RevOrd;
use std::io::prelude::*;
use std::fs::File;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap};

type Distance = usize;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct Point {
    x: usize,
    y: usize,
}

impl std::fmt::Display for Point {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(f, "({}, {})", self.x, self.y)
    }
}

impl Point {
    fn is_interesting(&self, map: &Map) -> bool {
        match map[*self] {
            Element::Wall => false,
            Element::Goal(_) => true,
            Element::Open => map.possible_moves(*self).len() > 2,
        }
    }
}

#[derive(Debug, Clone, Copy)]
enum Element {
    Wall,
    Open,
    Goal(usize),
}

impl Element {
    fn from_char(ch: char) -> Result<Element, String> {
        if let Some(digit) = ch.to_digit(10) {
            Ok(Element::Goal(digit as usize))
        } else if ch == '.' {
            Ok(Element::Open)
        } else if ch == '#' {
            Ok(Element::Wall)
        } else {
            Err(format!("Invalid element: {}", ch))
        }
    }
    fn is_wall(&self) -> bool {
        match *self {
            Element::Wall => true,
            _ => false,
        }
    }
}

#[derive(Debug, Clone)]
struct Map {
    elements: Vec<Vec<Element>>,
}

impl Map {
    fn walk_to_interesting_point(&self,
                                 home: Point,
                                 first_step: Point)
                                 -> Option<(Point, Distance)> {
        let mut prev = home;
        let mut current = first_step;
        let mut dist = 1;
        while !current.is_interesting(self) {
            if let Some(next) = self.possible_moves(current)
                .into_iter()
                .filter(|p| *p != prev)
                .next() {
                current = next;
                prev = current;
                dist += 1;
            } else {
                return None;
            }
        }
        Some((current, dist))
    }
    fn interesting_points(&self) -> InterestingPointGraph {
        let mut ips = BTreeMap::new();
        let mut types = BTreeMap::new();
        for y in 0..self.elements.len() {
            for x in 0..self.elements[0].len() {
                let point = Point { x: x, y: y };
                if point.is_interesting(self) {
                    let kind = match self[point] {
                        Element::Open => InterestingPoint::Intersection,
                        Element::Goal(n) => InterestingPoint::Goal(n),
                        _ => panic!("Thought a wall was interesting"),
                    };
                    let mut connections = BTreeMap::new();
                    for (ip, dist) in self.possible_moves(point)
                        .into_iter()
                        .map(|mov| self.walk_to_interesting_point(point, mov))
                        .filter_map(|o| o) {
                        if !connections.contains_key(&ip) || connections[&ip] > dist {
                            connections.insert(ip, dist);
                        }
                    }
                    if !connections.is_empty() {
                        ips.insert(point, connections);
                        types.insert(point, kind);
                    }
                }
            }
        }
        InterestingPointGraph {
            points: ips,
            types: types,
        }
    }
    fn possible_moves(&self, Point { x, y }: Point) -> Vec<Point> {
        if self[Point { x: x, y: y }].is_wall() {
            return Vec::new();
        }
        [Point { x: x, y: y - 1 },
         Point { x: x + 1, y: y },
         Point { x: x, y: y + 1 },
         Point { x: x - 1, y: y }]
            .iter()
            .cloned()
            .filter(|point| !self[*point].is_wall())
            .collect()
    }
}

impl std::ops::Index<Point> for Map {
    type Output = Element;
    fn index(&self, Point { x, y }: Point) -> &Self::Output {
        &self.elements[y][x]
    }
}

impl std::str::FromStr for Map {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Map {
            elements: s.lines()
                .map(|line| {
                    line.trim()
                        .chars()
                        .map(|ch| Element::from_char(ch))
                        .collect()
                })
                .collect::<Result<_, _>>()?,
        })
    }
}

#[derive(Debug, Clone, Copy)]
enum InterestingPoint {
    Intersection,
    Goal(usize),
}

#[derive(Debug, Clone)]
struct InterestingPointGraph {
    points: BTreeMap<Point, BTreeMap<Point, Distance>>,
    types: BTreeMap<Point, InterestingPoint>,
}

impl InterestingPointGraph {
    fn start(&self) -> Point {
        self.types
            .iter()
            .filter_map(|(point, elem)| match *elem {
                InterestingPoint::Goal(0) => Some(*point),
                _ => None,
            })
            .next()
            .expect("Interesting Point Graph had no start!")
    }
    fn goals(&self) -> BTreeSet<usize> {
        self.types
            .values()
            .filter_map(|ip| match *ip {
                InterestingPoint::Goal(num) => Some(num),
                InterestingPoint::Intersection => None,
            })
            .collect()
    }
    fn solve(&self) -> Option<Vec<(Point, Distance)>> {
        let start = self.start();
        let goals = self.goals();
        let mut visited = BTreeSet::new();
        let mut queue = BinaryHeap::new();
        let initial_obtained: BTreeSet<usize> = std::iter::once(0).collect();
        let mut best = initial_obtained.clone(); // DEBUG
        visited.insert((start, initial_obtained.clone()));
        queue.push((RevOrd(0), start, initial_obtained, Vec::new()));
        while let Some((RevOrd(dist_so_far), point, obtained, moves)) = queue.pop() {
            // println!("Considering: {}, {}, {:?}, {:?}",
            //         dist_so_far,
            //         point,
            //         obtained,
            //         moves);
            for (ip, next_dist) in self.points[&point].iter() {
                let total_dist = dist_so_far + next_dist;
                // println!("Neighbor: {}, {}", ip, next_dist);
                let mut new_moves = moves.clone();
                new_moves.push((*ip, *next_dist));
                let mut new_obtained = obtained.clone();
                if let InterestingPoint::Goal(n) = self.types[ip] {
                    new_obtained.insert(n);
                    if new_obtained == goals {
                        return Some(new_moves);
                    }
                    if new_obtained.len() > best.len() {
                        best = new_obtained.clone();
                        println!("new best: {:?}", best);
                    }
                }
                if !visited.contains(&(*ip, new_obtained.clone())) {
                    visited.insert((*ip, new_obtained.clone()));
                    queue.push((RevOrd(total_dist), *ip, new_obtained, new_moves));
                }
            }
        }
        None
    }
}

fn parse_args() -> std::io::Result<String> {
    let matches = clap::App::new("Day 20")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("IP ranges")
            .index(1)
            .help("file containing IP ranges for puzzle. Reads from stdin otherwise"))
        .get_matches();
    let source = matches.value_of_os("IP ranges");
    let mut contents = String::new();
    match source {
        Some(filename) => {
            let mut input = File::open(filename)?;
            input.read_to_string(&mut contents)?;
        }
        None => {
            let mut input = std::io::stdin();
            input.read_to_string(&mut contents)?;
        }
    }
    Ok(contents)
}

fn main() {
    let input = parse_args().unwrap_or_else(|err| panic!("Error reading args: {}", err));
    let map = input.parse::<Map>().unwrap_or_else(|err| panic!("Error reading map: {}", err));
    let ips = map.interesting_points();
    let mut total_dist = 0;
    println!("{}", ips.start());
    for (mov, dist) in ips.solve().expect("No solution found!") {
        total_dist += dist;
        println!(" -> {}", mov);
    }
    println!("Total distance: {}", total_dist);
}

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

    #[test]
    fn example() {
        let map = "###########\n#0.1.....2#\n#.#######.#\n#4.......3#\n###########"
            .parse::<Map>()
            .unwrap();
        let ips = map.interesting_points();
        assert_eq!(ips.solve()
                       .expect("No solution found!")
                       .into_iter()
                       .fold(0, |acc, (_, dist)| acc + dist),
                   14);
    }
}
<commit_msg>Day 24 part 1, finally<commit_after>extern crate clap;
extern crate revord;

use revord::RevOrd;
use std::io::prelude::*;
use std::fs::File;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap};

type Distance = usize;
type GoalNum = usize;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct Point {
    x: usize,
    y: usize,
}

impl std::fmt::Display for Point {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(f, "({}, {})", self.x, self.y)
    }
}

impl Point {
    fn is_interesting(&self, map: &Map) -> bool {
        match map[*self] {
            Element::Wall => false,
            Element::Goal(_) => true,
            Element::Open => map.possible_moves(*self).len() > 2,
        }
    }
}

#[derive(Debug, Clone, Copy)]
enum Element {
    Wall,
    Open,
    Goal(GoalNum),
}

impl Element {
    fn from_char(ch: char) -> Result<Element, String> {
        if let Some(digit) = ch.to_digit(10) {
            Ok(Element::Goal(digit as GoalNum))
        } else if ch == '.' {
            Ok(Element::Open)
        } else if ch == '#' {
            Ok(Element::Wall)
        } else {
            Err(format!("Invalid element: {}", ch))
        }
    }
    fn is_wall(&self) -> bool {
        match *self {
            Element::Wall => true,
            _ => false,
        }
    }
}

#[derive(Debug, Clone)]
struct Map {
    elements: Vec<Vec<Element>>,
}

impl Map {
    fn walk_to_interesting_point(&self,
                                 home: Point,
                                 first_step: Point)
                                 -> Option<(Point, Distance)> {
        let mut prev = home;
        let mut current = first_step;
        let mut dist = 1;
        while !current.is_interesting(self) {
            if let Some(next) = self.possible_moves(current)
                .into_iter()
                .filter(|p| *p != prev)
                .next() {
                prev = current;
                current = next;
                dist += 1;
            } else {
                return None;
            }
        }
        Some((current, dist))
    }
    fn interesting_points(&self) -> InterestingPointGraph {
        let mut ips = BTreeMap::new();
        let mut types = BTreeMap::new();
        for y in 0..self.elements.len() {
            for x in 0..self.elements[0].len() {
                let point = Point { x: x, y: y };
                if point.is_interesting(self) {
                    let kind = match self[point] {
                        Element::Open => InterestingPoint::Intersection,
                        Element::Goal(n) => InterestingPoint::Goal(n),
                        _ => panic!("Thought a wall was interesting"),
                    };
                    let mut connections = BTreeMap::new();
                    for (ip, dist) in self.possible_moves(point)
                        .into_iter()
                        .map(|mov| self.walk_to_interesting_point(point, mov))
                        .filter_map(|o| o) {
                        if !connections.contains_key(&ip) || connections[&ip] > dist {
                            connections.insert(ip, dist);
                        }
                    }
                    if !connections.is_empty() {
                        ips.insert(point, connections);
                        types.insert(point, kind);
                    }
                }
            }
        }
        InterestingPointGraph {
            neighbors: ips,
            types: types,
        }
    }
    fn possible_moves(&self, Point { x, y }: Point) -> Vec<Point> {
        if self[Point { x: x, y: y }].is_wall() {
            return Vec::new();
        }
        [Point { x: x, y: y - 1 },
         Point { x: x + 1, y: y },
         Point { x: x, y: y + 1 },
         Point { x: x - 1, y: y }]
            .iter()
            .cloned()
            .filter(|point| !self[*point].is_wall())
            .collect()
    }
}

impl std::ops::Index<Point> for Map {
    type Output = Element;
    fn index(&self, Point { x, y }: Point) -> &Self::Output {
        &self.elements[y][x]
    }
}

impl std::str::FromStr for Map {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Map {
            elements: s.lines()
                .map(|line| {
                    line.trim()
                        .chars()
                        .map(|ch| Element::from_char(ch))
                        .collect()
                })
                .collect::<Result<_, _>>()?,
        })
    }
}

#[derive(Debug, Clone, Copy)]
enum InterestingPoint {
    Intersection,
    Goal(GoalNum),
}

#[derive(Debug, Clone)]
struct InterestingPointGraph {
    neighbors: BTreeMap<Point, BTreeMap<Point, Distance>>,
    types: BTreeMap<Point, InterestingPoint>,
}

impl InterestingPointGraph {
    fn goals(&self) -> BTreeMap<Point, GoalNum> {
        self.types
            .iter()
            .filter_map(|(point, ip)| match *ip {
                InterestingPoint::Goal(num) => Some((*point, num)),
                InterestingPoint::Intersection => None,
            })
            .collect()
    }
    fn goal_graph(&self) -> GoalGraph {
        GoalGraph {
            goals: self.goals()
                .into_iter()
                .map(|(point, num)| (num, self.shortest_dist_to_goals(point)))
                .collect(),
        }
    }
    fn shortest_dist_to_goals(&self, start: Point) -> BTreeMap<GoalNum, Distance> {
        let mut goals = BTreeMap::new();
        let mut visited = BTreeSet::new();
        let mut queue = BinaryHeap::new();
        queue.push((RevOrd(0), start));
        while let Some((RevOrd(dist_so_far), current_point)) = queue.pop() {
            if visited.contains(&current_point) {
                continue;
            }
            visited.insert(current_point);
            if let InterestingPoint::Goal(n) = self.types[&current_point] {
                if !goals.contains_key(&n) || dist_so_far < goals[&n] {
                    goals.insert(n, dist_so_far);
                }
            }
            for (ip, next_dist) in self.neighbors[&current_point].iter() {
                let total_dist = dist_so_far + next_dist;
                if !visited.contains(ip) {
                    queue.push((RevOrd(total_dist), *ip));
                }
            }
        }
        if let InterestingPoint::Goal(n) = self.types[&start] {
            goals.remove(&n);
        }
        goals
    }
}

#[derive(Debug)]
struct GoalGraph {
    goals: BTreeMap<GoalNum, BTreeMap<GoalNum, Distance>>,
}

impl GoalGraph {
    fn shortest_circuit(&self) -> Distance {
        let mut queue = BinaryHeap::new();
        let initial_obtained: BTreeSet<GoalNum> = std::iter::once(0).collect();
        let all_goals: BTreeSet<GoalNum> = self.goals.keys().cloned().collect();
        let mut visited = BTreeSet::new();
        queue.push((RevOrd(0), 0, initial_obtained));
        while let Some((RevOrd(dist_so_far), current, obtained)) = queue.pop() {
            if visited.contains(&(current, obtained.clone())) {
                continue;
            }
            visited.insert((current, obtained.clone()));
            if obtained == all_goals {
                return dist_so_far;
            }
            for (next, next_dist) in self.goals[&current].iter() {
                let total_dist = dist_so_far + next_dist;
                let mut new_obtained = obtained.clone();
                new_obtained.insert(*next);
                if !visited.contains(&(*next, new_obtained.clone())) {
                    queue.push((RevOrd(total_dist), *next, new_obtained));
                }
            }
        }
        panic!("Could not reach all goals!")
    }
}

fn parse_args() -> std::io::Result<String> {
    let matches = clap::App::new("Day 20")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("IP ranges")
            .index(1)
            .help("file containing IP ranges for puzzle. Reads from stdin otherwise"))
        .get_matches();
    let source = matches.value_of_os("IP ranges");
    let mut contents = String::new();
    match source {
        Some(filename) => {
            let mut input = File::open(filename)?;
            input.read_to_string(&mut contents)?;
        }
        None => {
            let mut input = std::io::stdin();
            input.read_to_string(&mut contents)?;
        }
    }
    Ok(contents)
}

fn main() {
    let input = parse_args().unwrap_or_else(|err| panic!("Error reading args: {}", err));
    let map = input.parse::<Map>().unwrap_or_else(|err| panic!("Error reading map: {}", err));
    let ips = map.interesting_points();
    let goal_graph = ips.goal_graph();
    println!("Part 1 total distance: {}", goal_graph.shortest_circuit());
}

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

    #[test]
    fn example() {
        let map = "###########\n#0.1.....2#\n#.#######.#\n#4.......3#\n###########"
            .parse::<Map>()
            .unwrap();
        let ips = map.interesting_points();
        let goal_graph = ips.goal_graph();
        assert_eq!(goal_graph.shortest_circuit(), 14);
    }
}
<|endoftext|>


<commit_before>use crate::controls::{Adapted, Control, HasLabel};
use crate::types::{RecursiveTupleVecIterator};
use crate::sdk;
use crate::types::{adapter, Adapter, AsAny, RecursiveTupleVec, Spawnable, VecItemChangeOption};
use std::any::Any;
use std::marker::PhantomData;
use std::usize;

pub struct StringTupleVecAdapter<C: HasLabel + Spawnable> {
    item: RecursiveTupleVec<String>,
    on_item_change: Option<sdk::AdapterInnerCallback>,
    _marker: PhantomData<C>,
}
impl<C: HasLabel + Spawnable> StringTupleVecAdapter<C> {
	pub fn new() -> Self {
        Self::from(RecursiveTupleVec::default())
    }
    pub fn put<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize], value: VecItemChangeOption<RecursiveTupleVec<String>>) -> Result<Option<RecursiveTupleVec<String>>, &'b [usize]> {
    	let value_some = value.is_some();
        let value_is_branch = if value_some { value.as_ref().value.is_some() } else { false };
        let ret = self.item.put(indexes, value);
        if let Some(ref mut cb) = self.on_item_change.as_mut() {
        	if ret.is_ok() {
        		let change = match ret.as_ref().unwrap() {
        			Some(_) if value_some => adapter::Change::Edited(indexes, if value_is_branch {adapter::Node::Branch(false)} else {adapter::Node::Leaf}),
        			Some(_) => adapter::Change::Removed(indexes),
        			None if value_some => adapter::Change::Added(indexes, if value_is_branch {adapter::Node::Branch(false)} else {adapter::Node::Leaf}),
        			_ => adapter::Change::Edited(indexes, adapter::Node::Leaf),
        		};
        		cb.on_item_change(change);
        	}
        }
        ret
    }
    pub fn get_mut<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize]) -> Option<&'a mut RecursiveTupleVec<String>> {
        self.item.get_mut(indexes)
    }
    pub fn get<'a, 'b: 'a>(&'a self, indexes: &'b [usize]) -> Option<&'a RecursiveTupleVec<String>> {
	    self.item.get(indexes)
    }
}
impl<C: HasLabel + Spawnable> From<RecursiveTupleVec<String>> for StringTupleVecAdapter<C> {
    fn from(a: RecursiveTupleVec<String>) -> Self {
        StringTupleVecAdapter {
            item: a,
            on_item_change: None,
            _marker: PhantomData,
        }
    }
}
impl<C: HasLabel + Spawnable> AsAny for StringTupleVecAdapter<C> {
    #[inline]
    fn as_any(&self) -> &dyn Any {
        self
    }
    #[inline]
    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
    #[inline]
    fn into_any(self: Box<Self>) -> Box<dyn Any> {
        self
    }
}

impl<C: HasLabel + Spawnable> Adapter for StringTupleVecAdapter<C> {
    fn len_at(&self, indexes: &[usize]) -> Option<usize> {
        if indexes.len() == 0 {
            if let Some(ref value) = self.item.value {
                Some(value.len())
            } else {
                None
            }
        } else {
            self.item.get(indexes).and_then(|n| n.value.as_ref()).map(|n| n.len())
        }
    }
    fn node_at(&self, indexes: &[usize]) -> Option<adapter::Node> {
        self.item.get(indexes).map(|n| if n.value.is_some() { adapter::Node::Branch(true) } else { adapter::Node::Leaf })
    }
    fn spawn_item_view(&mut self, indexes: &[usize], _: &dyn Adapted) -> Option<Box<dyn Control>> {
        self.item.get(indexes).map(|n| {
            let mut control = C::spawn();
            control.as_any_mut().downcast_mut::<C>().unwrap().set_label(n.id.as_str().into());

            control
        })
    }
    fn for_each<'a, 'b:'a, 'c: 'b>(&'c self, f: &'a mut dyn adapter::FnNodeItem) {
        let mut iterator = RecursiveTupleVecIterator::with_item(&self.item);
        while let Some((indexes, ref node, _item)) = iterator.next() {
            f(indexes, node);
        }
    }
}
impl<C: HasLabel + Spawnable> sdk::AdapterInner for StringTupleVecAdapter<C> {
    fn on_item_change(&mut self, cb: Option<sdk::AdapterInnerCallback>) {
        self.on_item_change = cb;
    }
}
<commit_msg>StringTupleVecAdapter - expand branches by default<commit_after>use crate::controls::{Adapted, Control, HasLabel};
use crate::types::{RecursiveTupleVecIterator};
use crate::sdk;
use crate::types::{adapter, Adapter, AsAny, RecursiveTupleVec, Spawnable, VecItemChangeOption};
use std::any::Any;
use std::marker::PhantomData;
use std::usize;

pub struct StringTupleVecAdapter<C: HasLabel + Spawnable> {
    item: RecursiveTupleVec<String>,
    on_item_change: Option<sdk::AdapterInnerCallback>,
    _marker: PhantomData<C>,
}
impl<C: HasLabel + Spawnable> StringTupleVecAdapter<C> {
	pub fn new() -> Self {
        Self::from(RecursiveTupleVec::default())
    }
    pub fn put<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize], value: VecItemChangeOption<RecursiveTupleVec<String>>) -> Result<Option<RecursiveTupleVec<String>>, &'b [usize]> {
    	let value_some = value.is_some();
        let value_is_branch = if value_some { value.as_ref().value.is_some() } else { false };
        let ret = self.item.put(indexes, value);
        if let Some(ref mut cb) = self.on_item_change.as_mut() {
        	if ret.is_ok() {
        		let change = match ret.as_ref().unwrap() {
        			Some(_) if value_some => adapter::Change::Edited(indexes, if value_is_branch {adapter::Node::Branch(true)} else {adapter::Node::Leaf}),
        			Some(_) => adapter::Change::Removed(indexes),
        			None if value_some => adapter::Change::Added(indexes, if value_is_branch {adapter::Node::Branch(true)} else {adapter::Node::Leaf}),
        			_ => adapter::Change::Edited(indexes, adapter::Node::Leaf),
        		};
        		cb.on_item_change(change);
        	}
        }
        ret
    }
    pub fn get_mut<'a, 'b: 'a>(&'a mut self, indexes: &'b [usize]) -> Option<&'a mut RecursiveTupleVec<String>> {
        self.item.get_mut(indexes)
    }
    pub fn get<'a, 'b: 'a>(&'a self, indexes: &'b [usize]) -> Option<&'a RecursiveTupleVec<String>> {
	    self.item.get(indexes)
    }
}
impl<C: HasLabel + Spawnable> From<RecursiveTupleVec<String>> for StringTupleVecAdapter<C> {
    fn from(a: RecursiveTupleVec<String>) -> Self {
        StringTupleVecAdapter {
            item: a,
            on_item_change: None,
            _marker: PhantomData,
        }
    }
}
impl<C: HasLabel + Spawnable> AsAny for StringTupleVecAdapter<C> {
    #[inline]
    fn as_any(&self) -> &dyn Any {
        self
    }
    #[inline]
    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
    #[inline]
    fn into_any(self: Box<Self>) -> Box<dyn Any> {
        self
    }
}

impl<C: HasLabel + Spawnable> Adapter for StringTupleVecAdapter<C> {
    fn len_at(&self, indexes: &[usize]) -> Option<usize> {
        if indexes.len() == 0 {
            if let Some(ref value) = self.item.value {
                Some(value.len())
            } else {
                None
            }
        } else {
            self.item.get(indexes).and_then(|n| n.value.as_ref()).map(|n| n.len())
        }
    }
    fn node_at(&self, indexes: &[usize]) -> Option<adapter::Node> {
        self.item.get(indexes).map(|n| if n.value.is_some() { adapter::Node::Branch(true) } else { adapter::Node::Leaf })
    }
    fn spawn_item_view(&mut self, indexes: &[usize], _: &dyn Adapted) -> Option<Box<dyn Control>> {
        self.item.get(indexes).map(|n| {
            let mut control = C::spawn();
            control.as_any_mut().downcast_mut::<C>().unwrap().set_label(n.id.as_str().into());

            control
        })
    }
    fn for_each<'a, 'b:'a, 'c: 'b>(&'c self, f: &'a mut dyn adapter::FnNodeItem) {
        let mut iterator = RecursiveTupleVecIterator::with_item(&self.item);
        while let Some((indexes, ref node, _item)) = iterator.next() {
            f(indexes, node);
        }
    }
}
impl<C: HasLabel + Spawnable> sdk::AdapterInner for StringTupleVecAdapter<C> {
    fn on_item_change(&mut self, cb: Option<sdk::AdapterInnerCallback>) {
        self.on_item_change = cb;
    }
}
<|endoftext|>


<commit_before>use std::io::{self, ErrorKind, Read, Write};
use std::mem;
use std::net::{self, SocketAddr};
use std::sync::Arc;

use futures::stream::{self, Stream};
use futures::{Future, IntoFuture, failed, Task, Poll};
use futures_io::{Ready, IoFuture, IoStream};
use mio;

use {ReadinessStream, LoopHandle};
use event_loop::Source;

/// An I/O object representing a TCP socket listening for incoming connections.
///
/// This object can be converted into a stream of incoming connections for
/// various forms of processing.
pub struct TcpListener {
    loop_handle: LoopHandle,
    ready: ReadinessStream,
    listener: Arc<Source<mio::tcp::TcpListener>>,
}

impl TcpListener {
    fn new(listener: mio::tcp::TcpListener,
           handle: LoopHandle) -> Box<IoFuture<TcpListener>> {
        let listener = Arc::new(Source::new(listener));
        ReadinessStream::new(handle.clone(), listener.clone()).map(|r| {
            TcpListener {
                loop_handle: handle,
                ready: r,
                listener: listener,
            }
        }).boxed()
    }

    /// Create a new TCP listener from the standard library's TCP listener.
    ///
    /// This method can be used when the `LoopHandle::tcp_listen` method isn't
    /// sufficient because perhaps some more configuration is needed in terms of
    /// before the calls to `bind` and `listen`.
    ///
    /// This API is typically paired with the `net2` crate and the `TcpBuilder`
    /// type to build up and customize a listener before it's shipped off to the
    /// backing event loop. This allows configuration of options like
    /// `SO_REUSEPORT`, binding to multiple addresses, etc.
    ///
    /// The `addr` argument here is one of the addresses that `listener` is
    /// bound to and the listener will only be guaranteed to accept connections
    /// of the same address type currently.
    ///
    /// Finally, the `handle` argument is the event loop that this listener will
    /// be bound to.
    ///
    /// The platform specific behavior of this function looks like:
    ///
    /// * On Unix, the socket is placed into nonblocking mode and connections
    ///   can be accepted as normal
    ///
    /// * On Windows, the address is stored internally and all future accepts
    ///   will only be for the same IP version as `addr` specified. That is, if
    ///   `addr` is an IPv4 address then all sockets accepted will be IPv4 as
    ///   well (same for IPv6).
    pub fn from_listener(listener: net::TcpListener,
                         addr: &SocketAddr,
                         handle: LoopHandle) -> Box<IoFuture<TcpListener>> {
        mio::tcp::TcpListener::from_listener(listener, addr)
            .into_future()
            .and_then(|l| TcpListener::new(l, handle))
            .boxed()
    }

    /// Returns the local address that this listener is bound to.
    ///
    /// This can be useful, for example, when binding to port 0 to figure out
    /// which port was actually bound.
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.listener.io().local_addr()
    }

    /// Consumes this listener, returning a stream of the sockets this listener
    /// accepts.
    ///
    /// This method returns an implementation of the `Stream` trait which
    /// resolves to the sockets the are accepted on this listener.
    pub fn incoming(self) -> Box<IoStream<(TcpStream, SocketAddr)>> {
        let TcpListener { loop_handle, listener, ready } = self;

        ready
            .map(move |_| {
                stream::iter(NonblockingIter { source: listener.clone() }.fuse())
            })
            .flatten()
            .and_then(move |(tcp, addr)| {
                let tcp = Arc::new(Source::new(tcp));
                ReadinessStream::new(loop_handle.clone(),
                                     tcp.clone()).map(move |ready| {
                    let stream = TcpStream {
                        source: tcp,
                        ready: ready,
                    };
                    (stream, addr)
                })
            }).boxed()
    }
}

struct NonblockingIter {
    source: Arc<Source<mio::tcp::TcpListener>>,
}

impl Iterator for NonblockingIter {
    type Item = io::Result<(mio::tcp::TcpStream, SocketAddr)>;

    fn next(&mut self) -> Option<io::Result<(mio::tcp::TcpStream, SocketAddr)>> {
        match self.source.io().accept() {
            Ok(Some(e)) => {
                debug!("accepted connection");
                Some(Ok(e))
            }
            Ok(None) => {
                debug!("no connection ready");
                None
            }
            Err(e) => Some(Err(e)),
        }
    }
}

impl Stream for TcpListener {
    type Item = Ready;
    type Error = io::Error;

    fn poll(&mut self, task: &mut Task) -> Poll<Option<Ready>, io::Error> {
        self.ready.poll(task)
    }

    fn schedule(&mut self, task: &mut Task) {
        self.ready.schedule(task)
    }
}

/// An I/O object representing a TCP stream connected to a remote endpoint.
///
/// A TCP stream can either be created by connecting to an endpoint or by
/// accepting a connection from a listener. Inside the stream is access to the
/// raw underlying I/O object as well as streams for the read/write
/// notifications on the stream itself.
pub struct TcpStream {
    source: Arc<Source<mio::tcp::TcpStream>>,
    ready: ReadinessStream,
}

enum TcpStreamNew {
    Waiting(TcpStream),
    Empty,
}

impl LoopHandle {
    /// Create a new TCP listener associated with this event loop.
    ///
    /// The TCP listener will bind to the provided `addr` address, if available,
    /// and will be returned as a future. The returned future, if resolved
    /// successfully, can then be used to accept incoming connections.
    pub fn tcp_listen(self, addr: &SocketAddr) -> Box<IoFuture<TcpListener>> {
        match mio::tcp::TcpListener::bind(addr) {
            Ok(l) => TcpListener::new(l, self),
            Err(e) => failed(e).boxed(),
        }
    }

    /// Create a new TCP stream connected to the specified address.
    ///
    /// This function will create a new TCP socket and attempt to connect it to
    /// the `addr` provided. The returned future will be resolved once the
    /// stream has successfully connected. If an error happens during the
    /// connection or during the socket creation, that error will be returned to
    /// the future instead.
    pub fn tcp_connect(self, addr: &SocketAddr) -> Box<IoFuture<TcpStream>> {
        match mio::tcp::TcpStream::connect(addr) {
            Ok(tcp) => TcpStream::new(tcp, self),
            Err(e) => failed(e).boxed(),
        }
    }
}

impl TcpStream {
    fn new(connected_stream: mio::tcp::TcpStream,
           handle: LoopHandle)
           -> Box<IoFuture<TcpStream>> {
        // Once we've connected, wait for the stream to be writable as that's
        // when the actual connection has been initiated. Once we're writable we
        // check for `take_socket_error` to see if the connect actually hit an
        // error or not.
        //
        // If all that succeeded then we ship everything on up.
        let connected_stream = Arc::new(Source::new(connected_stream));
        ReadinessStream::new(handle, connected_stream.clone()).and_then(|ready| {
            TcpStreamNew::Waiting(TcpStream {
                source: connected_stream,
                ready: ready,
            })
        }).boxed()
    }

    /// Creates a new `TcpStream` from the pending socket inside the given
    /// `std::net::TcpStream`, connecting it to the address specified.
    ///
    /// This constructor allows configuring the socket before it's actually
    /// connected, and this function will transfer ownership to the returned
    /// `TcpStream` if successful. An unconnected `TcpStream` can be created
    /// with the `net2::TcpBuilder` type (and also configured via that route).
    ///
    /// The platform specific behavior of this function looks like:
    ///
    /// * On Unix, the socket is placed into nonblocking mode and then a
    ///   `connect` call is issued.
    ///
    /// * On Windows, the address is stored internally and the connect operation
    ///   is issued when the returned `TcpStream` is registered with an event
    ///   loop. Note that on Windows you must `bind` a socket before it can be
    ///   connected, so if a custom `TcpBuilder` is used it should be bound
    ///   (perhaps to `INADDR_ANY`) before this method is called.
    pub fn connect_stream(stream: net::TcpStream,
                          addr: &SocketAddr,
                          handle: LoopHandle) -> Box<IoFuture<TcpStream>> {
        match mio::tcp::TcpStream::connect_stream(stream, addr) {
            Ok(tcp) => TcpStream::new(tcp, handle),
            Err(e) => failed(e).boxed(),
        }
    }

    /// Returns the local address that this stream is bound to.
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.source.io().local_addr()
    }

    /// Returns the remote address that this stream is connected to.
    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        self.source.io().peer_addr()
    }
}

impl Future for TcpStreamNew {
    type Item = TcpStream;
    type Error = io::Error;

    fn poll(&mut self, task: &mut Task) -> Poll<TcpStream, io::Error> {
        let mut stream = match mem::replace(self, TcpStreamNew::Empty) {
            TcpStreamNew::Waiting(s) => s,
            TcpStreamNew::Empty => panic!("can't poll TCP stream twice"),
        };
        match stream.ready.poll(task) {
            Poll::Ok(None) => panic!(),
            Poll::Ok(Some(_)) => {
                match stream.source.io().take_socket_error() {
                    Ok(()) => return Poll::Ok(stream),
                    Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
                    Err(e) => return Poll::Err(e),
                }
            }
            Poll::Err(e) => return Poll::Err(e),
            Poll::NotReady => {}
        }
        *self = TcpStreamNew::Waiting(stream);
        Poll::NotReady
    }

    fn schedule(&mut self, task: &mut Task) {
        match *self {
            TcpStreamNew::Waiting(ref mut s) => {
                s.ready.schedule(task);
            }
            TcpStreamNew::Empty => task.notify(),
        }
    }
}

impl Read for TcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let r = self.source.io().read(buf);
        trace!("read[{:p}] {:?} on {:?}", self, r, self.source.io());
        return r
    }
}

impl Write for TcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let r = self.source.io().write(buf);
        trace!("write[{:p}] {:?} on {:?}", self, r, self.source.io());
        return r
    }
    fn flush(&mut self) -> io::Result<()> {
        self.source.io().flush()
    }
}

impl<'a> Read for &'a TcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.source.io().read(buf)
    }
}

impl<'a> Write for &'a TcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.source.io().write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.source.io().flush()
    }
}

impl Stream for TcpStream {
    type Item = Ready;
    type Error = io::Error;

    fn poll(&mut self, task: &mut Task) -> Poll<Option<Ready>, io::Error> {
        self.ready.poll(task)
    }

    fn schedule(&mut self, task: &mut Task) {
        self.ready.schedule(task)
    }
}
<commit_msg>Add a few more TCP methods<commit_after>use std::io::{self, ErrorKind, Read, Write};
use std::mem;
use std::net::{self, SocketAddr, Shutdown};
use std::sync::Arc;

use futures::stream::{self, Stream};
use futures::{Future, IntoFuture, failed, Task, Poll};
use futures_io::{Ready, IoFuture, IoStream};
use mio;

use {ReadinessStream, LoopHandle};
use event_loop::Source;

/// An I/O object representing a TCP socket listening for incoming connections.
///
/// This object can be converted into a stream of incoming connections for
/// various forms of processing.
pub struct TcpListener {
    loop_handle: LoopHandle,
    ready: ReadinessStream,
    listener: Arc<Source<mio::tcp::TcpListener>>,
}

impl TcpListener {
    fn new(listener: mio::tcp::TcpListener,
           handle: LoopHandle) -> Box<IoFuture<TcpListener>> {
        let listener = Arc::new(Source::new(listener));
        ReadinessStream::new(handle.clone(), listener.clone()).map(|r| {
            TcpListener {
                loop_handle: handle,
                ready: r,
                listener: listener,
            }
        }).boxed()
    }

    /// Create a new TCP listener from the standard library's TCP listener.
    ///
    /// This method can be used when the `LoopHandle::tcp_listen` method isn't
    /// sufficient because perhaps some more configuration is needed in terms of
    /// before the calls to `bind` and `listen`.
    ///
    /// This API is typically paired with the `net2` crate and the `TcpBuilder`
    /// type to build up and customize a listener before it's shipped off to the
    /// backing event loop. This allows configuration of options like
    /// `SO_REUSEPORT`, binding to multiple addresses, etc.
    ///
    /// The `addr` argument here is one of the addresses that `listener` is
    /// bound to and the listener will only be guaranteed to accept connections
    /// of the same address type currently.
    ///
    /// Finally, the `handle` argument is the event loop that this listener will
    /// be bound to.
    ///
    /// The platform specific behavior of this function looks like:
    ///
    /// * On Unix, the socket is placed into nonblocking mode and connections
    ///   can be accepted as normal
    ///
    /// * On Windows, the address is stored internally and all future accepts
    ///   will only be for the same IP version as `addr` specified. That is, if
    ///   `addr` is an IPv4 address then all sockets accepted will be IPv4 as
    ///   well (same for IPv6).
    pub fn from_listener(listener: net::TcpListener,
                         addr: &SocketAddr,
                         handle: LoopHandle) -> Box<IoFuture<TcpListener>> {
        mio::tcp::TcpListener::from_listener(listener, addr)
            .into_future()
            .and_then(|l| TcpListener::new(l, handle))
            .boxed()
    }

    /// Returns the local address that this listener is bound to.
    ///
    /// This can be useful, for example, when binding to port 0 to figure out
    /// which port was actually bound.
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.listener.io().local_addr()
    }

    /// Consumes this listener, returning a stream of the sockets this listener
    /// accepts.
    ///
    /// This method returns an implementation of the `Stream` trait which
    /// resolves to the sockets the are accepted on this listener.
    pub fn incoming(self) -> Box<IoStream<(TcpStream, SocketAddr)>> {
        let TcpListener { loop_handle, listener, ready } = self;

        ready
            .map(move |_| {
                stream::iter(NonblockingIter { source: listener.clone() }.fuse())
            })
            .flatten()
            .and_then(move |(tcp, addr)| {
                let tcp = Arc::new(Source::new(tcp));
                ReadinessStream::new(loop_handle.clone(),
                                     tcp.clone()).map(move |ready| {
                    let stream = TcpStream {
                        source: tcp,
                        ready: ready,
                    };
                    (stream, addr)
                })
            }).boxed()
    }
}

struct NonblockingIter {
    source: Arc<Source<mio::tcp::TcpListener>>,
}

impl Iterator for NonblockingIter {
    type Item = io::Result<(mio::tcp::TcpStream, SocketAddr)>;

    fn next(&mut self) -> Option<io::Result<(mio::tcp::TcpStream, SocketAddr)>> {
        match self.source.io().accept() {
            Ok(Some(e)) => {
                debug!("accepted connection");
                Some(Ok(e))
            }
            Ok(None) => {
                debug!("no connection ready");
                None
            }
            Err(e) => Some(Err(e)),
        }
    }
}

impl Stream for TcpListener {
    type Item = Ready;
    type Error = io::Error;

    fn poll(&mut self, task: &mut Task) -> Poll<Option<Ready>, io::Error> {
        self.ready.poll(task)
    }

    fn schedule(&mut self, task: &mut Task) {
        self.ready.schedule(task)
    }
}

/// An I/O object representing a TCP stream connected to a remote endpoint.
///
/// A TCP stream can either be created by connecting to an endpoint or by
/// accepting a connection from a listener. Inside the stream is access to the
/// raw underlying I/O object as well as streams for the read/write
/// notifications on the stream itself.
pub struct TcpStream {
    source: Arc<Source<mio::tcp::TcpStream>>,
    ready: ReadinessStream,
}

enum TcpStreamNew {
    Waiting(TcpStream),
    Empty,
}

impl LoopHandle {
    /// Create a new TCP listener associated with this event loop.
    ///
    /// The TCP listener will bind to the provided `addr` address, if available,
    /// and will be returned as a future. The returned future, if resolved
    /// successfully, can then be used to accept incoming connections.
    pub fn tcp_listen(self, addr: &SocketAddr) -> Box<IoFuture<TcpListener>> {
        match mio::tcp::TcpListener::bind(addr) {
            Ok(l) => TcpListener::new(l, self),
            Err(e) => failed(e).boxed(),
        }
    }

    /// Create a new TCP stream connected to the specified address.
    ///
    /// This function will create a new TCP socket and attempt to connect it to
    /// the `addr` provided. The returned future will be resolved once the
    /// stream has successfully connected. If an error happens during the
    /// connection or during the socket creation, that error will be returned to
    /// the future instead.
    pub fn tcp_connect(self, addr: &SocketAddr) -> Box<IoFuture<TcpStream>> {
        match mio::tcp::TcpStream::connect(addr) {
            Ok(tcp) => TcpStream::new(tcp, self),
            Err(e) => failed(e).boxed(),
        }
    }
}

impl TcpStream {
    fn new(connected_stream: mio::tcp::TcpStream,
           handle: LoopHandle)
           -> Box<IoFuture<TcpStream>> {
        // Once we've connected, wait for the stream to be writable as that's
        // when the actual connection has been initiated. Once we're writable we
        // check for `take_socket_error` to see if the connect actually hit an
        // error or not.
        //
        // If all that succeeded then we ship everything on up.
        let connected_stream = Arc::new(Source::new(connected_stream));
        ReadinessStream::new(handle, connected_stream.clone()).and_then(|ready| {
            TcpStreamNew::Waiting(TcpStream {
                source: connected_stream,
                ready: ready,
            })
        }).boxed()
    }

    /// Creates a new `TcpStream` from the pending socket inside the given
    /// `std::net::TcpStream`, connecting it to the address specified.
    ///
    /// This constructor allows configuring the socket before it's actually
    /// connected, and this function will transfer ownership to the returned
    /// `TcpStream` if successful. An unconnected `TcpStream` can be created
    /// with the `net2::TcpBuilder` type (and also configured via that route).
    ///
    /// The platform specific behavior of this function looks like:
    ///
    /// * On Unix, the socket is placed into nonblocking mode and then a
    ///   `connect` call is issued.
    ///
    /// * On Windows, the address is stored internally and the connect operation
    ///   is issued when the returned `TcpStream` is registered with an event
    ///   loop. Note that on Windows you must `bind` a socket before it can be
    ///   connected, so if a custom `TcpBuilder` is used it should be bound
    ///   (perhaps to `INADDR_ANY`) before this method is called.
    pub fn connect_stream(stream: net::TcpStream,
                          addr: &SocketAddr,
                          handle: LoopHandle) -> Box<IoFuture<TcpStream>> {
        match mio::tcp::TcpStream::connect_stream(stream, addr) {
            Ok(tcp) => TcpStream::new(tcp, handle),
            Err(e) => failed(e).boxed(),
        }
    }

    /// Returns the local address that this stream is bound to.
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.source.io().local_addr()
    }

    /// Returns the remote address that this stream is connected to.
    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        self.source.io().peer_addr()
    }

    /// Shuts down the read, write, or both halves of this connection.
    ///
    /// This function will cause all pending and future I/O on the specified
    /// portions to return immediately with an appropriate value (see the
    /// documentation of `Shutdown`).
    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        self.source.io().shutdown(how)
    }

    /// Sets the value of the `TCP_NODELAY` option on this socket.
    ///
    /// If set, this option disables the Nagle algorithm. This means that
    /// segments are always sent as soon as possible, even if there is only a
    /// small amount of data. When not set, data is buffered until there is a
    /// sufficient amount to send out, thereby avoiding the frequent sending of
    /// small packets.
    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
        self.source.io().set_nodelay(nodelay)
    }

    /// Sets the keepalive time in seconds for this socket.
    pub fn set_keepalive_s(&self, seconds: Option<u32>) -> io::Result<()> {
        self.source.io().set_keepalive(seconds)
    }
}

impl Future for TcpStreamNew {
    type Item = TcpStream;
    type Error = io::Error;

    fn poll(&mut self, task: &mut Task) -> Poll<TcpStream, io::Error> {
        let mut stream = match mem::replace(self, TcpStreamNew::Empty) {
            TcpStreamNew::Waiting(s) => s,
            TcpStreamNew::Empty => panic!("can't poll TCP stream twice"),
        };
        match stream.ready.poll(task) {
            Poll::Ok(None) => panic!(),
            Poll::Ok(Some(_)) => {
                match stream.source.io().take_socket_error() {
                    Ok(()) => return Poll::Ok(stream),
                    Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
                    Err(e) => return Poll::Err(e),
                }
            }
            Poll::Err(e) => return Poll::Err(e),
            Poll::NotReady => {}
        }
        *self = TcpStreamNew::Waiting(stream);
        Poll::NotReady
    }

    fn schedule(&mut self, task: &mut Task) {
        match *self {
            TcpStreamNew::Waiting(ref mut s) => {
                s.ready.schedule(task);
            }
            TcpStreamNew::Empty => task.notify(),
        }
    }
}

impl Read for TcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let r = self.source.io().read(buf);
        trace!("read[{:p}] {:?} on {:?}", self, r, self.source.io());
        return r
    }
}

impl Write for TcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let r = self.source.io().write(buf);
        trace!("write[{:p}] {:?} on {:?}", self, r, self.source.io());
        return r
    }
    fn flush(&mut self) -> io::Result<()> {
        self.source.io().flush()
    }
}

impl<'a> Read for &'a TcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.source.io().read(buf)
    }
}

impl<'a> Write for &'a TcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.source.io().write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.source.io().flush()
    }
}

impl Stream for TcpStream {
    type Item = Ready;
    type Error = io::Error;

    fn poll(&mut self, task: &mut Task) -> Poll<Option<Ready>, io::Error> {
        self.ready.poll(task)
    }

    fn schedule(&mut self, task: &mut Task) {
        self.ready.schedule(task)
    }
}
<|endoftext|>


<commit_before>use std::iter::repeat;
use std::io::{self, Write};
use time::{self, Timespec, Duration};
use tty::{Width, terminal_size};

macro_rules! printfl {
    ($($tt:tt)*) => {{
        print!($($tt)*);
        io::stdout().flush().ok().expect("flush() fail");
    }}
}

macro_rules! kb_fmt {
    ($n: ident) => {{
        let kb = 1024f64;
        match $n {
            $n if $n >= kb.powf(4_f64) => format!("{:.*} TB", 2, $n / kb.powf(4_f64)),
            $n if $n >= kb.powf(3_f64) => format!("{:.*} GB", 2, $n / kb.powf(3_f64)),
            $n if $n >= kb.powf(2_f64) => format!("{:.*} MB", 2, $n / kb.powf(2_f64)),
            $n if $n >= kb => format!("{:.*} KB", 2, $n / kb),
            _ => format!("{:.*} B", 0, $n)
        }
    }}
}

macro_rules! repeat {
    ($s: expr, $n: expr) => {{
        &repeat($s).take($n).collect::<String>()
    }}
}

static FORMAT: &'static str = "[=>-]";

// Output type format, indicate which format wil be used in
// the speed box.
#[derive(Debug)]
pub enum Units {
    Default,
    Bytes,
}

#[derive(Debug)]
pub struct ProgressBar {
    start_time: Timespec,
    units: Units,
    total: usize,
    current: usize,
    is_finish: bool,
    show_bar: bool,
    show_speed: bool,
    show_percent: bool,
    show_counter: bool,
    show_time_left: bool,
    bar_start: String,
    bar_current: String,
    bar_current_n: String,
    bar_remain: String,
    bar_end: String,
}

impl ProgressBar {
    /// Create a new ProgressBar with default configuration.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::thread;
    /// use pb::{ProgressBar, Units};
    ///
    /// let count = 1000;
    /// let mut pb = ProgressBar::new(count);
    /// pb.set_units(Units::Bytes);
    ///
    /// for _ in 0..count {
    ///    pb.inc();
    ///    thread::sleep_ms(100);
    /// }
    /// ```
    pub fn new(total: usize) -> ProgressBar {
        let mut pb = ProgressBar {
            total: total,
            current: 0,
            start_time: time::get_time(),
            units: Units::Default,
            is_finish: false,
            show_bar: true,
            show_speed: false,
            show_percent: true,
            show_counter: true,
            show_time_left: true,
            bar_start: String::new(),
            bar_current: String::new(),
            bar_current_n: String::new(),
            bar_remain: String::new(),
            bar_end: String::new(),
        };
        pb.format(FORMAT);
        pb
    }

    /// set units, default is simple numbers
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use pb::{ProgressBar, Units};
    ///
    /// let mut pb = ProgressBar::new(n_bytes);
    /// pb.set_units(Units::Bytes);
    /// ```
    pub fn set_units(&mut self, u: Units) {
        self.units = u;
    }

    /// Set custom format to the drawing bar, default is "[=>-]"
    ///
    /// # Examples
    ///
    /// ```no_run
    /// pb.format("[=>_]")
    /// ```
    pub fn format(&mut self, fmt: &str) {
        if fmt.len() >= 5 {
            let v: Vec<&str> = fmt.split("").collect();
            self.bar_start = v[1].to_string();
            self.bar_current = v[2].to_string();
            self.bar_current_n = v[3].to_string();
            self.bar_remain = v[4].to_string();
            self.bar_end = v[5].to_string();
        }
    }

    /// Add to current value
    pub fn add(&mut self, i: usize) -> usize {
        self.current += i;
        if self.current <= self.total {
            self.draw()
        };
        self.current
    }

    /// Increment current value
    pub fn inc(&mut self) -> usize {
        return self.add(1);
    }

    fn draw(&self) {
        let tty_size = terminal_size();
        let width = if let Some((Width(w), _)) = tty_size {
            w as usize
        } else {
            80
        };
        let mut base = String::new();
        let mut suffix = String::new();
        let mut prefix = String::new();
        let mut out;
        // precent box
        if self.show_percent {
            let percent = self.current as f64 / (self.total as f64 / 100f64);
            suffix = suffix + &format!(" {:.*} % ", 2, percent);
        }
        // speed box
        if !self.show_speed {
            let from_start = (time::get_time() - self.start_time).num_nanoseconds().unwrap() as f64;
            let sec_nano = Duration::seconds(1).num_nanoseconds().unwrap() as f64;
            let speed = self.current as f64 / (from_start / sec_nano);
            suffix = match self.units {
                Units::Default => suffix + &format!("{}/s ", speed),
                Units::Bytes => suffix + &format!("{}/s ", kb_fmt!(speed)),
            };
        }
        // time left box
        if self.show_time_left {
            let from_start = time::get_time() - self.start_time;
            let sec_nano = Duration::seconds(1).num_nanoseconds().unwrap() as i32;
            let per_entry = from_start / self.current as i32;
            let mut left = per_entry * (self.total - self.current) as i32;
            left = (left / sec_nano) * sec_nano;
            if left.num_seconds() > 0 {
                if left.num_seconds() < Duration::minutes(1).num_seconds() {
                    suffix = suffix + &format!("{}s", left.num_seconds());
                } else {
                    suffix = suffix + &format!("{}m", left.num_minutes());
                }
            }
        }
        // counter box
        if self.show_counter {
            let (c, t) = (self.current as f64, self.total as f64);
            prefix = match self.units {
                Units::Default => format!("{} / {} ", c, t),
                Units::Bytes => format!("{} / {} ", kb_fmt!(c), kb_fmt!(t)),
            };
        }
        // bar box
        if self.show_bar {
            let size = width - (prefix.len() + suffix.len() + 3);
            if size > 0 {
                let curr_count =
                    ((self.current as f64 / self.total as f64) * size as f64).ceil() as usize;
                let rema_count = size - curr_count;
                base = self.bar_start.to_string();
                if rema_count > 0 {
                    base = base + repeat!(self.bar_current.as_ref(), curr_count - 1) +
                           &self.bar_current_n;
                } else {
                    base = base + repeat!(self.bar_current.as_ref(), curr_count);
                }
                base = base + repeat!(self.bar_remain.as_ref(), rema_count) + &self.bar_end;
            }
        }
        out = prefix + &base + &suffix;
        // pad
        if out.len() < width {
            let gap = width - out.len();
            out = out + repeat!(" ", gap);
        }
        // print
        printfl!("\r{}", out);
    }

    /// Calling finish manually will set current to total and draw
    /// the last time
    pub fn finish(&mut self) {
        if self.current < self.total {
            self.current = self.total;
            self.draw();
        }
        println!("");
        self.is_finish = true;
    }
}

// Implement io::Writer
impl Write for ProgressBar {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = buf.len();
        self.add(n);
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use pb::ProgressBar;

    #[test]
    fn add() {
        let mut pb = ProgressBar::new(10);
        pb.add(2);
        assert!(pb.current == 2,
                "should add the given `n` to current");
        assert!(pb.add(2) == pb.current,
                "add should return the current value");
    }

    #[test]
    fn inc() {
        let mut pb = ProgressBar::new(10);
        pb.inc();
        assert!(pb.current == 1, "should increment current by 1");
    }

    #[test]
    fn format() {
        let FORMAT = "[~> ]";
        let mut pb = ProgressBar::new(1);
        pb.format(FORMAT);
        assert!(pb.bar_start + &pb.bar_current + &pb.bar_current_n + &pb.bar_remain +
                &pb.bar_end == FORMAT);
    }

    #[test]
    fn finish() {
        let mut pb = ProgressBar::new(10);
        pb.finish();
        assert!(pb.current == pb.total,
                "should set current to total");
        assert!(pb.is_finish, "should set is_finish to true");
    }

    #[test]
    fn kb_fmt() {
        let kb = 1024f64;
        let mb = kb.powf(2f64);
        let gb = kb.powf(3f64);
        let tb = kb.powf(4f64);
        assert_eq!(kb_fmt!(kb), "1.00 KB");
        assert_eq!(kb_fmt!(mb), "1.00 MB");
        assert_eq!(kb_fmt!(gb), "1.00 GB");
        assert_eq!(kb_fmt!(tb), "1.00 TB");
    }
}
<commit_msg>style(pb): write fn<commit_after>use std::iter::repeat;
use std::io::{self, Write};
use time::{self, Timespec, Duration};
use tty::{Width, terminal_size};

macro_rules! printfl {
    ($($tt:tt)*) => {{
        print!($($tt)*);
        io::stdout().flush().ok().expect("flush() fail");
    }}
}

macro_rules! kb_fmt {
    ($n: ident) => {{
        let kb = 1024f64;
        match $n {
            $n if $n >= kb.powf(4_f64) => format!("{:.*} TB", 2, $n / kb.powf(4_f64)),
            $n if $n >= kb.powf(3_f64) => format!("{:.*} GB", 2, $n / kb.powf(3_f64)),
            $n if $n >= kb.powf(2_f64) => format!("{:.*} MB", 2, $n / kb.powf(2_f64)),
            $n if $n >= kb => format!("{:.*} KB", 2, $n / kb),
            _ => format!("{:.*} B", 0, $n)
        }
    }}
}

macro_rules! repeat {
    ($s: expr, $n: expr) => {{
        &repeat($s).take($n).collect::<String>()
    }}
}

static FORMAT: &'static str = "[=>-]";

// Output type format, indicate which format wil be used in
// the speed box.
#[derive(Debug)]
pub enum Units {
    Default,
    Bytes,
}

#[derive(Debug)]
pub struct ProgressBar {
    start_time: Timespec,
    units: Units,
    total: usize,
    current: usize,
    is_finish: bool,
    show_bar: bool,
    show_speed: bool,
    show_percent: bool,
    show_counter: bool,
    show_time_left: bool,
    bar_start: String,
    bar_current: String,
    bar_current_n: String,
    bar_remain: String,
    bar_end: String,
}

impl ProgressBar {
    /// Create a new ProgressBar with default configuration.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use std::thread;
    /// use pb::{ProgressBar, Units};
    ///
    /// let count = 1000;
    /// let mut pb = ProgressBar::new(count);
    /// pb.set_units(Units::Bytes);
    ///
    /// for _ in 0..count {
    ///    pb.inc();
    ///    thread::sleep_ms(100);
    /// }
    /// ```
    pub fn new(total: usize) -> ProgressBar {
        let mut pb = ProgressBar {
            total: total,
            current: 0,
            start_time: time::get_time(),
            units: Units::Default,
            is_finish: false,
            show_bar: true,
            show_speed: false,
            show_percent: true,
            show_counter: true,
            show_time_left: true,
            bar_start: String::new(),
            bar_current: String::new(),
            bar_current_n: String::new(),
            bar_remain: String::new(),
            bar_end: String::new(),
        };
        pb.format(FORMAT);
        pb
    }

    /// set units, default is simple numbers
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use pb::{ProgressBar, Units};
    ///
    /// let mut pb = ProgressBar::new(n_bytes);
    /// pb.set_units(Units::Bytes);
    /// ```
    pub fn set_units(&mut self, u: Units) {
        self.units = u;
    }

    /// Set custom format to the drawing bar, default is "[=>-]"
    ///
    /// # Examples
    ///
    /// ```no_run
    /// pb.format("[=>_]")
    /// ```
    pub fn format(&mut self, fmt: &str) {
        if fmt.len() >= 5 {
            let v: Vec<&str> = fmt.split("").collect();
            self.bar_start = v[1].to_string();
            self.bar_current = v[2].to_string();
            self.bar_current_n = v[3].to_string();
            self.bar_remain = v[4].to_string();
            self.bar_end = v[5].to_string();
        }
    }

    /// Add to current value
    pub fn add(&mut self, i: usize) -> usize {
        self.current += i;
        if self.current <= self.total {
            self.draw()
        };
        self.current
    }

    /// Increment current value
    pub fn inc(&mut self) -> usize {
        return self.add(1);
    }

    fn draw(&self) {
        let tty_size = terminal_size();
        let width = if let Some((Width(w), _)) = tty_size {
            w as usize
        } else {
            80
        };
        let mut base = String::new();
        let mut suffix = String::new();
        let mut prefix = String::new();
        let mut out;
        // precent box
        if self.show_percent {
            let percent = self.current as f64 / (self.total as f64 / 100f64);
            suffix = suffix + &format!(" {:.*} % ", 2, percent);
        }
        // speed box
        if !self.show_speed {
            let from_start = (time::get_time() - self.start_time).num_nanoseconds().unwrap() as f64;
            let sec_nano = Duration::seconds(1).num_nanoseconds().unwrap() as f64;
            let speed = self.current as f64 / (from_start / sec_nano);
            suffix = match self.units {
                Units::Default => suffix + &format!("{}/s ", speed),
                Units::Bytes => suffix + &format!("{}/s ", kb_fmt!(speed)),
            };
        }
        // time left box
        if self.show_time_left {
            let from_start = time::get_time() - self.start_time;
            let sec_nano = Duration::seconds(1).num_nanoseconds().unwrap() as i32;
            let per_entry = from_start / self.current as i32;
            let mut left = per_entry * (self.total - self.current) as i32;
            left = (left / sec_nano) * sec_nano;
            if left.num_seconds() > 0 {
                if left.num_seconds() < Duration::minutes(1).num_seconds() {
                    suffix = suffix + &format!("{}s", left.num_seconds());
                } else {
                    suffix = suffix + &format!("{}m", left.num_minutes());
                }
            }
        }
        // counter box
        if self.show_counter {
            let (c, t) = (self.current as f64, self.total as f64);
            prefix = match self.units {
                Units::Default => format!("{} / {} ", c, t),
                Units::Bytes => format!("{} / {} ", kb_fmt!(c), kb_fmt!(t)),
            };
        }
        // bar box
        if self.show_bar {
            let size = width - (prefix.len() + suffix.len() + 3);
            if size > 0 {
                let curr_count =
                    ((self.current as f64 / self.total as f64) * size as f64).ceil() as usize;
                let rema_count = size - curr_count;
                base = self.bar_start.to_string();
                if rema_count > 0 {
                    base = base + repeat!(self.bar_current.as_ref(), curr_count - 1) +
                           &self.bar_current_n;
                } else {
                    base = base + repeat!(self.bar_current.as_ref(), curr_count);
                }
                base = base + repeat!(self.bar_remain.as_ref(), rema_count) + &self.bar_end;
            }
        }
        out = prefix + &base + &suffix;
        // pad
        if out.len() < width {
            let gap = width - out.len();
            out = out + repeat!(" ", gap);
        }
        // print
        printfl!("\r{}", out);
    }

    /// Calling finish manually will set current to total and draw
    /// the last time
    pub fn finish(&mut self) {
        if self.current < self.total {
            self.current = self.total;
            self.draw();
        }
        println!("");
        self.is_finish = true;
    }
}

// Implement io::Writer
impl Write for ProgressBar {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = buf.len();
        self.add(n);
        Ok(n)
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use pb::ProgressBar;

    #[test]
    fn add() {
        let mut pb = ProgressBar::new(10);
        pb.add(2);
        assert!(pb.current == 2,
                "should add the given `n` to current");
        assert!(pb.add(2) == pb.current,
                "add should return the current value");
    }

    #[test]
    fn inc() {
        let mut pb = ProgressBar::new(10);
        pb.inc();
        assert!(pb.current == 1, "should increment current by 1");
    }

    #[test]
    fn format() {
        let FORMAT = "[~> ]";
        let mut pb = ProgressBar::new(1);
        pb.format(FORMAT);
        assert!(pb.bar_start + &pb.bar_current + &pb.bar_current_n + &pb.bar_remain +
                &pb.bar_end == FORMAT);
    }

    #[test]
    fn finish() {
        let mut pb = ProgressBar::new(10);
        pb.finish();
        assert!(pb.current == pb.total,
                "should set current to total");
        assert!(pb.is_finish, "should set is_finish to true");
    }

    #[test]
    fn kb_fmt() {
        let kb = 1024f64;
        let mb = kb.powf(2f64);
        let gb = kb.powf(3f64);
        let tb = kb.powf(4f64);
        assert_eq!(kb_fmt!(kb), "1.00 KB");
        assert_eq!(kb_fmt!(mb), "1.00 MB");
        assert_eq!(kb_fmt!(gb), "1.00 GB");
        assert_eq!(kb_fmt!(tb), "1.00 TB");
    }
}
<|endoftext|>