<commit_before>extern crate rusoto;

use std::default::Default;
use std::error::Error;

use rusoto::{
    ProvideAwsCredentials,
    DispatchSignedRequest,
    Region,
};
use rusoto::kinesis::{
    KinesisClient,
    ListStreamsInput,
    DescribeStreamInput,
};

pub struct KinesisHelper<P, D> where P: ProvideAwsCredentials, D: DispatchSignedRequest {
    client: KinesisClient<P, D>,
}

impl <P, D>KinesisHelper<P, D> where P: ProvideAwsCredentials, D: DispatchSignedRequest {

    pub fn new(request_dispatcher: D, credentials_provider: P, region: Region) -> KinesisHelper<P, D> {

        KinesisHelper { client: KinesisClient::with_request_dispatcher(request_dispatcher, credentials_provider, region) }
    }

    pub fn list_streams(&self) -> Result<Vec<String>, Box<Error>> {

        let request = ListStreamsInput::default();
        let result = try!(self.client.list_streams(&request));
        Ok(result.stream_names)

    }

    pub fn describe_shards(&self, stream_name: &str) -> Result<Vec<String>, Box<Error>> {

        let stream = DescribeStreamInput {
            stream_name: stream_name.to_string(),
            limit: None,
            exclusive_start_shard_id: None,
        };

        let result = try!(self.client.describe_stream(&stream));
        Ok(result.stream_description.shards.iter().map(|x| &x.shard_id).cloned().collect())

    }

}
<commit_msg>Add get shard iterator<commit_after>extern crate rusoto;

use std::default::Default;
use std::error::Error;

use rusoto::{
    ProvideAwsCredentials,
    DispatchSignedRequest,
    Region,
};
use rusoto::kinesis::{
    KinesisClient,
    ListStreamsInput,
    DescribeStreamInput,
};

pub struct KinesisHelper<P, D> where P: ProvideAwsCredentials, D: DispatchSignedRequest {
    client: KinesisClient<P, D>,
}

impl <P, D>KinesisHelper<P, D> where P: ProvideAwsCredentials, D: DispatchSignedRequest {

    pub fn new(request_dispatcher: D, credentials_provider: P, region: Region) -> KinesisHelper<P, D> {

        KinesisHelper { client: KinesisClient::with_request_dispatcher(request_dispatcher, credentials_provider, region) }
    }

    pub fn list_streams(&self) -> Result<Vec<String>, Box<Error>> {

        let request = ListStreamsInput::default();
        let result = try!(self.client.list_streams(&request));
        Ok(result.stream_names)

    }

    pub fn describe_shards(&self, stream_name: &str) -> Result<Vec<String>, Box<Error>> {

        let stream = DescribeStreamInput {
            stream_name: stream_name.to_string(),
            limit: None,
            exclusive_start_shard_id: None,
        };

        let result = try!(self.client.describe_stream(&stream));
        Ok(result.stream_description.shards.iter().map(|x| &x.shard_id).cloned().collect())

    }

    pub fn get_shard_iterator(&self, stream_name: &str, shard_id: &str) -> Result<String, Box<Error>> {

        let input = GetShardIteratorInput {
            shard_id: shard_id.to_string(),
            shard_iterator_type: "TRIM_HORIZON",
            stream_name: stream_name.to_string(),
        };

        let result = try!(self.client.get_shard_iterator(&input));
        Ok(result.shard_iterator.unwrap())
    }

}
<|endoftext|>


<commit_before>//! Partially ordered elements with a least upper bound.

/// A bounded partially ordered type supporting joins and meets.
pub trait Lattice : PartialOrd {
    /// The smallest element of the type.
    fn min() -> Self;
    /// The largest element of the type.
    fn max() -> Self;
    /// The smallest element greater than both arguments.
    fn join(&self, &Self) -> Self;
    /// The largest element lesser than both arguments.
    fn meet(&self, &Self) -> Self;

    /// Advances self to the largest time indistinguishable under `frontier`.
    // TODO : add an example here demonstrating the result invariant.
    fn advance_by(&self, frontier: &[Self]) -> Option<Self> where Self: Sized{
        if frontier.len() > 0 {
            let mut result = self.join(&frontier[0]);
            for f in &frontier[1..] {
                result = result.meet(&self.join(f));
            }
            Some(result)
        }
        else {
            None
        }
    }
}

use timely::progress::nested::product::Product;

impl<T1: Lattice, T2: Lattice> Lattice for Product<T1, T2> {
    #[inline(always)]
    fn min() -> Self { Product::new(T1::min(), T2::min()) }
    #[inline(always)]
    fn max() -> Self { Product::new(T1::max(), T2::max()) }

    fn join(&self, other: &Product<T1, T2>) -> Product<T1, T2> {
        Product {
            outer: self.outer.join(&other.outer),
            inner: self.inner.join(&other.inner),
        }
    }
    fn meet(&self, other: &Product<T1, T2>) -> Product<T1, T2> {
        Product {
            outer: self.outer.meet(&other.outer),
            inner: self.inner.meet(&other.inner),
        }
    }
}

use timely::progress::timestamp::RootTimestamp;

impl Lattice for RootTimestamp {
    fn min() -> RootTimestamp { RootTimestamp }
    fn max() -> RootTimestamp { RootTimestamp }
    fn join(&self, _: &RootTimestamp) -> RootTimestamp { RootTimestamp }
    fn meet(&self, _: &RootTimestamp) -> RootTimestamp { RootTimestamp }
}

impl Lattice for usize {
    fn min() -> usize { usize::min_value() }
    fn max() -> usize { usize::max_value() }
    fn join(&self, other: &usize) -> usize { ::std::cmp::max(*self, *other) }
    fn meet(&self, other: &usize) -> usize { ::std::cmp::min(*self, *other) }
}

impl Lattice for u64 {
    fn min() -> u64 { u64::min_value() }
    fn max() -> u64 { u64::max_value() }
    fn join(&self, other: &u64) -> u64 { ::std::cmp::max(*self, *other) }
    fn meet(&self, other: &u64) -> u64 { ::std::cmp::min(*self, *other) }
}

impl Lattice for u32 {
    fn min() -> u32 { u32::min_value() }
    fn max() -> u32 { u32::max_value() }
    fn join(&self, other: &u32) -> u32 { ::std::cmp::max(*self, *other) }
    fn meet(&self, other: &u32) -> u32 { ::std::cmp::min(*self, *other) }
}

impl Lattice for i32 {
    fn min() -> i32 { i32::min_value() }
    fn max() -> i32 { i32::max_value() }
    fn join(&self, other: &i32) -> i32 { ::std::cmp::max(*self, *other) }
    fn meet(&self, other: &i32) -> i32 { ::std::cmp::min(*self, *other) }
}

impl Lattice for () {
    fn min() -> () { () }
    fn max() -> () { () }
    fn join(&self, _other: &()) -> () { () }
    fn meet(&self, _other: &()) -> () { () }
}

/// Extends `vector` to contain all joins of pairs of elements.
pub fn close_under_join<T: Lattice>(vector: &mut Vec<T>) {
    // compares each element to those elements after it.
    let mut first = 0;
    while first < vector.len() {
        let mut next = first + 1;
        while next < vector.len() {
            let lub = vector[first].join(&vector[next]);
            if !vector.contains(&lub) {
                vector.push(lub);
            }

            next += 1;
        }

        first += 1;
    }
}
<commit_msg>insist on inlining simple operations<commit_after>//! Partially ordered elements with a least upper bound.

/// A bounded partially ordered type supporting joins and meets.
pub trait Lattice : PartialOrd {
    /// The smallest element of the type.
    fn min() -> Self;
    /// The largest element of the type.
    fn max() -> Self;
    /// The smallest element greater than both arguments.
    fn join(&self, &Self) -> Self;
    /// The largest element lesser than both arguments.
    fn meet(&self, &Self) -> Self;

    /// Advances self to the largest time indistinguishable under `frontier`.
    // TODO : add an example here demonstrating the result invariant.
    #[inline(always)]
    fn advance_by(&self, frontier: &[Self]) -> Option<Self> where Self: Sized{
        if frontier.len() > 0 {
            let mut result = self.join(&frontier[0]);
            for f in &frontier[1..] {
                result = result.meet(&self.join(f));
            }
            Some(result)
        }
        else {
            None
        }
    }
}

use timely::progress::nested::product::Product;

impl<T1: Lattice, T2: Lattice> Lattice for Product<T1, T2> {
    #[inline(always)]
    fn min() -> Self { Product::new(T1::min(), T2::min()) }
    #[inline(always)]
    fn max() -> Self { Product::new(T1::max(), T2::max()) }
    #[inline(always)]
    fn join(&self, other: &Product<T1, T2>) -> Product<T1, T2> {
        Product {
            outer: self.outer.join(&other.outer),
            inner: self.inner.join(&other.inner),
        }
    }
    #[inline(always)]
    fn meet(&self, other: &Product<T1, T2>) -> Product<T1, T2> {
        Product {
            outer: self.outer.meet(&other.outer),
            inner: self.inner.meet(&other.inner),
        }
    }
}

use timely::progress::timestamp::RootTimestamp;

impl Lattice for RootTimestamp {
    #[inline(always)]
    fn min() -> RootTimestamp { RootTimestamp }
    #[inline(always)]
    fn max() -> RootTimestamp { RootTimestamp }
    #[inline(always)]
    fn join(&self, _: &RootTimestamp) -> RootTimestamp { RootTimestamp }
    #[inline(always)]
    fn meet(&self, _: &RootTimestamp) -> RootTimestamp { RootTimestamp }
}

impl Lattice for usize {
    #[inline(always)]
    fn min() -> usize { usize::min_value() }
    #[inline(always)]
    fn max() -> usize { usize::max_value() }
    #[inline(always)]
    fn join(&self, other: &usize) -> usize { ::std::cmp::max(*self, *other) }
    #[inline(always)]
    fn meet(&self, other: &usize) -> usize { ::std::cmp::min(*self, *other) }
}

impl Lattice for u64 {
    #[inline(always)]
    fn min() -> u64 { u64::min_value() }
    #[inline(always)]
    fn max() -> u64 { u64::max_value() }
    #[inline(always)]
    fn join(&self, other: &u64) -> u64 { ::std::cmp::max(*self, *other) }
    #[inline(always)]
    fn meet(&self, other: &u64) -> u64 { ::std::cmp::min(*self, *other) }
}

impl Lattice for u32 {
    #[inline(always)]
    fn min() -> u32 { u32::min_value() }
    #[inline(always)]
    fn max() -> u32 { u32::max_value() }
    #[inline(always)]
    fn join(&self, other: &u32) -> u32 { ::std::cmp::max(*self, *other) }
    #[inline(always)]
    fn meet(&self, other: &u32) -> u32 { ::std::cmp::min(*self, *other) }
}

impl Lattice for i32 {
    #[inline(always)]
    fn min() -> i32 { i32::min_value() }
    #[inline(always)]
    fn max() -> i32 { i32::max_value() }
    #[inline(always)]
    fn join(&self, other: &i32) -> i32 { ::std::cmp::max(*self, *other) }
    #[inline(always)]
    fn meet(&self, other: &i32) -> i32 { ::std::cmp::min(*self, *other) }
}

impl Lattice for () {
    #[inline(always)]
    fn min() -> () { () }
    #[inline(always)]
    fn max() -> () { () }
    #[inline(always)]
    fn join(&self, _other: &()) -> () { () }
    #[inline(always)]
    fn meet(&self, _other: &()) -> () { () }
}

/// Extends `vector` to contain all joins of pairs of elements.
pub fn close_under_join<T: Lattice>(vector: &mut Vec<T>) {
    // compares each element to those elements after it.
    let mut first = 0;
    while first < vector.len() {
        let mut next = first + 1;
        while next < vector.len() {
            let lub = vector[first].join(&vector[next]);
            if !vector.contains(&lub) {
                vector.push(lub);
            }

            next += 1;
        }

        first += 1;
    }
}
<|endoftext|>


<commit_before>
import option::none;
import option::some;
import util::orb;

type vbuf = rustrt::vbuf;

type operator2[T, U, V] = fn(&T, &U) -> V ;

type array[T] = vec[mutable? T];

native "rust" mod rustrt {
    type vbuf;
    fn vec_buf[T](vec[T] v, uint offset) -> vbuf;
    fn vec_len[T](vec[T] v) -> uint;

        /**
         * Sometimes we modify the vec internal data via vec_buf and need to
         * update the vec's fill length accordingly.
         */
        fn vec_len_set[T](vec[T] v, uint n);

        /**
         * The T in vec_alloc[T, U] is the type of the vec to allocate.  The
         * U is the type of an element in the vec.  So to allocate a vec[U] we
         * want to invoke this as vec_alloc[vec[U], U].
         */
        fn vec_alloc[T, U](uint n_elts) -> vec[U];
    fn vec_alloc_mut[T, U](uint n_elts) -> vec[mutable U];
    fn refcount[T](vec[T] v) -> uint;
    fn vec_print_debug_info[T](vec[T] v);
    fn vec_from_vbuf[T](vbuf v, uint n_elts) -> vec[T];
    fn unsafe_vec_to_mut[T](vec[T] v) -> vec[mutable T];
}

fn alloc[T](uint n_elts) -> vec[T] {
    ret rustrt::vec_alloc[vec[T], T](n_elts);
}

fn alloc_mut[T](uint n_elts) -> vec[mutable T] {
    ret rustrt::vec_alloc_mut[vec[mutable T], T](n_elts);
}

fn refcount[T](array[T] v) -> uint {
    auto r = rustrt::refcount[T](v);
    if (r == dbg::const_refcount) {
        ret r;
    } else {
        // -2 because calling this function and the native function both
        // incremented the refcount.

        ret r - 2u;
    }
}

fn vec_from_vbuf[T](vbuf v, uint n_elts) -> vec[T] {
    ret rustrt::vec_from_vbuf[T](v, n_elts);
}

// FIXME: Remove me; this is a botch to get around rustboot's bad typechecker.
fn empty[T]() -> vec[T] { ret alloc[T](0u); }

// FIXME: Remove me; this is a botch to get around rustboot's bad typechecker.
fn empty_mut[T]() -> vec[mutable T] { ret alloc_mut[T](0u); }

type init_op[T] = fn(uint) -> T ;

fn init_fn[T](&init_op[T] op, uint n_elts) -> vec[T] {
    let vec[T] v = alloc[T](n_elts);
    let uint i = 0u;
    while (i < n_elts) { v += [op(i)]; i += 1u; }
    ret v;
}

fn init_fn_mut[T](&init_op[T] op, uint n_elts) -> vec[mutable T] {
    let vec[mutable T] v = alloc_mut[T](n_elts);
    let uint i = 0u;
    while (i < n_elts) { v += [mutable op(i)]; i += 1u; }
    ret v;
}

fn init_elt[T](&T t, uint n_elts) -> vec[T] {
    /**
     * FIXME (issue #81): should be:
     *
     * fn elt_op[T](&T x, uint i) -> T { ret x; }
     * let init_op[T] inner = bind elt_op[T](t, _);
     * ret init_fn[T](inner, n_elts);
     */

    let vec[T] v = alloc[T](n_elts);
    let uint i = n_elts;
    while (i > 0u) { i -= 1u; v += [t]; }
    ret v;
}

fn init_elt_mut[T](&T t, uint n_elts) -> vec[mutable T] {
    let vec[mutable T] v = alloc_mut[T](n_elts);
    let uint i = n_elts;
    while (i > 0u) { i -= 1u; v += [mutable t]; }
    ret v;
}

fn buf[T](array[T] v) -> vbuf { ret rustrt::vec_buf[T](v, 0u); }

fn len[T](array[T] v) -> uint { ret rustrt::vec_len[T](v); }

fn len_set[T](array[T] v, uint n) { rustrt::vec_len_set[T](v, n); }

fn buf_off[T](array[T] v, uint offset) -> vbuf {
    assert (offset < len[T](v));
    ret rustrt::vec_buf[T](v, offset);
}

fn print_debug_info[T](array[T] v) { rustrt::vec_print_debug_info[T](v); }

// FIXME: typestate precondition (list is non-empty)
// Returns the last element of v.
fn last[T](array[T] v) -> option::t[T] {
    auto l = len[T](v);
    if (l == 0u) { ret none[T]; }
    ret some[T](v.(l - 1u));
}

// Returns elements from [start..end) from v.
fn slice[T](array[T] v, uint start, uint end) -> vec[T] {
    assert (start <= end);
    assert (end <= len[T](v));
    auto result = alloc[T](end - start);
    let uint i = start;
    while (i < end) { result += [v.(i)]; i += 1u; }
    ret result;
}

// FIXME: Should go away eventually.
fn slice_mut[T](array[T] v, uint start, uint end) -> vec[mutable T] {
    assert (start <= end);
    assert (end <= len[T](v));
    auto result = alloc_mut[T](end - start);
    let uint i = start;
    while (i < end) { result += [mutable v.(i)]; i += 1u; }
    ret result;
}

fn shift[T](&mutable array[T] v) -> T {
    auto ln = len[T](v);
    assert (ln > 0u);
    auto e = v.(0);
    v = slice[T](v, 1u, ln);
    ret e;
}

fn pop[T](&mutable array[T] v) -> T {
    auto ln = len[T](v);
    assert (ln > 0u);
    ln -= 1u;
    auto e = v.(ln);
    v = slice[T](v, 0u, ln);
    ret e;
}

fn top[T](&array[T] v) -> T {
    auto ln = len[T](v);
    assert (ln > 0u);
    ret v.(ln - 1u);
}

fn push[T](&mutable array[T] v, &T t) { v += [t]; }

fn unshift[T](&mutable array[T] v, &T t) {
    auto rs = alloc[T](len[T](v) + 1u);
    rs += [t];
    rs += v;
    v = rs;
}

fn grow[T](&mutable array[T] v, uint n, &T initval) {
    let uint i = n;
    while (i > 0u) { i -= 1u; v += [initval]; }
}

fn grow_set[T](&mutable vec[mutable T] v, uint index, &T initval, &T val) {
    auto length = vec::len(v);
    if (index >= length) { grow(v, index - length + 1u, initval); }
    v.(index) = val;
}

fn grow_init_fn[T](&mutable array[T] v, uint n, fn() -> T  init_fn) {
    let uint i = n;
    while (i > 0u) { i -= 1u; v += [init_fn()]; }
}

fn grow_init_fn_set[T](&array[T] v, uint index, fn() -> T  init_fn, &T val) {
    auto length = vec::len(v);
    if (index >= length) { grow_init_fn(v, index - length + 1u, init_fn); }
    v.(index) = val;
}

fn map[T, U](&fn(&T) -> U  f, &vec[T] v) -> vec[U] {
    let vec[U] rs = alloc[U](len[T](v));
    for (T ve in v) { rs += [f(ve)]; }
    ret rs;
}

fn filter_map[T, U](&fn(&T) -> option::t[U]  f, &vec[T] v) -> vec[U] {
    let vec[U] rs = [];
    for (T ve in v) {
        alt (f(ve)) { case (some(?elt)) { rs += [elt]; } case (none) { } }
    }
    ret rs;
}

fn map2[T, U, V](&operator2[T, U, V] f, &vec[T] v0, &vec[U] v1) -> vec[V] {
    auto v0_len = len[T](v0);
    if (v0_len != len[U](v1)) { fail; }
    let vec[V] u = alloc[V](v0_len);
    auto i = 0u;
    while (i < v0_len) { u += [f({ v0.(i) }, { v1.(i) })]; i += 1u; }
    ret u;
}

fn find[T](fn(&T) -> bool  f, &vec[T] v) -> option::t[T] {
    for (T elt in v) { if (f(elt)) { ret some[T](elt); } }
    ret none[T];
}

fn position[T](&T x, &array[T] v) -> option::t[uint] {
    let uint i = 0u;
    while (i < len(v)) {
        if (x == v.(i)) { ret some[uint](i); }
        i += 1u;
    }
    ret none[uint];
}

fn position_pred[T](fn (&T) -> bool f, &vec[T] v) -> option::t[uint] {
    let uint i = 0u;
    while (i < len(v)) {
        if (f(v.(i))) { ret some[uint](i); }
        i += 1u;
    }
    ret none[uint];
}

fn member[T](&T x, &array[T] v) -> bool {
    for (T elt in v) { if (x == elt) { ret true; } }
    ret false;
}

fn count[T](&T x, &array[T] v) -> uint {
    auto cnt = 0u;
    for (T elt in v) { if (x == elt) { cnt += 1u; } }
    ret cnt;
}

fn foldl[T, U](fn(&U, &T) -> U  p, &U z, &vec[T] v) -> U {
    auto sz = len[T](v);
    if (sz == 0u) {
        ret z;
    } else {
        auto rest = slice[T](v, 1u, sz);
        ret p(foldl[T, U](p, z, rest), v.(0));
    }
}

fn unzip[T, U](&vec[tup(T, U)] v) -> tup(vec[T], vec[U]) {
    auto sz = len[tup(T, U)](v);
    if (sz == 0u) {
        ret tup(alloc[T](0u), alloc[U](0u));
    } else {
        auto rest = slice[tup(T, U)](v, 1u, sz);
        auto tl = unzip[T, U](rest);
        auto a = [v.(0)._0];
        auto b = [v.(0)._1];
        ret tup(a + tl._0, b + tl._1);
    }
}

// FIXME make the lengths being equal a constraint
fn zip[T, U](&vec[T] v, &vec[U] u) -> vec[tup(T, U)] {
    auto sz = len[T](v);
    assert (sz == len[U](u));
    if (sz == 0u) {
        ret alloc[tup(T, U)](0u);
    } else {
        auto rest = zip[T, U](slice[T](v, 1u, sz), slice[U](u, 1u, sz));
        vec::push(rest, tup(v.(0), u.(0)));
        ret rest;
    }
}

fn or(&vec[bool] v) -> bool {
    auto f = orb;
    ret vec::foldl[bool, bool](f, false, v);
}

fn clone[T](&vec[T] v) -> vec[T] { ret slice[T](v, 0u, len[T](v)); }

fn plus_option[T](&mutable vec[T] v, &option::t[T] o) {
    alt (o) { case (none) { } case (some(?x)) { v += [x]; } }
}

fn cat_options[T](&vec[option::t[T]] v) -> vec[T] {
    let vec[T] rs = [];
    for (option::t[T] o in v) {
        alt (o) { case (none) { } case (some(?t)) { rs += [t]; } }
    }
    ret rs;
}

// TODO: Remove in favor of built-in "freeze" operation when it's implemented.
fn freeze[T](vec[mutable T] v) -> vec[T] {
    let vec[T] result = [];
    for (T elem in v) { result += [elem]; }
    ret result;
}

// Swaps two elements in a vector
fn swap[T](&vec[mutable T] v, uint a, uint b) {
    let T t = v.(a);
    v.(a) = v.(b);
    v.(b) = t;
}

// In place vector reversal
fn reverse[T](&vec[mutable T] v) {
    let uint i = 0u;
    auto ln = len[T](v);
    while (i < ln / 2u) { swap(v, i, ln - i - 1u); i += 1u; }
}

// Functional vector reversal. Returns a reversed copy of v.
fn reversed[T](vec[T] v) -> vec[T] {
    let vec[T] rs = [];
    auto i = len[T](v);
    if (i == 0u) { ret rs; } else { i -= 1u; }
    while (i != 0u) { push[T](rs, v.(i)); i -= 1u; }
    push[T](rs, v.(0));
    ret rs;
}

/// Truncates the vector to length `new_len`.
/// FIXME: This relies on a typechecker bug (covariance vs. invariance).
fn truncate[T](&mutable vec[mutable? T] v, uint new_len) {
    v = slice[T](v, 0u, new_len);
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Comments.<commit_after>
import option::none;
import option::some;
import util::orb;

type vbuf = rustrt::vbuf;

type operator2[T, U, V] = fn(&T, &U) -> V ;

type array[T] = vec[mutable? T];

native "rust" mod rustrt {
    type vbuf;
    fn vec_buf[T](vec[T] v, uint offset) -> vbuf;
    fn vec_len[T](vec[T] v) -> uint;

        /**
         * Sometimes we modify the vec internal data via vec_buf and need to
         * update the vec's fill length accordingly.
         */
        fn vec_len_set[T](vec[T] v, uint n);

        /**
         * The T in vec_alloc[T, U] is the type of the vec to allocate.  The
         * U is the type of an element in the vec.  So to allocate a vec[U] we
         * want to invoke this as vec_alloc[vec[U], U].
         */
        fn vec_alloc[T, U](uint n_elts) -> vec[U];
    fn vec_alloc_mut[T, U](uint n_elts) -> vec[mutable U];
    fn refcount[T](vec[T] v) -> uint;
    fn vec_print_debug_info[T](vec[T] v);
    fn vec_from_vbuf[T](vbuf v, uint n_elts) -> vec[T];
    fn unsafe_vec_to_mut[T](vec[T] v) -> vec[mutable T];
}

fn alloc[T](uint n_elts) -> vec[T] {
    ret rustrt::vec_alloc[vec[T], T](n_elts);
}

fn alloc_mut[T](uint n_elts) -> vec[mutable T] {
    ret rustrt::vec_alloc_mut[vec[mutable T], T](n_elts);
}

fn refcount[T](array[T] v) -> uint {
    auto r = rustrt::refcount[T](v);
    if (r == dbg::const_refcount) {
        ret r;
    } else {
        // -2 because calling this function and the native function both
        // incremented the refcount.

        ret r - 2u;
    }
}

fn vec_from_vbuf[T](vbuf v, uint n_elts) -> vec[T] {
    ret rustrt::vec_from_vbuf[T](v, n_elts);
}

// FIXME: Remove me; this is a botch to get around rustboot's bad typechecker.
fn empty[T]() -> vec[T] { ret alloc[T](0u); }

// FIXME: Remove me; this is a botch to get around rustboot's bad typechecker.
fn empty_mut[T]() -> vec[mutable T] { ret alloc_mut[T](0u); }

type init_op[T] = fn(uint) -> T ;

fn init_fn[T](&init_op[T] op, uint n_elts) -> vec[T] {
    let vec[T] v = alloc[T](n_elts);
    let uint i = 0u;
    while (i < n_elts) { v += [op(i)]; i += 1u; }
    ret v;
}

fn init_fn_mut[T](&init_op[T] op, uint n_elts) -> vec[mutable T] {
    let vec[mutable T] v = alloc_mut[T](n_elts);
    let uint i = 0u;
    while (i < n_elts) { v += [mutable op(i)]; i += 1u; }
    ret v;
}

// init_elt: creates and returns a vector of length n_elts, filled with
// that many copies of element t.
fn init_elt[T](&T t, uint n_elts) -> vec[T] {
    /**
     * FIXME (issue #81): should be:
     *
     * fn elt_op[T](&T x, uint i) -> T { ret x; }
     * let init_op[T] inner = bind elt_op[T](t, _);
     * ret init_fn[T](inner, n_elts);
     */

    let vec[T] v = alloc[T](n_elts);
    let uint i = n_elts;
    while (i > 0u) { i -= 1u; v += [t]; }
    ret v;
}

fn init_elt_mut[T](&T t, uint n_elts) -> vec[mutable T] {
    let vec[mutable T] v = alloc_mut[T](n_elts);
    let uint i = n_elts;
    while (i > 0u) { i -= 1u; v += [mutable t]; }
    ret v;
}

fn buf[T](array[T] v) -> vbuf { ret rustrt::vec_buf[T](v, 0u); }

fn len[T](array[T] v) -> uint { ret rustrt::vec_len[T](v); }

fn len_set[T](array[T] v, uint n) { rustrt::vec_len_set[T](v, n); }

fn buf_off[T](array[T] v, uint offset) -> vbuf {
    assert (offset < len[T](v));
    ret rustrt::vec_buf[T](v, offset);
}

fn print_debug_info[T](array[T] v) { rustrt::vec_print_debug_info[T](v); }

// FIXME: typestate precondition (list is non-empty)
// Returns the last element of v.
fn last[T](array[T] v) -> option::t[T] {
    auto l = len[T](v);
    if (l == 0u) { ret none[T]; }
    ret some[T](v.(l - 1u));
}

// Returns elements from [start..end) from v.
fn slice[T](array[T] v, uint start, uint end) -> vec[T] {
    assert (start <= end);
    assert (end <= len[T](v));
    auto result = alloc[T](end - start);
    let uint i = start;
    while (i < end) { result += [v.(i)]; i += 1u; }
    ret result;
}

// FIXME: Should go away eventually.
fn slice_mut[T](array[T] v, uint start, uint end) -> vec[mutable T] {
    assert (start <= end);
    assert (end <= len[T](v));
    auto result = alloc_mut[T](end - start);
    let uint i = start;
    while (i < end) { result += [mutable v.(i)]; i += 1u; }
    ret result;
}

fn shift[T](&mutable array[T] v) -> T {
    auto ln = len[T](v);
    assert (ln > 0u);
    auto e = v.(0);
    v = slice[T](v, 1u, ln);
    ret e;
}

fn pop[T](&mutable array[T] v) -> T {
    auto ln = len[T](v);
    assert (ln > 0u);
    ln -= 1u;
    auto e = v.(ln);
    v = slice[T](v, 0u, ln);
    ret e;
}

fn top[T](&array[T] v) -> T {
    auto ln = len[T](v);
    assert (ln > 0u);
    ret v.(ln - 1u);
}

fn push[T](&mutable array[T] v, &T t) { v += [t]; }

fn unshift[T](&mutable array[T] v, &T t) {
    auto rs = alloc[T](len[T](v) + 1u);
    rs += [t];
    rs += v;
    v = rs;
}

fn grow[T](&mutable array[T] v, uint n, &T initval) {
    let uint i = n;
    while (i > 0u) { i -= 1u; v += [initval]; }
}

fn grow_set[T](&mutable vec[mutable T] v, uint index, &T initval, &T val) {
    auto length = vec::len(v);
    if (index >= length) { grow(v, index - length + 1u, initval); }
    v.(index) = val;
}

fn grow_init_fn[T](&mutable array[T] v, uint n, fn() -> T  init_fn) {
    let uint i = n;
    while (i > 0u) { i -= 1u; v += [init_fn()]; }
}

fn grow_init_fn_set[T](&array[T] v, uint index, fn() -> T  init_fn, &T val) {
    auto length = vec::len(v);
    if (index >= length) { grow_init_fn(v, index - length + 1u, init_fn); }
    v.(index) = val;
}

fn map[T, U](&fn(&T) -> U  f, &vec[T] v) -> vec[U] {
    let vec[U] rs = alloc[U](len[T](v));
    for (T ve in v) { rs += [f(ve)]; }
    ret rs;
}

fn filter_map[T, U](&fn(&T) -> option::t[U]  f, &vec[T] v) -> vec[U] {
    let vec[U] rs = [];
    for (T ve in v) {
        alt (f(ve)) { case (some(?elt)) { rs += [elt]; } case (none) { } }
    }
    ret rs;
}

fn map2[T, U, V](&operator2[T, U, V] f, &vec[T] v0, &vec[U] v1) -> vec[V] {
    auto v0_len = len[T](v0);
    if (v0_len != len[U](v1)) { fail; }
    let vec[V] u = alloc[V](v0_len);
    auto i = 0u;
    while (i < v0_len) { u += [f({ v0.(i) }, { v1.(i) })]; i += 1u; }
    ret u;
}

fn find[T](fn(&T) -> bool  f, &vec[T] v) -> option::t[T] {
    for (T elt in v) { if (f(elt)) { ret some[T](elt); } }
    ret none[T];
}

fn position[T](&T x, &array[T] v) -> option::t[uint] {
    let uint i = 0u;
    while (i < len(v)) {
        if (x == v.(i)) { ret some[uint](i); }
        i += 1u;
    }
    ret none[uint];
}

fn position_pred[T](fn (&T) -> bool f, &vec[T] v) -> option::t[uint] {
    let uint i = 0u;
    while (i < len(v)) {
        if (f(v.(i))) { ret some[uint](i); }
        i += 1u;
    }
    ret none[uint];
}

fn member[T](&T x, &array[T] v) -> bool {
    for (T elt in v) { if (x == elt) { ret true; } }
    ret false;
}

fn count[T](&T x, &array[T] v) -> uint {
    auto cnt = 0u;
    for (T elt in v) { if (x == elt) { cnt += 1u; } }
    ret cnt;
}

fn foldl[T, U](fn(&U, &T) -> U  p, &U z, &vec[T] v) -> U {
    auto sz = len[T](v);
    if (sz == 0u) {
        ret z;
    } else {
        auto rest = slice[T](v, 1u, sz);
        ret p(foldl[T, U](p, z, rest), v.(0));
    }
}

fn unzip[T, U](&vec[tup(T, U)] v) -> tup(vec[T], vec[U]) {
    auto sz = len[tup(T, U)](v);
    if (sz == 0u) {
        ret tup(alloc[T](0u), alloc[U](0u));
    } else {
        auto rest = slice[tup(T, U)](v, 1u, sz);
        auto tl = unzip[T, U](rest);
        auto a = [v.(0)._0];
        auto b = [v.(0)._1];
        ret tup(a + tl._0, b + tl._1);
    }
}

// FIXME make the lengths being equal a constraint
fn zip[T, U](&vec[T] v, &vec[U] u) -> vec[tup(T, U)] {
    auto sz = len[T](v);
    assert (sz == len[U](u));
    if (sz == 0u) {
        ret alloc[tup(T, U)](0u);
    } else {
        auto rest = zip[T, U](slice[T](v, 1u, sz), slice[U](u, 1u, sz));
        vec::push(rest, tup(v.(0), u.(0)));
        ret rest;
    }
}

fn or(&vec[bool] v) -> bool {
    auto f = orb;
    ret vec::foldl[bool, bool](f, false, v);
}

fn clone[T](&vec[T] v) -> vec[T] { ret slice[T](v, 0u, len[T](v)); }

fn plus_option[T](&mutable vec[T] v, &option::t[T] o) {
    alt (o) { case (none) { } case (some(?x)) { v += [x]; } }
}

fn cat_options[T](&vec[option::t[T]] v) -> vec[T] {
    let vec[T] rs = [];
    for (option::t[T] o in v) {
        alt (o) { case (none) { } case (some(?t)) { rs += [t]; } }
    }
    ret rs;
}

// TODO: Remove in favor of built-in "freeze" operation when it's implemented.
fn freeze[T](vec[mutable T] v) -> vec[T] {
    let vec[T] result = [];
    for (T elem in v) { result += [elem]; }
    ret result;
}

// Swaps two elements in a vector
fn swap[T](&vec[mutable T] v, uint a, uint b) {
    let T t = v.(a);
    v.(a) = v.(b);
    v.(b) = t;
}

// In place vector reversal
fn reverse[T](&vec[mutable T] v) {
    let uint i = 0u;
    auto ln = len[T](v);
    while (i < ln / 2u) { swap(v, i, ln - i - 1u); i += 1u; }
}

// Functional vector reversal. Returns a reversed copy of v.
fn reversed[T](vec[T] v) -> vec[T] {
    let vec[T] rs = [];
    auto i = len[T](v);
    if (i == 0u) { ret rs; } else { i -= 1u; }
    while (i != 0u) { push[T](rs, v.(i)); i -= 1u; }
    push[T](rs, v.(0));
    ret rs;
}

/// Truncates the vector to length `new_len`.
/// FIXME: This relies on a typechecker bug (covariance vs. invariance).
fn truncate[T](&mutable vec[mutable? T] v, uint new_len) {
    v = slice[T](v, 0u, new_len);
}
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::*;
use std::mem;
use std::slice;
use std::thread;

use super::FONT;
use super::Event;
use super::Color;

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: i32,
    /// The y coordinate of the window
    y: i32,
    /// The width of the window
    w: u32,
    /// The height of the window
    h: u32,
    /// The title of the window
    t: String,
    /// The input scheme
    file: File,
    /// Window data
    data: Box<[Color]>,
}

impl Window {
    /// Create a new window
    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Box<Self>> {
        match File::open(&format!("orbital:/{}/{}/{}/{}/{}", x, y, w, h, title)) {
            Ok(file) => {
                Some(box Window {
                    x: x,
                    y: y,
                    w: w,
                    h: h,
                    t: title.to_string(),
                    file: file,
                    data: vec![Color::rgb(0, 0, 0); (w * h * 4) as usize].into_boxed_slice(),
                })
            }
            Err(_) => None,
        }
    }

    // TODO: Replace with smarter mechanism, maybe a move event?
    pub fn sync_path(&mut self) {
        if let Ok(path) = self.file.path() {
            // orbital:/x/y/w/h/t
            if let Some(path_str) = path.to_str() {
                let mut parts = path_str.split('/').skip(1);
                if let Some(x) = parts.next() {
                    self.x = x.parse::<i32>().unwrap_or(0);
                }
                if let Some(y) = parts.next() {
                    self.y = y.parse::<i32>().unwrap_or(0);
                }
                if let Some(w) = parts.next() {
                    self.w = w.parse::<u32>().unwrap_or(0);
                }
                if let Some(h) = parts.next() {
                    self.h = h.parse::<u32>().unwrap_or(0);
                }
            }
        }
    }

    /// Get x
    // TODO: Sync with window movements
    pub fn x(&self) -> i32 {
        self.x
    }

    /// Get y
    // TODO: Sync with window movements
    pub fn y(&self) -> i32 {
        self.y
    }

    /// Get width
    pub fn width(&self) -> u32 {
        self.w
    }

    /// Get height
    pub fn height(&self) -> u32 {
        self.h
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set title
    pub fn set_title(&mut self, _: &str) {
        // TODO
    }

    /// Draw a pixel
    pub fn pixel(&mut self, x: i32, y: i32, color: Color) {
        if x >= 0 && y >= 0 && x < self.w as i32 && y < self.h as i32 {
            let new = color.data;

            let alpha = (new >> 24) & 0xFF;
            if alpha > 0 {
                let old = &mut self.data[y as usize * self.w as usize + x as usize].data;
                if alpha >= 255 {
                    *old = new;
                } else {
                    let n_r = (((new >> 16) & 0xFF) * alpha) >> 8;
                    let n_g = (((new >> 8) & 0xFF) * alpha) >> 8;
                    let n_b = ((new & 0xFF) * alpha) >> 8;

                    let n_alpha = 255 - alpha;
                    let o_a = (((*old >> 24) & 0xFF) * n_alpha) >> 8;
                    let o_r = (((*old >> 16) & 0xFF) * n_alpha) >> 8;
                    let o_g = (((*old >> 8) & 0xFF) * n_alpha) >> 8;
                    let o_b = ((*old & 0xFF) * n_alpha) >> 8;

                    *old = ((o_a << 24) | (o_r << 16) | (o_g << 8) | o_b) + ((alpha << 24) | (n_r << 16) | (n_g << 8) | n_b);
                }
            }
        }
    }

    /// Draw a character, using the loaded font
    pub fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
        let mut offset = (c as usize) * 16;
        for row in 0..16 {
            let row_data;
            if offset < FONT.len() {
                row_data = FONT[offset];
            } else {
                row_data = 0;
            }

            for col in 0..8 {
                let pixel = (row_data >> (7 - col)) & 1;
                if pixel > 0 {
                    self.pixel(x + col as i32, y + row as i32, color);
                }
            }
            offset += 1;
        }
    }

    // TODO move, resize, set_title

    /// Set entire window to a color
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn set(&mut self, color: Color) {
        for mut d in self.data.iter_mut() {
            *d = color;
        }
    }

    // Allows to draw a left border in the window
    // x_limit is the left limit of the border!!!
    pub fn set_border_left(&mut self, x_limit: i32, color: Color, density: i32) {
        for y in 0..self.height {
            for x in x_limit..(x_limit + density) {
                self.pixel(x, y as i32, color);
            }
        }
    }

    // Allows to draw a right border in the window
    // x_limit is the left limit of the border!!!
    pub fn set_border_right(&mut self, x_limit: i32, color: Color, density: i32) {
        for y in 0..self.height {
            for x in x_limit..(x_limit + density) {
                let new_x : i32 = self.width as i32;
                self.pixel((new_x - x), y as i32, color);
            }
        }
    }

    // Allows to draw a top border in the window
    // x_limit is the top limit of the border!!!
    pub fn set_border_top(&mut self, y_limit: i32, color: Color, density: u32) {
        for x in 0..self.width {
            for y in y_limit..(y_limit + density) {
                self.pixel(x, y, color);
            }
        }
    }

    // Allows to draw a bottom border in the window
    // x_limit is the top limit of the border!!!
    pub fn set_border_bottom(&mut self, color: Color, density: u32) {
        for x in 0..self.x {
            for y in 0..(y_limit + density) {
                self.pixel(x, self.y - y, color);
            }
        }
    }

    /// Draw rectangle
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn rect(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, color: Color) {
        for y in start_y..start_y + h as i32 {
            for x in start_x..start_x + w as i32 {
                self.pixel(x, y, color);
            }
        }
    }

    /// Display an image
    // TODO: Improve speed
    pub fn image(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, data: &[Color]) {
        let mut i = 0;
        for y in start_y..start_y + h as i32 {
            for x in start_x..start_x + w as i32 {
                if i < data.len() {
                    self.pixel(x, y, data[i])
                }
                i += 1;
            }
        }
    }

    /// Return a iterator over events
    fn events_inner(&mut self, wait: bool) -> EventIter {
        let mut iter = EventIter {
            events: [Event::new(); 128],
            i: 0,
            count: 0,
        };

        'blocking: loop {
            //Should it be cleared? iter.events = [Event::new(); 128];
            match self.file.read(unsafe {
                slice::from_raw_parts_mut(iter.events.as_mut_ptr() as *mut u8, iter.events.len() * mem::size_of::<Event>())
            }){
                Ok(0) => if wait {
                    thread::yield_now();
                } else {
                    break 'blocking;
                },
                Ok(count) => {
                    iter.count = count/mem::size_of::<Event>();
                    break 'blocking;
                },
                Err(_) => break 'blocking,
            }
        }

        iter
    }

    /// Blocking iterator over events
    pub fn events(&mut self) -> EventIter {
        self.events_inner(true)
    }

    /// Nonblocking iterator over events
    pub fn events_no_wait(&mut self) -> EventIter {
        self.events_inner(false)
    }

    /// Flip the window buffer
    pub fn sync(&mut self) -> bool {
        self.file.write(unsafe {
            slice::from_raw_parts(self.data.as_ptr() as *const u8, self.data.len() * mem::size_of::<Color>())
        }).is_ok()
    }
}

/// Event iterator
pub struct EventIter {
    events: [Event; 128],
    i: usize,
    count: usize,
}

impl Iterator for EventIter {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        if self.i < self.count {
            if let Some(event) = self.events.get(self.i) {
                self.i += 1;
                Some(*event)
            } else {
                None
            }
        } else {
            None
        }
    }
}
<commit_msg>Debug set_border_bottom<commit_after>use std::fs::File;
use std::io::*;
use std::mem;
use std::slice;
use std::thread;

use super::FONT;
use super::Event;
use super::Color;

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: i32,
    /// The y coordinate of the window
    y: i32,
    /// The width of the window
    w: u32,
    /// The height of the window
    h: u32,
    /// The title of the window
    t: String,
    /// The input scheme
    file: File,
    /// Window data
    data: Box<[Color]>,
}

impl Window {
    /// Create a new window
    pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Box<Self>> {
        match File::open(&format!("orbital:/{}/{}/{}/{}/{}", x, y, w, h, title)) {
            Ok(file) => {
                Some(box Window {
                    x: x,
                    y: y,
                    w: w,
                    h: h,
                    t: title.to_string(),
                    file: file,
                    data: vec![Color::rgb(0, 0, 0); (w * h * 4) as usize].into_boxed_slice(),
                })
            }
            Err(_) => None,
        }
    }

    // TODO: Replace with smarter mechanism, maybe a move event?
    pub fn sync_path(&mut self) {
        if let Ok(path) = self.file.path() {
            // orbital:/x/y/w/h/t
            if let Some(path_str) = path.to_str() {
                let mut parts = path_str.split('/').skip(1);
                if let Some(x) = parts.next() {
                    self.x = x.parse::<i32>().unwrap_or(0);
                }
                if let Some(y) = parts.next() {
                    self.y = y.parse::<i32>().unwrap_or(0);
                }
                if let Some(w) = parts.next() {
                    self.w = w.parse::<u32>().unwrap_or(0);
                }
                if let Some(h) = parts.next() {
                    self.h = h.parse::<u32>().unwrap_or(0);
                }
            }
        }
    }

    /// Get x
    // TODO: Sync with window movements
    pub fn x(&self) -> i32 {
        self.x
    }

    /// Get y
    // TODO: Sync with window movements
    pub fn y(&self) -> i32 {
        self.y
    }

    /// Get width
    pub fn width(&self) -> u32 {
        self.w
    }

    /// Get height
    pub fn height(&self) -> u32 {
        self.h
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set title
    pub fn set_title(&mut self, _: &str) {
        // TODO
    }

    /// Draw a pixel
    pub fn pixel(&mut self, x: i32, y: i32, color: Color) {
        if x >= 0 && y >= 0 && x < self.w as i32 && y < self.h as i32 {
            let new = color.data;

            let alpha = (new >> 24) & 0xFF;
            if alpha > 0 {
                let old = &mut self.data[y as usize * self.w as usize + x as usize].data;
                if alpha >= 255 {
                    *old = new;
                } else {
                    let n_r = (((new >> 16) & 0xFF) * alpha) >> 8;
                    let n_g = (((new >> 8) & 0xFF) * alpha) >> 8;
                    let n_b = ((new & 0xFF) * alpha) >> 8;

                    let n_alpha = 255 - alpha;
                    let o_a = (((*old >> 24) & 0xFF) * n_alpha) >> 8;
                    let o_r = (((*old >> 16) & 0xFF) * n_alpha) >> 8;
                    let o_g = (((*old >> 8) & 0xFF) * n_alpha) >> 8;
                    let o_b = ((*old & 0xFF) * n_alpha) >> 8;

                    *old = ((o_a << 24) | (o_r << 16) | (o_g << 8) | o_b) + ((alpha << 24) | (n_r << 16) | (n_g << 8) | n_b);
                }
            }
        }
    }

    /// Draw a character, using the loaded font
    pub fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
        let mut offset = (c as usize) * 16;
        for row in 0..16 {
            let row_data;
            if offset < FONT.len() {
                row_data = FONT[offset];
            } else {
                row_data = 0;
            }

            for col in 0..8 {
                let pixel = (row_data >> (7 - col)) & 1;
                if pixel > 0 {
                    self.pixel(x + col as i32, y + row as i32, color);
                }
            }
            offset += 1;
        }
    }

    // TODO move, resize, set_title

    /// Set entire window to a color
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn set(&mut self, color: Color) {
        for mut d in self.data.iter_mut() {
            *d = color;
        }
    }

    // Allows to draw a left border in the window
    // x_limit is the left limit of the border!!!
    pub fn set_border_left(&mut self, x_limit: i32, color: Color, density: i32) {
        for y in 0..self.height {
            for x in x_limit..(x_limit + density) {
                self.pixel(x, y as i32, color);
            }
        }
    }

    // Allows to draw a right border in the window
    // x_limit is the left limit of the border!!!
    pub fn set_border_right(&mut self, x_limit: i32, color: Color, density: i32) {
        for y in 0..self.height {
            for x in x_limit..(x_limit + density) {
                let new_x : i32 = self.width as i32;
                self.pixel((new_x - x), y as i32, color);
            }
        }
    }

    // Allows to draw a top border in the window
    // x_limit is the top limit of the border!!!
    pub fn set_border_top(&mut self, y_limit: i32, color: Color, density: u32) {
        for x in 0..self.width {
            for y in y_limit..(y_limit + density) {
                self.pixel(x, y, color);
            }
        }
    }

    // Allows to draw a bottom border in the window
    // x_limit is the top limit of the border!!!
    pub fn set_border_bottom(&mut self, y_limit: i32, color: Color, density: u32) {
        for x in 0..self.x {
            for y in 0..(y_limit + density) {
                let new_y : i32 = self.height as i32;
                self.pixel(x, (new_y - y), color);
            }
        }
    }

    /// Draw rectangle
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn rect(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, color: Color) {
        for y in start_y..start_y + h as i32 {
            for x in start_x..start_x + w as i32 {
                self.pixel(x, y, color);
            }
        }
    }

    /// Display an image
    // TODO: Improve speed
    pub fn image(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, data: &[Color]) {
        let mut i = 0;
        for y in start_y..start_y + h as i32 {
            for x in start_x..start_x + w as i32 {
                if i < data.len() {
                    self.pixel(x, y, data[i])
                }
                i += 1;
            }
        }
    }

    /// Return a iterator over events
    fn events_inner(&mut self, wait: bool) -> EventIter {
        let mut iter = EventIter {
            events: [Event::new(); 128],
            i: 0,
            count: 0,
        };

        'blocking: loop {
            //Should it be cleared? iter.events = [Event::new(); 128];
            match self.file.read(unsafe {
                slice::from_raw_parts_mut(iter.events.as_mut_ptr() as *mut u8, iter.events.len() * mem::size_of::<Event>())
            }){
                Ok(0) => if wait {
                    thread::yield_now();
                } else {
                    break 'blocking;
                },
                Ok(count) => {
                    iter.count = count/mem::size_of::<Event>();
                    break 'blocking;
                },
                Err(_) => break 'blocking,
            }
        }

        iter
    }

    /// Blocking iterator over events
    pub fn events(&mut self) -> EventIter {
        self.events_inner(true)
    }

    /// Nonblocking iterator over events
    pub fn events_no_wait(&mut self) -> EventIter {
        self.events_inner(false)
    }

    /// Flip the window buffer
    pub fn sync(&mut self) -> bool {
        self.file.write(unsafe {
            slice::from_raw_parts(self.data.as_ptr() as *const u8, self.data.len() * mem::size_of::<Color>())
        }).is_ok()
    }
}

/// Event iterator
pub struct EventIter {
    events: [Event; 128],
    i: usize,
    count: usize,
}

impl Iterator for EventIter {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        if self.i < self.count {
            if let Some(event) = self.events.get(self.i) {
                self.i += 1;
                Some(*event)
            } else {
                None
            }
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Logging for alacritty.
//!
//! The main executable is supposed to call `initialize()` exactly once during
//! startup. All logging messages are written to stdout, given that their
//! log-level is sufficient for the level configured in `cli::Options`.
use log;
use std::sync;
use std::io;
use cli;

pub struct Logger<T> {
    level: log::LevelFilter,
    output: sync::Mutex<T>
}

impl<T: Send + io::Write> Logger<T> {
    // False positive, see: https://github.com/rust-lang-nursery/rust-clippy/issues/734
    #[cfg_attr(feature = "clippy", allow(new_ret_no_self))]
    pub fn new(output: T, level: log::LevelFilter) -> Logger<io::LineWriter<T>> {
        Logger {
            level,
            output: sync::Mutex::new(io::LineWriter::new(output))
        }
    }
}

impl<T: Send + io::Write> log::Log for Logger<T> {
    fn enabled(&self, metadata: &log::Metadata) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &log::Record) {
        if self.enabled(record.metadata()) && record.target().starts_with("alacritty") {
            if let Ok(ref mut writer) = self.output.lock() {
                writer.write_all(format!("{}\n", record.args()).as_ref()).expect("Error while logging!");
            }
        }
    }

    fn flush(&self) {}
}

pub fn initialize(options: &cli::Options) -> Result<(), log::SetLoggerError> {
    // Use env_logger if RUST_LOG environment variable is defined. Otherwise,
    // use the alacritty-only logger.
    if ::std::env::var("RUST_LOG").is_ok() {
        ::env_logger::try_init()
    } else {
        log::set_boxed_logger(Box::new(Logger::new(io::stdout(), options.log_level)))
    }
}
<commit_msg>Explicitly call log::set_max_level (Closes: #1201)<commit_after>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Logging for alacritty.
//!
//! The main executable is supposed to call `initialize()` exactly once during
//! startup. All logging messages are written to stdout, given that their
//! log-level is sufficient for the level configured in `cli::Options`.
use log;
use std::sync;
use std::io;
use cli;

pub struct Logger<T> {
    level: log::LevelFilter,
    output: sync::Mutex<T>
}

impl<T: Send + io::Write> Logger<T> {
    // False positive, see: https://github.com/rust-lang-nursery/rust-clippy/issues/734
    #[cfg_attr(feature = "clippy", allow(new_ret_no_self))]
    pub fn new(output: T, level: log::LevelFilter) -> Logger<io::LineWriter<T>> {
        log::set_max_level(level);
        Logger {
            level,
            output: sync::Mutex::new(io::LineWriter::new(output))
        }
    }
}

impl<T: Send + io::Write> log::Log for Logger<T> {
    fn enabled(&self, metadata: &log::Metadata) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &log::Record) {
        if self.enabled(record.metadata()) && record.target().starts_with("alacritty") {
            if let Ok(ref mut writer) = self.output.lock() {
                writer.write_all(format!("{}\n", record.args()).as_ref()).expect("Error while logging!");
            }
        }
    }

    fn flush(&self) {}
}

pub fn initialize(options: &cli::Options) -> Result<(), log::SetLoggerError> {
    // Use env_logger if RUST_LOG environment variable is defined. Otherwise,
    // use the alacritty-only logger.
    if ::std::env::var("RUST_LOG").is_ok() {
        ::env_logger::try_init()
    } else {
        log::set_boxed_logger(Box::new(Logger::new(io::stdout(), options.log_level)))
    }
}
<|endoftext|>


<commit_before>use std::string::{String};
use super::{utils};
use std::io::net::{ip};
use std::from_str::{FromStr};

/// Maximum length of the local part.
static MAX_MAILBOX_LOCAL_PART_LEN: uint = 64;

/// Maximum length of an email address.
///
/// The RFC doesn't actually specify 254 chars, but it does say that a reverse path starts with
/// "<", ends with ">" and including those symbols has a maximum length of 256.
static MAX_MAILBOX_LEN: uint = 254;

/// Maximum length of a domain name.
static MAX_DOMAIN_LEN: uint = 255;

#[test]
fn test_static_vars() {
    assert_eq!(64, MAX_MAILBOX_LOCAL_PART_LEN);
    assert_eq!(254, MAX_MAILBOX_LEN);
    assert_eq!(255, MAX_DOMAIN_LEN);
}

/// Represents the local part of an email address, aka the username.
#[deriving(PartialEq, Eq, Clone, Show)]
pub struct MailboxLocalPart {
    /// This is a version of the local part for use in the SMTP protocol.
    ///
    /// This is either a dot-string or a quoted-string, whatever is shortest as
    /// recommended in RFC 5321.
    pub smtp_string: String,
    /// This is a version of the local part that is completely unescaped.
    ///
    /// It is human readable but not suitable for use in SMTP.
    pub human_string: String
}

impl MailboxLocalPart {
    /// Create a local part from a dot-string.
    fn from_dot_string(dot_string: &str) -> MailboxLocalPart {
        MailboxLocalPart {
            human_string: dot_string.into_string(),
            smtp_string: dot_string.into_string()
        }
    }

    /// Create a local part from a quoted-string.
    ///
    /// Since a quoted-string can sometimes be simplified, this function tries to simplify it
    /// as much as possible.
    fn from_quoted_string(quoted_string: &str) -> MailboxLocalPart {
        MailboxLocalPart {
            human_string: utils::unescape_quoted_string(quoted_string),
            smtp_string: utils::simplify_quoted_string(quoted_string)
        }
    }
}

#[test]
fn test_local_part() {
    let mut lp1: MailboxLocalPart;
    let mut lp2: MailboxLocalPart;
    let mut lp3: MailboxLocalPart;
    let mut lp4: MailboxLocalPart;
    let mut lp5: MailboxLocalPart;

    lp1 = MailboxLocalPart::from_dot_string("rust.cool");
    lp2 = MailboxLocalPart::from_quoted_string("\"rust \\a cool\"");
    lp3 = MailboxLocalPart::from_quoted_string("\"rust.cool\"");
    lp4 = MailboxLocalPart::from_quoted_string("\"rust.cool.\"");
    lp5 = MailboxLocalPart::from_quoted_string("\"rust\\\\\\b\\;.c\\\"ool\"");

    assert!(lp1.clone() == lp1.clone());
    assert!(lp2.clone() == lp2.clone());
    assert!(lp1.clone() != lp2.clone());

    assert_eq!(lp1.smtp_string.as_slice(), "rust.cool");
    assert_eq!(lp1.human_string.as_slice(), "rust.cool");

    assert_eq!(lp2.smtp_string.as_slice(), "\"rust a cool\"");
    assert_eq!(lp2.human_string.as_slice(), "rust a cool");

    assert_eq!(lp3.smtp_string.as_slice(), "rust.cool");
    assert_eq!(lp3.human_string.as_slice(), "rust.cool");

    assert_eq!(lp4.smtp_string.as_slice(), "\"rust.cool.\"");
    assert_eq!(lp4.human_string.as_slice(), "rust.cool.");

    assert_eq!(lp5.smtp_string.as_slice(), "\"rust\\\\b;.c\\\"ool\"");
    assert_eq!(lp5.human_string.as_slice(), "rust\\b;.c\"ool");
}

/// Represents the foreign part of an email address, aka the host.
#[deriving(PartialEq, Eq, Clone, Show)]
pub enum MailboxForeignPart {
    /// The foreign part is a domain name.
    Domain(String),
    /// The foreign part is an ip address.
    IpAddr(ip::IpAddr)
}

#[test]
fn test_foreign_part() {
    let domain_text = "rustastic.org";
    let domain = Domain(domain_text.into_string());
    let ipv4 = IpAddr(ip::Ipv4Addr(127, 0, 0, 1));
    let ipv6 = IpAddr(ip::Ipv6Addr(1, 1, 1, 1, 1, 1, 1, 1));

    assert!(domain == domain);
    assert!(domain != Domain(domain_text.into_string() + "bullshit"));
    assert!(domain != ipv4);
    assert!(domain != ipv6);
}

/// Represents an email address, aka "mailbox" in the SMTP spec.
///
/// It is composed of a local part and a foreign part.
#[deriving(PartialEq, Eq, Clone, Show)]
pub struct Mailbox {
    local_part: MailboxLocalPart,
    foreign_part: MailboxForeignPart
}

/// Represents an error that occured while trying to parse an email address.
#[deriving(PartialEq, Eq, Show)]
pub enum MailboxParseError {
    /// The maximum length of 64 octets [as per RFC 5321](http://tools.ietf.org/html/rfc5321#section-4.5.3.1.1) is exceeded.
    LocalPartTooLong,
    /// The local part was neither a atom, nor a quoted string.
    LocalPartUnrecognized,
    /// The foreign part was neither a domain, nor an IP.
    ForeignPartUnrecognized,
    /// The maximum length of 255 octets [as per RFC 5321](http://tools.ietf.org/html/rfc5321#section-4.5.3.1.2) is exceeded.
    DomainTooLong,
    /// The maximum length of 254 octets (256 - 2 for punctuaction) [as per RFC 5321](http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3) is exceeded.
    TooLong,
    /// If no @ was present.
    AtNotFound
}

impl Mailbox {
    /// Creates a `Mailbox` from a string if the string contains a valid email
    /// address. Otherwise, returns a `MailboxParseError`.
    ///
    /// The argument should be of the form:
    /// `hello@world.com`
    /// This function does *not* expect anything to wrap the passed email
    /// address. For example, this will result in an error:
    /// `<hello@world.com>`
    pub fn parse(s: &str) -> Result<Mailbox, MailboxParseError> {
        let mut local_part: MailboxLocalPart;
        let mut foreign_part: MailboxForeignPart;

        // Skip the source routes as specified in RFC 5321.
        let mut offset: uint = utils::get_source_route_len(s);

        // Get the local part.
        let dot_string_len = utils::get_dot_string_len(s.slice_from(offset));
        if dot_string_len > 0 {
            if dot_string_len > MAX_MAILBOX_LOCAL_PART_LEN {
                return Err(LocalPartTooLong);
            }
            local_part = MailboxLocalPart::from_dot_string(
                s.slice(offset, offset + dot_string_len)
            );
            offset += dot_string_len;
        } else {
            let quoted_string_len = utils::get_quoted_string_len(s.slice_from(offset));
            if quoted_string_len == 0 {
                return Err(LocalPartUnrecognized);
            }
            if quoted_string_len > MAX_MAILBOX_LOCAL_PART_LEN {
                return Err(LocalPartTooLong);
            }
            local_part = MailboxLocalPart::from_quoted_string(
                s.slice(offset, offset + quoted_string_len)
            );
            offset += quoted_string_len;
        }

        // Check if the email address continues to find an @.
        if offset >= s.len() {
            return Err(AtNotFound);
        }
        // If no @ is found, it means we're still in what should be the local
        // part but it is invalid, ie "rust is@rustastic.org".
        if s.char_at(offset) != '@' {
            return Err(LocalPartUnrecognized);
        }
        offset += 1;

        let domain_len = utils::get_domain_len(s.slice_from(offset));
        if domain_len > 0 {
            // Is the domain is too long ?
            if domain_len > MAX_DOMAIN_LEN {
                return Err(DomainTooLong);
            }
            // Save the domain.
            foreign_part = Domain(
                s.slice(offset, offset + domain_len).into_string()
            );
            offset += domain_len;
        } else {
            let ipv4_len = utils::get_possible_ipv4_len(s.slice_from(offset));
            if ipv4_len > 0 {
                match FromStr::from_str(s.slice(offset + 1, offset + ipv4_len - 1)) {
                    Some(ip) => {
                        foreign_part = IpAddr(ip);
                        offset += ipv4_len;
                    },
                    _ => return Err(ForeignPartUnrecognized)
                }
            } else {
                let ipv6_len = utils::get_possible_ipv6_len(s.slice_from(offset));
                if ipv6_len > 0 {
                    match FromStr::from_str(s.slice(offset + 6, offset + ipv6_len - 1)) {
                        Some(ip) => {
                            foreign_part = IpAddr(ip);
                            offset += ipv6_len;
                        },
                        _ => return Err(ForeignPartUnrecognized)
                    }
                } else {
                    return Err(ForeignPartUnrecognized);
                }
            }
        }

        // Example would be "rust.is@rustastic.org{}" where "rustastic.org{}"
        // would be considered an invalid domain name.
        if offset != s.len() {
            Err(ForeignPartUnrecognized)
        // Overall, is the email address to long? We could test this at the
        // beginning of the function to potentially save processing power, but
        // this shouldn't happen too often and this error doesn't give much
        // information whereas LocalPartTooLong is more precise which allows
        // for more understandable debug messages.
        } else if offset > MAX_MAILBOX_LEN {
            Err(TooLong)
        } else {
            Ok(Mailbox {
                local_part: local_part,
                foreign_part: foreign_part
            })
        }
    }
}

#[test]
fn test_mailbox() {
    let path_1 = Mailbox::parse("rust.is@rustastic.org").unwrap();
    let path_2 = Mailbox::parse("rust.is.not@rustastic.org").unwrap();
    let path_3 = Mailbox::parse("\"hello\"@rust").unwrap();
    let path_4 = Mailbox::parse("rust.is@[127.0.0.1]").unwrap();
    let path_5 = Mailbox::parse("rust.is@[Ipv6:::1]").unwrap();
    let path_6 = Mailbox::parse("rust.is@[Ipv6:2001:db8::ff00:42:8329]").unwrap();

    assert!(path_1 == path_1.clone());
    assert!(path_2 == path_2.clone());
    assert!(path_1 != path_2);

    assert_eq!(path_3.local_part.smtp_string.as_slice(), "hello");
    assert_eq!(path_3.local_part.human_string.as_slice(), "hello");
    assert_eq!(path_3.foreign_part, Domain("rust".into_string()));

    Mailbox::parse(
        String::from_char(MAX_MAILBOX_LOCAL_PART_LEN, 'a')
            .append("@t.com")
            .as_slice()
    ).unwrap();
    assert_eq!(Err(LocalPartTooLong), Mailbox::parse(
        String::from_char(MAX_MAILBOX_LOCAL_PART_LEN + 1, 'a')
            .append("@t.com")
            .as_slice()
    ));
    assert_eq!(Err(LocalPartUnrecognized), Mailbox::parse("t @t.com{"));
    assert_eq!(Err(LocalPartUnrecognized), Mailbox::parse("t "));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("t@{}"));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("t@t.com{"));
    // The check here is to expect something else than DomainTooLong.
    assert_eq!(Err(TooLong), Mailbox::parse(
        ("rust@".into_string() + String::from_char(MAX_DOMAIN_LEN, 'a'))
            .as_slice()
    ));
    assert_eq!(Err(DomainTooLong), Mailbox::parse(
        ("rust@".into_string() + String::from_char(MAX_DOMAIN_LEN + 1, 'a'))
            .as_slice()
    ));
    Mailbox::parse(
        ("rust@".into_string() + String::from_char(MAX_MAILBOX_LEN - 5, 'a'))
            .as_slice()
    ).unwrap();
    assert_eq!(Err(TooLong), Mailbox::parse(
        ("rust@".into_string() + String::from_char(MAX_MAILBOX_LEN - 4, 'a'))
            .as_slice()
    ));
    assert_eq!(Err(AtNotFound), Mailbox::parse("t"));

    assert_eq!(path_4.foreign_part, IpAddr(ip::Ipv4Addr(127, 0, 0, 1)));
    assert_eq!(path_5.foreign_part, IpAddr(ip::Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)));
    assert_eq!(path_6.foreign_part, IpAddr(
        ip::Ipv6Addr(0x2001, 0xdb8, 0x0, 0x0, 0x0, 0xff00, 0x42, 0x8329)
    ));

    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("rust.is@[127.0.0.1"));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("rust.is@[00.0.1]"));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("rust.is@[::1]"));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("rust.is@[Ipv6: ::1]"));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("rust.is@[Ipv6:::1"));
}
<commit_msg>make local part attributes not public, will use immutable getters instead<commit_after>use std::string::{String};
use super::{utils};
use std::io::net::{ip};
use std::from_str::{FromStr};

/// Maximum length of the local part.
static MAX_MAILBOX_LOCAL_PART_LEN: uint = 64;

/// Maximum length of an email address.
///
/// The RFC doesn't actually specify 254 chars, but it does say that a reverse path starts with
/// "<", ends with ">" and including those symbols has a maximum length of 256.
static MAX_MAILBOX_LEN: uint = 254;

/// Maximum length of a domain name.
static MAX_DOMAIN_LEN: uint = 255;

#[test]
fn test_static_vars() {
    assert_eq!(64, MAX_MAILBOX_LOCAL_PART_LEN);
    assert_eq!(254, MAX_MAILBOX_LEN);
    assert_eq!(255, MAX_DOMAIN_LEN);
}

/// Represents the local part of an email address, aka the username.
#[deriving(PartialEq, Eq, Clone, Show)]
pub struct MailboxLocalPart {
    /// This is a version of the local part for use in the SMTP protocol.
    ///
    /// This is either a dot-string or a quoted-string, whatever is shortest as
    /// recommended in RFC 5321.
    smtp_string: String,
    /// This is a version of the local part that is completely unescaped.
    ///
    /// It is human readable but not suitable for use in SMTP.
    human_string: String
}

impl MailboxLocalPart {
    /// Create a local part from a dot-string.
    fn from_dot_string(dot_string: &str) -> MailboxLocalPart {
        MailboxLocalPart {
            human_string: dot_string.into_string(),
            smtp_string: dot_string.into_string()
        }
    }

    /// Create a local part from a quoted-string.
    ///
    /// Since a quoted-string can sometimes be simplified, this function tries to simplify it
    /// as much as possible.
    fn from_quoted_string(quoted_string: &str) -> MailboxLocalPart {
        MailboxLocalPart {
            human_string: utils::unescape_quoted_string(quoted_string),
            smtp_string: utils::simplify_quoted_string(quoted_string)
        }
    }
}

#[test]
fn test_local_part() {
    let mut lp1: MailboxLocalPart;
    let mut lp2: MailboxLocalPart;
    let mut lp3: MailboxLocalPart;
    let mut lp4: MailboxLocalPart;
    let mut lp5: MailboxLocalPart;

    lp1 = MailboxLocalPart::from_dot_string("rust.cool");
    lp2 = MailboxLocalPart::from_quoted_string("\"rust \\a cool\"");
    lp3 = MailboxLocalPart::from_quoted_string("\"rust.cool\"");
    lp4 = MailboxLocalPart::from_quoted_string("\"rust.cool.\"");
    lp5 = MailboxLocalPart::from_quoted_string("\"rust\\\\\\b\\;.c\\\"ool\"");

    assert!(lp1.clone() == lp1.clone());
    assert!(lp2.clone() == lp2.clone());
    assert!(lp1.clone() != lp2.clone());

    assert_eq!(lp1.smtp_string.as_slice(), "rust.cool");
    assert_eq!(lp1.human_string.as_slice(), "rust.cool");

    assert_eq!(lp2.smtp_string.as_slice(), "\"rust a cool\"");
    assert_eq!(lp2.human_string.as_slice(), "rust a cool");

    assert_eq!(lp3.smtp_string.as_slice(), "rust.cool");
    assert_eq!(lp3.human_string.as_slice(), "rust.cool");

    assert_eq!(lp4.smtp_string.as_slice(), "\"rust.cool.\"");
    assert_eq!(lp4.human_string.as_slice(), "rust.cool.");

    assert_eq!(lp5.smtp_string.as_slice(), "\"rust\\\\b;.c\\\"ool\"");
    assert_eq!(lp5.human_string.as_slice(), "rust\\b;.c\"ool");
}

/// Represents the foreign part of an email address, aka the host.
#[deriving(PartialEq, Eq, Clone, Show)]
pub enum MailboxForeignPart {
    /// The foreign part is a domain name.
    Domain(String),
    /// The foreign part is an ip address.
    IpAddr(ip::IpAddr)
}

#[test]
fn test_foreign_part() {
    let domain_text = "rustastic.org";
    let domain = Domain(domain_text.into_string());
    let ipv4 = IpAddr(ip::Ipv4Addr(127, 0, 0, 1));
    let ipv6 = IpAddr(ip::Ipv6Addr(1, 1, 1, 1, 1, 1, 1, 1));

    assert!(domain == domain);
    assert!(domain != Domain(domain_text.into_string() + "bullshit"));
    assert!(domain != ipv4);
    assert!(domain != ipv6);
}

/// Represents an email address, aka "mailbox" in the SMTP spec.
///
/// It is composed of a local part and a foreign part.
#[deriving(PartialEq, Eq, Clone, Show)]
pub struct Mailbox {
    local_part: MailboxLocalPart,
    foreign_part: MailboxForeignPart
}

/// Represents an error that occured while trying to parse an email address.
#[deriving(PartialEq, Eq, Show)]
pub enum MailboxParseError {
    /// The maximum length of 64 octets [as per RFC 5321](http://tools.ietf.org/html/rfc5321#section-4.5.3.1.1) is exceeded.
    LocalPartTooLong,
    /// The local part was neither a atom, nor a quoted string.
    LocalPartUnrecognized,
    /// The foreign part was neither a domain, nor an IP.
    ForeignPartUnrecognized,
    /// The maximum length of 255 octets [as per RFC 5321](http://tools.ietf.org/html/rfc5321#section-4.5.3.1.2) is exceeded.
    DomainTooLong,
    /// The maximum length of 254 octets (256 - 2 for punctuaction) [as per RFC 5321](http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3) is exceeded.
    TooLong,
    /// If no @ was present.
    AtNotFound
}

impl Mailbox {
    /// Creates a `Mailbox` from a string if the string contains a valid email
    /// address. Otherwise, returns a `MailboxParseError`.
    ///
    /// The argument should be of the form:
    /// `hello@world.com`
    /// This function does *not* expect anything to wrap the passed email
    /// address. For example, this will result in an error:
    /// `<hello@world.com>`
    pub fn parse(s: &str) -> Result<Mailbox, MailboxParseError> {
        let mut local_part: MailboxLocalPart;
        let mut foreign_part: MailboxForeignPart;

        // Skip the source routes as specified in RFC 5321.
        let mut offset: uint = utils::get_source_route_len(s);

        // Get the local part.
        let dot_string_len = utils::get_dot_string_len(s.slice_from(offset));
        if dot_string_len > 0 {
            if dot_string_len > MAX_MAILBOX_LOCAL_PART_LEN {
                return Err(LocalPartTooLong);
            }
            local_part = MailboxLocalPart::from_dot_string(
                s.slice(offset, offset + dot_string_len)
            );
            offset += dot_string_len;
        } else {
            let quoted_string_len = utils::get_quoted_string_len(s.slice_from(offset));
            if quoted_string_len == 0 {
                return Err(LocalPartUnrecognized);
            }
            if quoted_string_len > MAX_MAILBOX_LOCAL_PART_LEN {
                return Err(LocalPartTooLong);
            }
            local_part = MailboxLocalPart::from_quoted_string(
                s.slice(offset, offset + quoted_string_len)
            );
            offset += quoted_string_len;
        }

        // Check if the email address continues to find an @.
        if offset >= s.len() {
            return Err(AtNotFound);
        }
        // If no @ is found, it means we're still in what should be the local
        // part but it is invalid, ie "rust is@rustastic.org".
        if s.char_at(offset) != '@' {
            return Err(LocalPartUnrecognized);
        }
        offset += 1;

        let domain_len = utils::get_domain_len(s.slice_from(offset));
        if domain_len > 0 {
            // Is the domain is too long ?
            if domain_len > MAX_DOMAIN_LEN {
                return Err(DomainTooLong);
            }
            // Save the domain.
            foreign_part = Domain(
                s.slice(offset, offset + domain_len).into_string()
            );
            offset += domain_len;
        } else {
            let ipv4_len = utils::get_possible_ipv4_len(s.slice_from(offset));
            if ipv4_len > 0 {
                match FromStr::from_str(s.slice(offset + 1, offset + ipv4_len - 1)) {
                    Some(ip) => {
                        foreign_part = IpAddr(ip);
                        offset += ipv4_len;
                    },
                    _ => return Err(ForeignPartUnrecognized)
                }
            } else {
                let ipv6_len = utils::get_possible_ipv6_len(s.slice_from(offset));
                if ipv6_len > 0 {
                    match FromStr::from_str(s.slice(offset + 6, offset + ipv6_len - 1)) {
                        Some(ip) => {
                            foreign_part = IpAddr(ip);
                            offset += ipv6_len;
                        },
                        _ => return Err(ForeignPartUnrecognized)
                    }
                } else {
                    return Err(ForeignPartUnrecognized);
                }
            }
        }

        // Example would be "rust.is@rustastic.org{}" where "rustastic.org{}"
        // would be considered an invalid domain name.
        if offset != s.len() {
            Err(ForeignPartUnrecognized)
        // Overall, is the email address to long? We could test this at the
        // beginning of the function to potentially save processing power, but
        // this shouldn't happen too often and this error doesn't give much
        // information whereas LocalPartTooLong is more precise which allows
        // for more understandable debug messages.
        } else if offset > MAX_MAILBOX_LEN {
            Err(TooLong)
        } else {
            Ok(Mailbox {
                local_part: local_part,
                foreign_part: foreign_part
            })
        }
    }
}

#[test]
fn test_mailbox() {
    let path_1 = Mailbox::parse("rust.is@rustastic.org").unwrap();
    let path_2 = Mailbox::parse("rust.is.not@rustastic.org").unwrap();
    let path_3 = Mailbox::parse("\"hello\"@rust").unwrap();
    let path_4 = Mailbox::parse("rust.is@[127.0.0.1]").unwrap();
    let path_5 = Mailbox::parse("rust.is@[Ipv6:::1]").unwrap();
    let path_6 = Mailbox::parse("rust.is@[Ipv6:2001:db8::ff00:42:8329]").unwrap();

    assert!(path_1 == path_1.clone());
    assert!(path_2 == path_2.clone());
    assert!(path_1 != path_2);

    assert_eq!(path_3.local_part.smtp_string.as_slice(), "hello");
    assert_eq!(path_3.local_part.human_string.as_slice(), "hello");
    assert_eq!(path_3.foreign_part, Domain("rust".into_string()));

    Mailbox::parse(
        String::from_char(MAX_MAILBOX_LOCAL_PART_LEN, 'a')
            .append("@t.com")
            .as_slice()
    ).unwrap();
    assert_eq!(Err(LocalPartTooLong), Mailbox::parse(
        String::from_char(MAX_MAILBOX_LOCAL_PART_LEN + 1, 'a')
            .append("@t.com")
            .as_slice()
    ));
    assert_eq!(Err(LocalPartUnrecognized), Mailbox::parse("t @t.com{"));
    assert_eq!(Err(LocalPartUnrecognized), Mailbox::parse("t "));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("t@{}"));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("t@t.com{"));
    // The check here is to expect something else than DomainTooLong.
    assert_eq!(Err(TooLong), Mailbox::parse(
        ("rust@".into_string() + String::from_char(MAX_DOMAIN_LEN, 'a'))
            .as_slice()
    ));
    assert_eq!(Err(DomainTooLong), Mailbox::parse(
        ("rust@".into_string() + String::from_char(MAX_DOMAIN_LEN + 1, 'a'))
            .as_slice()
    ));
    Mailbox::parse(
        ("rust@".into_string() + String::from_char(MAX_MAILBOX_LEN - 5, 'a'))
            .as_slice()
    ).unwrap();
    assert_eq!(Err(TooLong), Mailbox::parse(
        ("rust@".into_string() + String::from_char(MAX_MAILBOX_LEN - 4, 'a'))
            .as_slice()
    ));
    assert_eq!(Err(AtNotFound), Mailbox::parse("t"));

    assert_eq!(path_4.foreign_part, IpAddr(ip::Ipv4Addr(127, 0, 0, 1)));
    assert_eq!(path_5.foreign_part, IpAddr(ip::Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)));
    assert_eq!(path_6.foreign_part, IpAddr(
        ip::Ipv6Addr(0x2001, 0xdb8, 0x0, 0x0, 0x0, 0xff00, 0x42, 0x8329)
    ));

    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("rust.is@[127.0.0.1"));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("rust.is@[00.0.1]"));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("rust.is@[::1]"));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("rust.is@[Ipv6: ::1]"));
    assert_eq!(Err(ForeignPartUnrecognized), Mailbox::parse("rust.is@[Ipv6:::1"));
}
<|endoftext|>


<commit_before>use std::fmt;
use std::io;
use std::mem;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, Shutdown};

use net2::TcpBuilder;

use futures::{Future, Poll, Stream, Async};

use nio;
use io::{AsyncRead, AsyncWrite};
use reactor::PollableIo;

#[derive(Debug)]
pub struct TcpStream {
    inner: PollableIo<nio::TcpStream>,
}

enum ConnectState {
    Connecting(TcpStream),
    Finishing(TcpStream),
    Connected(TcpStream),
    Error(io::Error),
    Dead,
}

pub struct TcpConnector {
    state: ConnectState,
}

impl TcpStream {
    #[inline]
    fn from(sock: nio::TcpStream) -> Self {
        TcpStream {
            inner: PollableIo::new(sock),
        }
    }

    pub fn connect(addr: &SocketAddr) -> TcpConnector {
        let state = match nio::TcpStream::connect(addr) {
            Ok((sock, connected)) => {
                let io = Self::from(sock);
                match connected {
                    false => ConnectState::Connecting(io),
                    true => ConnectState::Connected(io),
                }
            }
            Err(e) => ConnectState::Error(e),
        };
        TcpConnector { state }
    }

    #[inline]
    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        self.inner.get_ref().peer_addr()
    }

    #[inline]
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.inner.get_ref().local_addr()
    }

    #[inline]
    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        self.inner.get_ref().shutdown(how)
    }

    #[inline]
    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
        self.inner.get_ref().set_nodelay(nodelay)
    }

    #[inline]
    pub fn nodelay(&self) -> io::Result<bool> {
        self.inner.get_ref().nodelay()
    }

    #[inline]
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.inner.get_ref().set_ttl(ttl)
    }

    #[inline]
    pub fn ttl(&self) -> io::Result<u32> {
        self.inner.get_ref().ttl()
    }

    #[inline]
    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.inner.get_ref().take_error()
    }
}

impl fmt::Display for TcpStream {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::fmt::Debug;
        self.inner.get_ref().fmt(f)
    }
}

impl io::Read for TcpStream {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.get_mut().read(buf)
    }
}

impl nio::ReadV for TcpStream {
    #[inline]
    fn readv(&mut self, iovs: &[nio::IoVec]) -> io::Result<usize> {
        self.inner.get_mut().readv(iovs)
    }
}

impl AsyncRead for TcpStream {
    #[inline]
    fn need_read(&mut self) -> io::Result<()> {
        self.inner.need_read()
    }

    #[inline]
    fn no_need_read(&mut self) -> io::Result<()> {
        self.inner.no_need_read()
    }

    #[inline]
    fn is_readable(&self) -> bool {
        self.inner.is_readable()
    }
}

impl io::Write for TcpStream {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.get_mut().write(buf)
    }

    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        self.inner.get_mut().flush()
    }
}

impl nio::WriteV for TcpStream {
    #[inline]
    fn writev(&mut self, iovs: &[nio::IoVec]) -> io::Result<usize> {
        self.inner.get_mut().writev(iovs)
    }
}

impl AsyncWrite for TcpStream {
    #[inline]
    fn need_write(&mut self) -> io::Result<()> {
        self.inner.need_write()
    }

    #[inline]
    fn no_need_write(&mut self) -> io::Result<()> {
        self.inner.no_need_write()
    }

    #[inline]
    fn is_writable(&self) -> bool {
        self.inner.is_writable()
    }
}

pub struct Incoming {
    io: PollableIo<nio::TcpListener>,
}

#[derive(Debug, Clone, Copy)]
pub struct TcpListenerBuilder {
    addr: SocketAddr,
    backlog: i32,
    ttl: Option<u32>,
    only_v6: Option<bool>,
}

pub struct TcpListener {
    inner: nio::TcpListener,
}

impl TcpListener {
    #[inline]
    pub fn builder() -> TcpListenerBuilder {
        Default::default()
    }

    #[inline]
    pub fn incoming(self) -> Incoming {
        Incoming {
            io: PollableIo::new(self.inner),
        }
    }

    #[inline]
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.inner.local_addr()
    }

    #[inline]
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.inner.set_ttl(ttl)
    }

    #[inline]
    pub fn ttl(&self) -> io::Result<u32> {
        self.inner.ttl()
    }

    #[inline]
    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.inner.take_error()
    }

    #[inline]
    fn from(inner: nio::TcpListener) -> Self {
        TcpListener { inner }
    }
}

impl Default for TcpListenerBuilder {
    #[inline]
    fn default() -> Self {
        TcpListenerBuilder {
            addr: SocketAddr::new(IpAddr::from(Ipv4Addr::from(0)), 0),
            backlog: 128,
            ttl: None,
            only_v6: None,
        }
    }
}

impl TcpListenerBuilder {
    #[inline]
    pub fn addr(&mut self, addr: SocketAddr) -> &mut Self {
        self.addr = addr;
        self
    }

    #[inline]
    pub fn port(&mut self, port: u16) -> &mut Self {
        self.addr.set_port(port);
        self
    }

    #[inline]
    pub fn backlog(&mut self, backlog: i32) -> &mut Self {
        self.backlog = backlog;
        self
    }

    #[inline]
    pub fn ttl(&mut self, ttl: Option<u32>) -> &mut Self {
        self.ttl = ttl;
        self
    }

    #[inline]
    pub fn only_v6(&mut self, only_v6: Option<bool>) -> &mut Self {
        self.only_v6 = only_v6;
        self
    }

    pub fn build(&self) -> io::Result<TcpListener> {
        let builder = match self.addr {
            SocketAddr::V4(..) => TcpBuilder::new_v4()?,
            SocketAddr::V6(..) => TcpBuilder::new_v6()?,
        };
        if let Some(ttl) = self.ttl {
            builder.ttl(ttl)?;
        }
        if let Some(only_v6) = self.only_v6 {
            builder.only_v6(only_v6)?;
        }
        let listener = builder
            .reuse_address(true)?
            .bind(self.addr)?
            .listen(self.backlog)?;
        listener.set_nonblocking(true)?;
        Ok(TcpListener::from(nio::TcpListener::from(listener)))
    }
}

impl Stream for Incoming {
    type Item = (TcpStream, SocketAddr);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match self.io.get_ref().accept() {
            Ok((s, a)) => Ok(Async::Ready(Some((TcpStream::from(s), a)))),
            Err(e) => {
                match e.kind() {
                    io::ErrorKind::WouldBlock => {
                        self.io.need_read()?;
                        Ok(Async::NotReady)
                    }
                    _ => Err(e),
                }
            }
        }
    }
}

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

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match mem::replace(&mut self.state, ConnectState::Dead) {
            ConnectState::Connecting(mut sock) => {
                sock.need_write()?;
                self.state = ConnectState::Finishing(sock);
                Ok(Async::NotReady)
            }
            ConnectState::Finishing(mut sock) => {
                match sock.is_writable() {
                    true => {
                        match sock.take_error()? {
                            None => {
                                sock.no_need_write()?;
                                Ok(Async::Ready(sock))
                            }
                            Some(e) => Err(e),
                        }
                    }
                    false => {
                        self.state = ConnectState::Finishing(sock);
                        Ok(Async::NotReady)
                    }
                }
            }
            ConnectState::Connected(sock) => Ok(Async::Ready(sock)),
            ConnectState::Error(e) => Err(e),
            _ => ::unreachable(),
        }
    }
}
<commit_msg>Panic if polling TcpConnector after completion<commit_after>use std::fmt;
use std::io;
use std::mem;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, Shutdown};

use net2::TcpBuilder;

use futures::{Future, Poll, Stream, Async};

use nio;
use io::{AsyncRead, AsyncWrite};
use reactor::PollableIo;

#[derive(Debug)]
pub struct TcpStream {
    inner: PollableIo<nio::TcpStream>,
}

enum ConnectState {
    Connecting(TcpStream),
    Finishing(TcpStream),
    Connected(TcpStream),
    Error(io::Error),
    Dead,
}

pub struct TcpConnector {
    state: ConnectState,
}

impl TcpStream {
    #[inline]
    fn from(sock: nio::TcpStream) -> Self {
        TcpStream {
            inner: PollableIo::new(sock),
        }
    }

    pub fn connect(addr: &SocketAddr) -> TcpConnector {
        let state = match nio::TcpStream::connect(addr) {
            Ok((sock, connected)) => {
                let io = Self::from(sock);
                match connected {
                    false => ConnectState::Connecting(io),
                    true => ConnectState::Connected(io),
                }
            }
            Err(e) => ConnectState::Error(e),
        };
        TcpConnector { state }
    }

    #[inline]
    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        self.inner.get_ref().peer_addr()
    }

    #[inline]
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.inner.get_ref().local_addr()
    }

    #[inline]
    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        self.inner.get_ref().shutdown(how)
    }

    #[inline]
    pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
        self.inner.get_ref().set_nodelay(nodelay)
    }

    #[inline]
    pub fn nodelay(&self) -> io::Result<bool> {
        self.inner.get_ref().nodelay()
    }

    #[inline]
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.inner.get_ref().set_ttl(ttl)
    }

    #[inline]
    pub fn ttl(&self) -> io::Result<u32> {
        self.inner.get_ref().ttl()
    }

    #[inline]
    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.inner.get_ref().take_error()
    }
}

impl fmt::Display for TcpStream {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::fmt::Debug;
        self.inner.get_ref().fmt(f)
    }
}

impl io::Read for TcpStream {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.get_mut().read(buf)
    }
}

impl nio::ReadV for TcpStream {
    #[inline]
    fn readv(&mut self, iovs: &[nio::IoVec]) -> io::Result<usize> {
        self.inner.get_mut().readv(iovs)
    }
}

impl AsyncRead for TcpStream {
    #[inline]
    fn need_read(&mut self) -> io::Result<()> {
        self.inner.need_read()
    }

    #[inline]
    fn no_need_read(&mut self) -> io::Result<()> {
        self.inner.no_need_read()
    }

    #[inline]
    fn is_readable(&self) -> bool {
        self.inner.is_readable()
    }
}

impl io::Write for TcpStream {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.get_mut().write(buf)
    }

    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        self.inner.get_mut().flush()
    }
}

impl nio::WriteV for TcpStream {
    #[inline]
    fn writev(&mut self, iovs: &[nio::IoVec]) -> io::Result<usize> {
        self.inner.get_mut().writev(iovs)
    }
}

impl AsyncWrite for TcpStream {
    #[inline]
    fn need_write(&mut self) -> io::Result<()> {
        self.inner.need_write()
    }

    #[inline]
    fn no_need_write(&mut self) -> io::Result<()> {
        self.inner.no_need_write()
    }

    #[inline]
    fn is_writable(&self) -> bool {
        self.inner.is_writable()
    }
}

pub struct Incoming {
    io: PollableIo<nio::TcpListener>,
}

#[derive(Debug, Clone, Copy)]
pub struct TcpListenerBuilder {
    addr: SocketAddr,
    backlog: i32,
    ttl: Option<u32>,
    only_v6: Option<bool>,
}

pub struct TcpListener {
    inner: nio::TcpListener,
}

impl TcpListener {
    #[inline]
    pub fn builder() -> TcpListenerBuilder {
        Default::default()
    }

    #[inline]
    pub fn incoming(self) -> Incoming {
        Incoming {
            io: PollableIo::new(self.inner),
        }
    }

    #[inline]
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.inner.local_addr()
    }

    #[inline]
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.inner.set_ttl(ttl)
    }

    #[inline]
    pub fn ttl(&self) -> io::Result<u32> {
        self.inner.ttl()
    }

    #[inline]
    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.inner.take_error()
    }

    #[inline]
    fn from(inner: nio::TcpListener) -> Self {
        TcpListener { inner }
    }
}

impl Default for TcpListenerBuilder {
    #[inline]
    fn default() -> Self {
        TcpListenerBuilder {
            addr: SocketAddr::new(IpAddr::from(Ipv4Addr::from(0)), 0),
            backlog: 128,
            ttl: None,
            only_v6: None,
        }
    }
}

impl TcpListenerBuilder {
    #[inline]
    pub fn addr(&mut self, addr: SocketAddr) -> &mut Self {
        self.addr = addr;
        self
    }

    #[inline]
    pub fn port(&mut self, port: u16) -> &mut Self {
        self.addr.set_port(port);
        self
    }

    #[inline]
    pub fn backlog(&mut self, backlog: i32) -> &mut Self {
        self.backlog = backlog;
        self
    }

    #[inline]
    pub fn ttl(&mut self, ttl: Option<u32>) -> &mut Self {
        self.ttl = ttl;
        self
    }

    #[inline]
    pub fn only_v6(&mut self, only_v6: Option<bool>) -> &mut Self {
        self.only_v6 = only_v6;
        self
    }

    pub fn build(&self) -> io::Result<TcpListener> {
        let builder = match self.addr {
            SocketAddr::V4(..) => TcpBuilder::new_v4()?,
            SocketAddr::V6(..) => TcpBuilder::new_v6()?,
        };
        if let Some(ttl) = self.ttl {
            builder.ttl(ttl)?;
        }
        if let Some(only_v6) = self.only_v6 {
            builder.only_v6(only_v6)?;
        }
        let listener = builder
            .reuse_address(true)?
            .bind(self.addr)?
            .listen(self.backlog)?;
        listener.set_nonblocking(true)?;
        Ok(TcpListener::from(nio::TcpListener::from(listener)))
    }
}

impl Stream for Incoming {
    type Item = (TcpStream, SocketAddr);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match self.io.get_ref().accept() {
            Ok((s, a)) => Ok(Async::Ready(Some((TcpStream::from(s), a)))),
            Err(e) => {
                match e.kind() {
                    io::ErrorKind::WouldBlock => {
                        self.io.need_read()?;
                        Ok(Async::NotReady)
                    }
                    _ => Err(e),
                }
            }
        }
    }
}

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

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match mem::replace(&mut self.state, ConnectState::Dead) {
            ConnectState::Connecting(mut sock) => {
                sock.need_write()?;
                self.state = ConnectState::Finishing(sock);
                Ok(Async::NotReady)
            }
            ConnectState::Finishing(mut sock) => {
                if sock.is_writable() {
                    match sock.take_error()? {
                        None => {
                            sock.no_need_write()?;
                            Ok(Async::Ready(sock))
                        }
                        Some(e) => Err(e),
                    }
                } else {
                    self.state = ConnectState::Finishing(sock);
                    Ok(Async::NotReady)
                }
            }
            ConnectState::Connected(sock) => Ok(Async::Ready(sock)),
            ConnectState::Error(e) => Err(e),
            _ => panic!("Attempted to poll TcpConnector after completion"),
        }
    }
}
<|endoftext|>