<commit_before>// Copyright 2017 The Exonum Team
//
// 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.

//! An implementation of array list of items.
use std::cell::Cell;
use std::marker::PhantomData;

use super::{BaseIndex, BaseIndexIter, Snapshot, Fork, StorageValue};

/// A list of items that implement `StorageValue` trait.
///
/// `ListIndex` implements an array list, storing the element as values and using `u64` as an index.
/// `ListIndex` requires that the elements implement the [`StorageValue`] trait.
/// [`StorageValue`]: ../trait.StorageValue.html
#[derive(Debug)]
pub struct ListIndex<T, V> {
    base: BaseIndex<T>,
    length: Cell<Option<u64>>,
    _v: PhantomData<V>,
}

/// An iterator over the items of a `ListIndex`.
///
/// This struct is created by the [`iter`] or
/// [`iter_from`] methods on [`ListIndex`]. See its documentation for more.
///
/// [`iter`]: struct.ListIndex.html#method.iter
/// [`iter_from`]: struct.ListIndex.html#method.iter_from
/// [`ListIndex`]: struct.ListIndex.html
#[derive(Debug)]
pub struct ListIndexIter<'a, V> {
    base_iter: BaseIndexIter<'a, u64, V>,
}

impl<T, V> ListIndex<T, V> {
    /// Creates a new index representation based on the common prefix of its keys and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case only
    /// immutable methods are available. In the second case both immutable and mutable methods are
    /// available.
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    pub fn new(prefix: Vec<u8>, view: T) -> Self {
        ListIndex {
            base: BaseIndex::new(prefix, view),
            length: Cell::new(None),
            _v: PhantomData,
        }
    }
}

impl<T, V> ListIndex<T, V>
where
    T: AsRef<Snapshot>,
    V: StorageValue,
{
    /// Returns an element at that position or `None` if out of bounds.
    pub fn get(&self, index: u64) -> Option<V> {
        self.base.get(&index)
    }

    /// Returns the last element of the list, or `None` if it is empty.
    pub fn last(&self) -> Option<V> {
        match self.len() {
            0 => None,
            l => self.get(l - 1),
        }
    }

    /// Returns `true` if the list contains no elements.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the number of elements in the list.
    pub fn len(&self) -> u64 {
        if let Some(len) = self.length.get() {
            return len;
        }
        let len = self.base.get(&()).unwrap_or(0);
        self.length.set(Some(len));
        len
    }

    /// Returns an iterator over the list. The iterator element type is V.
    pub fn iter(&self) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter_from(&(), &0u64) }
    }

    /// Returns an iterator over the list starting from the specified position. The iterator
    /// element type is V.
    pub fn iter_from(&self, from: u64) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter_from(&(), &from) }
    }
}

impl<'a, V> ListIndex<&'a mut Fork, V>
where
    V: StorageValue,
{
    fn set_len(&mut self, len: u64) {
        self.base.put(&(), len);
        self.length.set(Some(len));
    }

    /// Appends an element to the back of the list.
    pub fn push(&mut self, value: V) {
        let len = self.len();
        self.base.put(&len, value);
        self.set_len(len + 1)
    }

    /// Removes the last element from the list and returns it, or None if it is empty.
    pub fn pop(&mut self) -> Option<V> {
        // TODO: shoud we get and return dropped value?
        match self.len() {
            0 => None,
            l => {
                let v = self.base.get(&(l - 1));
                self.base.remove(&(l - 1));
                self.set_len(l - 1);
                v
            }
        }
    }

    /// Extends the list with the contents of an iterator.
    pub fn extend<I>(&mut self, iter: I)
    where
        I: IntoIterator<Item = V>,
    {
        let mut len = self.len();
        for value in iter {
            self.base.put(&len, value);
            len += 1;
        }
        self.base.put(&(), len);
        self.set_len(len);
    }

    /// Shortens the list, keeping the first `len` elements and dropping the rest.
    ///
    /// If `len` is greater than the list's current length, this has no effect.
    pub fn truncate(&mut self, len: u64) {
        // TODO: optimize this
        while self.len() > len {
            self.pop();
        }
    }

    /// Changes a value at the specified position.
    ///
    /// # Panics
    /// Panics if `index` is equal or greater than the list's current length.
    pub fn set(&mut self, index: u64, value: V) {
        if index >= self.len() {
            panic!(
                "index out of bounds: \
                    the len is {} but the index is {}",
                self.len(),
                index
            );
        }
        self.base.put(&index, value)
    }

    /// Clears the list, removing all values.
    ///
    /// # Notes
    /// Currently this method is not optimized to delete large set of data. During the execution of
    /// this method the amount of allocated memory is linearly dependent on the number of elements
    /// in the index.
    pub fn clear(&mut self) {
        self.length.set(Some(0));
        self.base.clear()
    }
}

impl<'a, T, V> ::std::iter::IntoIterator for &'a ListIndex<T, V>
where
    T: AsRef<Snapshot>,
    V: StorageValue,
{
    type Item = V;
    type IntoIter = ListIndexIter<'a, V>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, V> Iterator for ListIndexIter<'a, V>
where
    V: StorageValue,
{
    type Item = V;

    fn next(&mut self) -> Option<Self::Item> {
        self.base_iter.next().map(|(.., v)| v)
    }
}

#[cfg(test)]
mod tests {
    use super::ListIndex;
    use super::super::{MemoryDB, Database};

    #[test]
    fn test_list_index_methods() {
        let mut fork = MemoryDB::new().fork();
        let mut list_index = ListIndex::new(vec![255], &mut fork);

        assert!(list_index.is_empty());
        assert_eq!(0, list_index.len());
        assert!(list_index.last().is_none());

        let extended_by = vec![45, 3422, 234];
        list_index.extend(extended_by);
        assert!(!list_index.is_empty());
        assert_eq!(Some(45), list_index.get(0));
        assert_eq!(Some(3422), list_index.get(1));
        assert_eq!(Some(234), list_index.get(2));
        assert_eq!(3, list_index.len());

        list_index.set(2, 777);
        assert_eq!(Some(777), list_index.get(2));
        assert_eq!(Some(777), list_index.last());
        assert_eq!(3, list_index.len());

        let mut extended_by_again = vec![666, 999];
        for el in &extended_by_again {
            list_index.push(*el);
        }
        assert_eq!(Some(666), list_index.get(3));
        assert_eq!(Some(999), list_index.get(4));
        assert_eq!(5, list_index.len());
        extended_by_again[1] = 1001;
        list_index.extend(extended_by_again);
        assert_eq!(7, list_index.len());
        assert_eq!(Some(1001), list_index.last());

        assert_eq!(Some(1001), list_index.pop());
        assert_eq!(6, list_index.len());

        list_index.truncate(3);

        assert_eq!(3, list_index.len());
        assert_eq!(Some(777), list_index.last());
    }

    #[test]
    fn test_list_index_iter() {
        let mut fork = MemoryDB::new().fork();
        let mut list_index = ListIndex::new(vec![255], &mut fork);

        list_index.extend(vec![1u8, 2, 3]);

        assert_eq!(list_index.iter().collect::<Vec<u8>>(), vec![1, 2, 3]);

        assert_eq!(list_index.iter_from(0).collect::<Vec<u8>>(), vec![1, 2, 3]);
        assert_eq!(list_index.iter_from(1).collect::<Vec<u8>>(), vec![2, 3]);
        assert_eq!(
            list_index.iter_from(3).collect::<Vec<u8>>(),
            Vec::<u8>::new()
        );
    }
}
<commit_msg>'ListIndex' examples<commit_after>// Copyright 2017 The Exonum Team
//
// 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.

//! An implementation of array list of items.
use std::cell::Cell;
use std::marker::PhantomData;

use super::{BaseIndex, BaseIndexIter, Snapshot, Fork, StorageValue};

/// A list of items that implement `StorageValue` trait.
///
/// `ListIndex` implements an array list, storing the element as values and using `u64` as an index.
/// `ListIndex` requires that the elements implement the [`StorageValue`] trait.
/// [`StorageValue`]: ../trait.StorageValue.html
#[derive(Debug)]
pub struct ListIndex<T, V> {
    base: BaseIndex<T>,
    length: Cell<Option<u64>>,
    _v: PhantomData<V>,
}

/// An iterator over the items of a `ListIndex`.
///
/// This struct is created by the [`iter`] or
/// [`iter_from`] methods on [`ListIndex`]. See its documentation for more.
///
/// [`iter`]: struct.ListIndex.html#method.iter
/// [`iter_from`]: struct.ListIndex.html#method.iter_from
/// [`ListIndex`]: struct.ListIndex.html
#[derive(Debug)]
pub struct ListIndexIter<'a, V> {
    base_iter: BaseIndexIter<'a, u64, V>,
}

impl<T, V> ListIndex<T, V> {
    /// Creates a new index representation based on the common prefix of its keys and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case only
    /// immutable methods are available. In the second case both immutable and mutable methods are
    /// available.
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let index: ListIndex<_, u8> = ListIndex::new(prefix, &snapshot);
    /// # drop(index);
    /// ```
    pub fn new(prefix: Vec<u8>, view: T) -> Self {
        ListIndex {
            base: BaseIndex::new(prefix, view),
            length: Cell::new(None),
            _v: PhantomData,
        }
    }
}

impl<T, V> ListIndex<T, V>
where
    T: AsRef<Snapshot>,
    V: StorageValue,
{
    /// Returns an element at that position or `None` if out of bounds.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let mut index = ListIndex::new(prefix, &snapshot);
    /// assert_eq!(None, index.get(0));
    /// index.push(42);
    /// assert_eq!(Some(42), index.get(0));
    /// ```
    pub fn get(&self, index: u64) -> Option<V> {
        self.base.get(&index)
    }

    /// Returns the last element of the list, or `None` if it is empty.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let mut index = ListIndex::new(prefix, &snapshot);
    /// assert_eq!(None, index.last());
    /// index.push(42);
    /// assert_eq!(Some(42), index.last());
    /// ```
    pub fn last(&self) -> Option<V> {
        match self.len() {
            0 => None,
            l => self.get(l - 1),
        }
    }

    /// Returns `true` if the list contains no elements.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let mut index = ListIndex::new(prefix, &snapshot);
    /// assert!(index.is_empty());
    /// index.push(42);
    /// assert!(!index.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the number of elements in the list.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let mut index = ListIndex::new(prefix, &snapshot);
    /// assert_eq!(0, index.len());
    /// index.push(10);
    /// assert_eq!(1, index.len());
    /// index.push(100);
    /// assert_eq!(2, index.len());
    /// ```
    pub fn len(&self) -> u64 {
        if let Some(len) = self.length.get() {
            return len;
        }
        let len = self.base.get(&()).unwrap_or(0);
        self.length.set(Some(len));
        len
    }

    /// Returns an iterator over the list. The iterator element type is V.
    pub fn iter(&self) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter_from(&(), &0u64) }
    }

    /// Returns an iterator over the list starting from the specified position. The iterator
    /// element type is V.
    pub fn iter_from(&self, from: u64) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter_from(&(), &from) }
    }
}

impl<'a, V> ListIndex<&'a mut Fork, V>
where
    V: StorageValue,
{
    fn set_len(&mut self, len: u64) {
        self.base.put(&(), len);
        self.length.set(Some(len));
    }

    /// Appends an element to the back of the list.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let mut index = ListIndex::new(prefix, &snapshot);
    /// index.push(1);
    /// assert!(!index.is_empty());
    /// ```
    pub fn push(&mut self, value: V) {
        let len = self.len();
        self.base.put(&len, value);
        self.set_len(len + 1)
    }

    /// Removes the last element from the list and returns it, or None if it is empty.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let mut index = ListIndex::new(prefix, &snapshot);
    /// assert_eq!(None, !index.pop());
    /// index.push(1);
    /// assert_eq!(Some(1), !index.pop());
    /// ```
    pub fn pop(&mut self) -> Option<V> {
        // TODO: shoud we get and return dropped value?
        match self.len() {
            0 => None,
            l => {
                let v = self.base.get(&(l - 1));
                self.base.remove(&(l - 1));
                self.set_len(l - 1);
                v
            }
        }
    }

    /// Extends the list with the contents of an iterator.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let mut index = ListIndex::new(prefix, &snapshot);
    /// assert!(index.is_empty());
    /// index.extend([1, 2, 3].iter());
    /// assert_eq!(3, index.len());
    /// ```
    pub fn extend<I>(&mut self, iter: I)
    where
        I: IntoIterator<Item = V>,
    {
        let mut len = self.len();
        for value in iter {
            self.base.put(&len, value);
            len += 1;
        }
        self.base.put(&(), len);
        self.set_len(len);
    }

    /// Shortens the list, keeping the first `len` elements and dropping the rest.
    ///
    /// If `len` is greater than the list's current length, this has no effect.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let mut index = ListIndex::new(prefix, &snapshot);
    /// index.extend([1, 2, 3, 4, 5].iter());
    /// assert_eq!(5, index.len());
    /// index.truncate(3);
    /// assert_eq!(3, index.len());
    /// ```
    pub fn truncate(&mut self, len: u64) {
        // TODO: optimize this
        while self.len() > len {
            self.pop();
        }
    }

    /// Changes a value at the specified position.
    ///
    /// # Panics
    ///
    /// Panics if `index` is equal or greater than the list's current length.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let mut index = ListIndex::new(prefix, &snapshot);
    /// index.push(1);
    /// assert_eq!(Some(1), index.get(0));
    /// index.set(0, 10);
    /// assert_eq!(Some(10), index.get(0));
    /// ```
    pub fn set(&mut self, index: u64, value: V) {
        if index >= self.len() {
            panic!(
                "index out of bounds: \
                    the len is {} but the index is {}",
                self.len(),
                index
            );
        }
        self.base.put(&index, value)
    }

    /// Clears the list, removing all values.
    ///
    /// # Notes
    /// Currently this method is not optimized to delete large set of data. During the execution of
    /// this method the amount of allocated memory is linearly dependent on the number of elements
    /// in the index.
    ///
    /// # Examples
    ///
    /// ```
    /// use exonum::storage::{MemoryDB, Database, ListIndex};
    ///
    /// let db = MemoryDB::new();
    /// let snapshot = db.snapshot();
    /// let prefix = vec![1, 2, 3];
    /// let mut index = ListIndex::new(prefix, &snapshot);
    /// index.push(1);
    /// assert_eq!(!index.is_empty());
    /// index.clear();
    /// assert_eq!(index.is_empty());
    /// ```
    pub fn clear(&mut self) {
        self.length.set(Some(0));
        self.base.clear()
    }
}

impl<'a, T, V> ::std::iter::IntoIterator for &'a ListIndex<T, V>
where
    T: AsRef<Snapshot>,
    V: StorageValue,
{
    type Item = V;
    type IntoIter = ListIndexIter<'a, V>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, V> Iterator for ListIndexIter<'a, V>
where
    V: StorageValue,
{
    type Item = V;

    fn next(&mut self) -> Option<Self::Item> {
        self.base_iter.next().map(|(.., v)| v)
    }
}

#[cfg(test)]
mod tests {
    use super::ListIndex;
    use super::super::{MemoryDB, Database};

    #[test]
    fn test_list_index_methods() {
        let mut fork = MemoryDB::new().fork();
        let mut list_index = ListIndex::new(vec![255], &mut fork);

        assert!(list_index.is_empty());
        assert_eq!(0, list_index.len());
        assert!(list_index.last().is_none());

        let extended_by = vec![45, 3422, 234];
        list_index.extend(extended_by);
        assert!(!list_index.is_empty());
        assert_eq!(Some(45), list_index.get(0));
        assert_eq!(Some(3422), list_index.get(1));
        assert_eq!(Some(234), list_index.get(2));
        assert_eq!(3, list_index.len());

        list_index.set(2, 777);
        assert_eq!(Some(777), list_index.get(2));
        assert_eq!(Some(777), list_index.last());
        assert_eq!(3, list_index.len());

        let mut extended_by_again = vec![666, 999];
        for el in &extended_by_again {
            list_index.push(*el);
        }
        assert_eq!(Some(666), list_index.get(3));
        assert_eq!(Some(999), list_index.get(4));
        assert_eq!(5, list_index.len());
        extended_by_again[1] = 1001;
        list_index.extend(extended_by_again);
        assert_eq!(7, list_index.len());
        assert_eq!(Some(1001), list_index.last());

        assert_eq!(Some(1001), list_index.pop());
        assert_eq!(6, list_index.len());

        list_index.truncate(3);

        assert_eq!(3, list_index.len());
        assert_eq!(Some(777), list_index.last());
    }

    #[test]
    fn test_list_index_iter() {
        let mut fork = MemoryDB::new().fork();
        let mut list_index = ListIndex::new(vec![255], &mut fork);

        list_index.extend(vec![1u8, 2, 3]);

        assert_eq!(list_index.iter().collect::<Vec<u8>>(), vec![1, 2, 3]);

        assert_eq!(list_index.iter_from(0).collect::<Vec<u8>>(), vec![1, 2, 3]);
        assert_eq!(list_index.iter_from(1).collect::<Vec<u8>>(), vec![2, 3]);
        assert_eq!(
            list_index.iter_from(3).collect::<Vec<u8>>(),
            Vec::<u8>::new()
        );
    }
}
<|endoftext|>


<commit_before>extern crate xml;

use std::collections::HashMap;
use std::str;

use xml::writer::{EmitterConfig, XmlEvent};

fn characters_to_xml(characters: HashMap<String, String>) -> String {
    let mut output: Vec<u8> = Vec::new();
    let mut writer = EmitterConfig::new()
        .perform_indent(true)
        .create_writer(&mut output);

    writer
        .write(XmlEvent::start_element("CharacterRemarks"))
        .unwrap();

    for (character, line) in &characters {
        let element = XmlEvent::start_element("Character").attr("name", character);
        writer.write(element).unwrap();
        writer.write(XmlEvent::characters(line)).unwrap();
        writer.write(XmlEvent::end_element()).unwrap();
    }

    writer.write(XmlEvent::end_element()).unwrap();
    str::from_utf8(&output).unwrap().to_string()
}

fn main() {
    let mut input = HashMap::new();
    input.insert(
        "April".to_string(),
        "Bubbly: I'm > Tam and <= Emily".to_string(),
    );
    input.insert(
        "Tam O'Shanter".to_string(),
        "Burns: \"When chapman billies leave the street ...\"".to_string(),
    );
    input.insert("Emily".to_string(), "Short & shrift".to_string());

    let output = characters_to_xml(input);

    println!("{}", output);
    assert!(output.contains(
        "<Character name=\"Tam O'Shanter\">Burns: \"When chapman \
         billies leave the street ...\"</Character>"
    ));
    assert!(
        output.contains("<Character name=\"April\">Bubbly: I'm > Tam and <= Emily</Character>")
    );
    assert!(output.contains("<Character name=\"Emily\">Short & shrift</Character>"));
}
<commit_msg>Put tests in an actual test module<commit_after>extern crate xml;

use std::collections::HashMap;
use std::str;

use xml::writer::{EmitterConfig, XmlEvent};

fn characters_to_xml(characters: HashMap<String, String>) -> String {
    let mut output: Vec<u8> = Vec::new();
    let mut writer = EmitterConfig::new()
        .perform_indent(true)
        .create_writer(&mut output);

    writer
        .write(XmlEvent::start_element("CharacterRemarks"))
        .unwrap();

    for (character, line) in &characters {
        let element = XmlEvent::start_element("Character").attr("name", character);
        writer.write(element).unwrap();
        writer.write(XmlEvent::characters(line)).unwrap();
        writer.write(XmlEvent::end_element()).unwrap();
    }

    writer.write(XmlEvent::end_element()).unwrap();
    str::from_utf8(&output).unwrap().to_string()
}

#[cfg(test)]
mod tests {
    use super::characters_to_xml;
    use std::collections::HashMap;

    #[test]
    fn test_xml_output() {
        let mut input = HashMap::new();
        input.insert(
            "April".to_string(),
            "Bubbly: I'm > Tam and <= Emily".to_string(),
        );
        input.insert(
            "Tam O'Shanter".to_string(),
            "Burns: \"When chapman billies leave the street ...\"".to_string(),
        );
        input.insert("Emily".to_string(), "Short & shrift".to_string());

        let output = characters_to_xml(input);

        println!("{}", output);
        assert!(output.contains(
            "<Character name=\"Tam O'Shanter\">Burns: \"When chapman \
             billies leave the street ...\"</Character>"
        ));
        assert!(output
            .contains("<Character name=\"April\">Bubbly: I'm > Tam and <= Emily</Character>"));
        assert!(output.contains("<Character name=\"Emily\">Short & shrift</Character>"));
    }
}
<|endoftext|>


<commit_before>use std;
use common::*;
use message;

pub struct SegmentReader<'self> {
    messageReader : &'self message::MessageReader<'self>,
    segment : &'self [u8]
}

pub struct SegmentBuilder {
    messageBuilder : @mut message::MessageBuilder,
    segment : ~[u8],
    pos : WordCount
}

impl SegmentBuilder {

    pub fn new(messageBuilder : @mut message::MessageBuilder,
               size : ByteCount) -> SegmentBuilder {
        SegmentBuilder {
            messageBuilder : messageBuilder,
            segment : std::vec::from_elem(size, 0),
            pos : 0
        }
    }

    pub fn allocate(&mut self, amount : WordCount) -> Option<WordCount> {
        if (amount > self.segment.len() - self.pos) {
            return None;
        } else {
            let result = self.pos;
            self.pos += amount;
            return Some(result);
        }
    }
}

<commit_msg>available<commit_after>use std;
use common::*;
use message;

pub struct SegmentReader<'self> {
    messageReader : &'self message::MessageReader<'self>,
    segment : &'self [u8]
}

pub struct SegmentBuilder {
    messageBuilder : @mut message::MessageBuilder,
    segment : ~[u8],
    pos : WordCount
}

impl SegmentBuilder {

    pub fn new(messageBuilder : @mut message::MessageBuilder,
               size : ByteCount) -> SegmentBuilder {
        SegmentBuilder {
            messageBuilder : messageBuilder,
            segment : std::vec::from_elem(size, 0),
            pos : 0
        }
    }

    pub fn allocate(&mut self, amount : WordCount) -> Option<WordCount> {
        if (amount > self.segment.len() - self.pos) {
            return None;
        } else {
            let result = self.pos;
            self.pos += amount;
            return Some(result);
        }
    }

    pub fn available(&self) -> WordCount {
        self.segment.len() * BYTES_PER_WORD - self.pos
    }
}

pub struct BuilderArena {
    message : @mut message::MessageBuilder
}
<|endoftext|>


<commit_before>// This is an implementation of the Sutherland-Hodgman (1974) reentrant polygon
// clipping algorithm. It takes a polygon represented as a number of vertices
// and cuts it according to the given planes.

// The implementation borrows heavily from Pucella-Tov (2008). See that paper
// for more explanation.

#![feature(plugin, custom_derive)]
#![plugin(rand_macros)]

extern crate rust_sessions;
extern crate rand;

use rust_sessions::*;

use std::sync::mpsc::{Sender, Receiver, channel};
use std::thread::spawn;
use std::num::Float;

#[derive(Debug, Copy, Rand)]
struct Point(f64, f64, f64);

#[derive(Debug, Copy, Rand)]
struct Plane(f64, f64, f64, f64);

fn above(Point(x, y, z): Point, Plane(a, b, c, d): Plane) -> bool {
    (a * x + b * y + c * z + d) / Float::sqrt(a * a + b * b + c * c) > 0.0
}

fn intersect(p1: Point, p2: Point, plane: Plane) -> Option<Point> {
    let Point(x1, y1, z1) = p1;
    let Point(x2, y2, z2) = p2;
    let Plane(a, b, c, d) = plane;

    if above(p1, plane) == above(p2, plane) {
        None
    } else {
        let t = (a * x1 + b * y1 + c * z1 + d) /
            (a * (x1 - x2) + b * (y1 - y2) + c * (z1 - z2));
        let x = x1 + (x2 - x1) * t;
        let y = y1 + (y2 - y1) * t;
        let z = z1 + (z2 - z1) * t;
        Some(Point(x, y, z))
    }
}

type SendList = Rec<Choose<Eps, Send<A, Var<Z>>>>;

fn sendlist
    (tx: Sender<Chan<(), SendList>>, xs: Vec)
{
    let c = accept(tx).unwrap();
    let mut c = c.enter();
    for x in xs.iter() {
        let c1 = c.sel2().send(*x);
        c = c1.zero();
    }
    c.sel1().close();
}

fn recvlist
    (rx: Receiver<Chan<(), SendList>>) -> Vec
{
    let c = request(rx).unwrap();
    let mut v = Vec::new();
    let mut c = c.enter();
    loop {
        c = match c.offer() {
            Ok(c) => {
                c.close();
                break;
            }
            Err(c) => {
                let (c, x) = c.recv();
                v.push(x);
                c.zero()
            }
        }
    }

    v
}

fn clipper(plane: Plane,
           inrv: Receiver<Chan<(), SendList<Point>>>,
           outrv: Sender<Chan<(), SendList<Point>>>)
{
    let oc = accept(outrv).unwrap();
    let ic = request(inrv).unwrap();

    let mut oc = oc.enter();
    let mut ic = ic.enter();

    match ic.offer() {
        Ok(c) => {
            c.close();
            oc.sel1().close();
        }
        Err(ic2) => {
            let (ic2, pt0) = ic2.recv();
            ic = ic2.zero();
            let mut pt = pt0;
            loop {
                if above(pt, plane) {
                    oc = oc.sel2().send(pt).zero();
                }
                match ic.offer() {
                    Ok(c) => {
                        match intersect(pt, pt0, plane) {
                            Some(pt) => { oc = oc.sel2().send(pt).zero(); }
                            None => ()
                        }
                        c.close();
                        oc.sel1().close();
                        break;
                    }
                    Err(ic2) => {
                        let (ic2, pt2) = ic2.recv();
                        ic = ic2.zero();
                        match intersect(pt, pt2, plane) {
                            Some(pt) => { oc = oc.sel2().send(pt).zero(); }
                            None => ()
                        }
                        pt = pt2;
                    }
                }
            }
        }
    }
}

fn clipmany(planes: Vec<Plane>, points: Vec<Point>) -> Vec<Point> {
    let (tx, rx) = channel();
    spawn(move || sendlist(tx, points));
    let mut planes = planes;
    let mut rx = rx;
    loop {
        match planes.pop() {
            None => {break;}
            Some(p) => {
                let (tx2, rx2) = channel();
                spawn(move || clipper(p, rx, tx2));
                rx = rx2;
            }
        }
    }
    recvlist(rx)
}

fn normalize_point(Point(a,b,c): Point) -> Point {
    Point(10.0 * (a - 0.5),
          10.0 * (b - 0.5),
          10.0 * (c - 0.5))
}

fn normalize_plane(Plane(a,b,c,d): Plane) -> Plane {
    Plane(10.0 * (a - 0.5),
          10.0 * (b - 0.5),
          10.0 * (c - 0.5),
          10.0 * (d - 0.5))
}

fn bench(n: usize, m: usize) {
    let mut g = rand::thread_rng();
    let points = (0..n)
        .map(|_| rand::Rand::rand(&mut g))
        .map(normalize_point)
        .collect();
    let planes = (0..m)
        .map(|_| rand::Rand::rand(&mut g))
        .map(normalize_plane)
        .collect();

    let points = clipmany(planes, points);
    println!("{}", points.len());
}

fn main() {
    bench(100, 5);
}
<commit_msg>Fix fallout in planeclip.rs<commit_after>// This is an implementation of the Sutherland-Hodgman (1974) reentrant polygon
// clipping algorithm. It takes a polygon represented as a number of vertices
// and cuts it according to the given planes.

// The implementation borrows heavily from Pucella-Tov (2008). See that paper
// for more explanation.

#![feature(plugin, custom_derive)]
#![plugin(rand_macros)]

extern crate rust_sessions;
extern crate rand;

use rust_sessions::*;

use std::sync::mpsc::{Sender, Receiver, channel};
use std::thread::spawn;
use std::num::Float;

#[derive(Debug, Copy, Clone, Rand)]
struct Point(f64, f64, f64);

#[derive(Debug, Copy, Clone, Rand)]
struct Plane(f64, f64, f64, f64);

fn above(Point(x, y, z): Point, Plane(a, b, c, d): Plane) -> bool {
    (a * x + b * y + c * z + d) / Float::sqrt(a * a + b * b + c * c) > 0.0
}

fn intersect(p1: Point, p2: Point, plane: Plane) -> Option<Point> {
    let Point(x1, y1, z1) = p1;
    let Point(x2, y2, z2) = p2;
    let Plane(a, b, c, d) = plane;

    if above(p1, plane) == above(p2, plane) {
        None
    } else {
        let t = (a * x1 + b * y1 + c * z1 + d) /
            (a * (x1 - x2) + b * (y1 - y2) + c * (z1 - z2));
        let x = x1 + (x2 - x1) * t;
        let y = y1 + (y2 - y1) * t;
        let z = z1 + (z2 - z1) * t;
        Some(Point(x, y, z))
    }
}

type SendList = Rec<Choose<Eps, Send<A, Var<Z>>>>;

fn sendlist
    (tx: Sender<Chan<(), SendList>>, xs: Vec)
{
    let c = accept(tx).unwrap();
    let mut c = c.enter();
    for x in xs.iter() {
        let c1 = c.sel2().send(*x);
        c = c1.zero();
    }
    c.sel1().close();
}

fn recvlist
    (rx: Receiver<Chan<(), SendList>>) -> Vec
{
    let c = request(rx).unwrap();
    let mut v = Vec::new();
    let mut c = c.enter();
    loop {
        c = match c.offer() {
            Ok(c) => {
                c.close();
                break;
            }
            Err(c) => {
                let (c, x) = c.recv();
                v.push(x);
                c.zero()
            }
        }
    }

    v
}

fn clipper(plane: Plane,
           inrv: Receiver<Chan<(), SendList<Point>>>,
           outrv: Sender<Chan<(), SendList<Point>>>)
{
    let oc = accept(outrv).unwrap();
    let ic = request(inrv).unwrap();

    let mut oc = oc.enter();
    let mut ic = ic.enter();

    match ic.offer() {
        Ok(c) => {
            c.close();
            oc.sel1().close();
        }
        Err(ic2) => {
            let (ic2, pt0) = ic2.recv();
            ic = ic2.zero();
            let mut pt = pt0;
            loop {
                if above(pt, plane) {
                    oc = oc.sel2().send(pt).zero();
                }
                match ic.offer() {
                    Ok(c) => {
                        match intersect(pt, pt0, plane) {
                            Some(pt) => { oc = oc.sel2().send(pt).zero(); }
                            None => ()
                        }
                        c.close();
                        oc.sel1().close();
                        break;
                    }
                    Err(ic2) => {
                        let (ic2, pt2) = ic2.recv();
                        ic = ic2.zero();
                        match intersect(pt, pt2, plane) {
                            Some(pt) => { oc = oc.sel2().send(pt).zero(); }
                            None => ()
                        }
                        pt = pt2;
                    }
                }
            }
        }
    }
}

fn clipmany(planes: Vec<Plane>, points: Vec<Point>) -> Vec<Point> {
    let (tx, rx) = channel();
    spawn(move || sendlist(tx, points));
    let mut planes = planes;
    let mut rx = rx;
    loop {
        match planes.pop() {
            None => {break;}
            Some(p) => {
                let (tx2, rx2) = channel();
                spawn(move || clipper(p, rx, tx2));
                rx = rx2;
            }
        }
    }
    recvlist(rx)
}

fn normalize_point(Point(a,b,c): Point) -> Point {
    Point(10.0 * (a - 0.5),
          10.0 * (b - 0.5),
          10.0 * (c - 0.5))
}

fn normalize_plane(Plane(a,b,c,d): Plane) -> Plane {
    Plane(10.0 * (a - 0.5),
          10.0 * (b - 0.5),
          10.0 * (c - 0.5),
          10.0 * (d - 0.5))
}

fn bench(n: usize, m: usize) {
    let mut g = rand::thread_rng();
    let points = (0..n)
        .map(|_| rand::Rand::rand(&mut g))
        .map(normalize_point)
        .collect();
    let planes = (0..m)
        .map(|_| rand::Rand::rand(&mut g))
        .map(normalize_plane)
        .collect();

    let points = clipmany(planes, points);
    println!("{}", points.len());
}

fn main() {
    bench(100, 5);
}
<|endoftext|>


<commit_before>extern crate gltf;

use std::{fs, io};

use gltf::{Glb, Gltf};
use std::boxed::Box;
use std::error::Error as StdError;

fn print_tree(node: &gltf::Node, depth: i32) {
    for _ in 0..(depth - 1) {
        print!("  ");
    }
    print!(" -");
    let index = node.index();
    let name = node.name().unwrap_or("<Unnamed>");
    println!(" Node {} ({})", index, name);
    for child in node.children() {
        print_tree(&child, depth + 1);
    }
}

fn run(path: &str) -> Result<(), Box<StdError>> {
    use io::Read;
    let file = fs::File::open(&path)?;
    let mut data = Vec::with_capacity(file.metadata()?.len() as usize);
    let mut reader = io::BufReader::new(file);
    let _ = reader.read_to_end(&mut data)?;
    let gltf = if gltf::is_binary(&data) {
        let glb = Glb::from_slice(&data)?;
        Gltf::from_slice(glb.json)
    } else {
        Gltf::from_slice(&data)
    }?.validate_completely()?;
    for scene in gltf.scenes() {
        let index = scene.index();
        let name = scene.name().unwrap_or("<Unnamed>");
        println!("Scene {} ({})", index, name);
        for node in scene.nodes() {
            print_tree(&node, 1);
        }
    }
    Ok(())
}

fn main() {
    if let Some(path) = std::env::args().nth(1) {
        run(&path).expect("runtime error");
    } else {
        println!("usage: gltf-tree <FILE>");
    }
}
<commit_msg>Fix tree example<commit_after>extern crate gltf;

use std::{fs, io};

use gltf::{Glb, Gltf};
use std::boxed::Box;
use std::error::Error as StdError;

fn print_tree(node: &gltf::Node, depth: i32) {
    for _ in 0..(depth - 1) {
        print!("  ");
    }
    print!(" -");
    let index = node.index();
    let name = node.name().unwrap_or("<Unnamed>");
    println!(" Node {} ({})", index, name);
    for child in node.children() {
        print_tree(&child, depth + 1);
    }
}

fn run(path: &str) -> Result<(), Box<StdError>> {
    use io::Read;
    let file = fs::File::open(&path)?;
    let mut data = Vec::with_capacity(file.metadata()?.len() as usize);
    let mut reader = io::BufReader::new(file);
    let _ = reader.read_to_end(&mut data)?;
    let gltf = if gltf::is_binary(&data) {
        let glb = Glb::from_slice(&data)?;
        Gltf::from_slice(&glb.json)
    } else {
        Gltf::from_slice(&data)
    }?.validate_completely()?;
    for scene in gltf.scenes() {
        let index = scene.index();
        let name = scene.name().unwrap_or("<Unnamed>");
        println!("Scene {} ({})", index, name);
        for node in scene.nodes() {
            print_tree(&node, 1);
        }
    }
    Ok(())
}

fn main() {
    if let Some(path) = std::env::args().nth(1) {
        run(&path).expect("runtime error");
    } else {
        println!("usage: gltf-tree <FILE>");
    }
}
<|endoftext|>


<commit_before>use super::Rope;
use std::iter;

#[test]
fn rebalance_test_1() {
    let r = Rope::from("This is a large string \
                        that will need to be rebalanced.".to_string());
    let r = r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn rebalance_test_2() {
    let r = Rope::from("Lorem ipsum dolor sit amet, consectetur adipiscing eli\
                        t, sed do eiusmod tempor incididunt ut labore et dolor\
                        e magna aliqua. Ut enim ad minim veniam, quis nostrud \
                        exercitation ullamco laboris nisi ut aliquip ex ea com\
                        modo consequat. Duis aute irure dolor in reprehenderit\
                         in voluptate velit esse cillum dolore eu fugiat nulla\
                         pariatur. Excepteur sint occaecat cupidatat non proid\
                        ent, sunt in culpa qui officia deserunt mollit anim id\
                         est laborum.".to_string());
    let r = r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn big_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let r = Rope::from(s);
    let r = r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn repeated_concat_left_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let mut r = Rope::from(s);
    for _ in 1..1000 {
        r = r + iter::repeat('a').take(100).collect::<String>();
    }
    assert!(r.is_balanced());
}

#[test]
fn repeated_concat_right_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let mut r = Rope::from(s);
    for _ in 1..1000 {
        let s2 = iter::repeat('a').take(100).collect::<String>();
        r = Rope::from(s2) + r;
    }
    assert!(r.is_balanced());
}

#[test]
fn merge_rebalance_test() {
    let s = "Lorem ipsum dolor sit amet, consectetur adipiscing eli\
             t, sed do eiusmod tempor incididunt ut labore et dolor\
             e magna aliqua. Ut enim ad minim veniam, quis nostrud \
             exercitation ullamco laboris nisi ut aliquip ex ea com\
             modo consequat. Duis aute irure dolor in reprehenderit\
              in voluptate velit esse cillum dolore eu fugiat nulla\
              pariatur. Excepteur sint occaecat cupidatat non proid\
             ent, sunt in culpa qui officia deserunt mollit anim id\
              est laborum.";

     let t = Rope::from(s.to_owned());
     let u = t + s;
     let u = u.rebalance();
     assert!(u.is_balanced());
}
<commit_msg>Basic insertion tests<commit_after>use super::Rope;
use std::iter;

#[test]
fn rebalance_test_1() {
    let r = Rope::from("This is a large string \
                        that will need to be rebalanced.".to_string());
    let r = r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn rebalance_test_2() {
    let r = Rope::from("Lorem ipsum dolor sit amet, consectetur adipiscing eli\
                        t, sed do eiusmod tempor incididunt ut labore et dolor\
                        e magna aliqua. Ut enim ad minim veniam, quis nostrud \
                        exercitation ullamco laboris nisi ut aliquip ex ea com\
                        modo consequat. Duis aute irure dolor in reprehenderit\
                         in voluptate velit esse cillum dolore eu fugiat nulla\
                         pariatur. Excepteur sint occaecat cupidatat non proid\
                        ent, sunt in culpa qui officia deserunt mollit anim id\
                         est laborum.".to_string());
    let r = r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn big_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let r = Rope::from(s);
    let r = r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn repeated_concat_left_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let mut r = Rope::from(s);
    for _ in 1..1000 {
        r = r + iter::repeat('a').take(100).collect::<String>();
    }
    assert!(r.is_balanced());
}

#[test]
fn repeated_concat_right_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let mut r = Rope::from(s);
    for _ in 1..1000 {
        let s2 = iter::repeat('a').take(100).collect::<String>();
        r = Rope::from(s2) + r;
    }
    assert!(r.is_balanced());
}

#[test]
fn merge_rebalance_test() {
    let s = "Lorem ipsum dolor sit amet, consectetur adipiscing eli\
             t, sed do eiusmod tempor incididunt ut labore et dolor\
             e magna aliqua. Ut enim ad minim veniam, quis nostrud \
             exercitation ullamco laboris nisi ut aliquip ex ea com\
             modo consequat. Duis aute irure dolor in reprehenderit\
              in voluptate velit esse cillum dolore eu fugiat nulla\
              pariatur. Excepteur sint occaecat cupidatat non proid\
             ent, sunt in culpa qui officia deserunt mollit anim id\
              est laborum.";

     let t = Rope::from(s.to_owned());
     let u = t + s;
     let u = u.rebalance();
     assert!(u.is_balanced());
}

#[test]
fn insert_balance_test() {
    let s: String = iter::repeat('a').take(10).collect();
    let r_1 = Rope::from(s);
    for _ in 0..99 {
        let t: String = iter::repeat('a').take(10).collect();
        r_1.insert(&Rope::from(t), 5);
    }

    r_1.rebalance();
    assert!(r_1.is_balanced());
}

#[test]
fn insert_test_1() {
    let s: String = iter::repeat('a').take(1_000).collect();
    let r_1 = Rope::from(s);
    let r_2 = Rope::new();
    for _ in 0..100 {
        let t: String = iter::repeat('a').take(10).collect();
        r_2.insert(&Rope::from(t), 0);
    }
    assert_eq!(r_1, r_2);
}

#[test]
fn insert_test_2() {
    let s: String = iter::repeat('a').take(10).collect();
    let r_1 = Rope::from(s);
    for _ in 0..99 {
        let t: String = iter::repeat('a').take(10).collect();
        r_1.insert(&Rope::from(t), 5);
    }

    let q: String = iter::repeat('a').take(1_000).collect();
    let r_2 = Rope::from(q);
    assert_eq!(r_1, r_2);
}

#[test]
fn insert_test_3() {
    let s_1 = Rope::from(String::from("aaaaa"));
    let s_2 = Rope::from(String::from("bbbbb"));
    let s_3 = Rope::from(String::from("ccccc"));
    s_2.insert(&s_3, 0);
    s_1.insert(&s_2, 0);
    assert_eq!(s_1, "cccccbbbbbaaaaa");
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::collections::hash_map::HashMap;
use std::sync::mpsc::{channel, Sender, Receiver};

use threadpool::ThreadPool;
use term::color::YELLOW;

use core::{Package, PackageId, Resolve, PackageSet};
use util::{Config, DependencyQueue, Fresh, Dirty, Freshness};
use util::{CargoResult, Dependency, profile};

use super::job::Job;

/// A management structure of the entire dependency graph to compile.
///
/// This structure is backed by the `DependencyQueue` type and manages the
/// actual compilation step of each package. Packages enqueue units of work and
/// then later on the entire graph is processed and compiled.
pub struct JobQueue<'a> {
    pool: ThreadPool,
    queue: DependencyQueue<(&'a PackageId, Stage),
                           (&'a Package, Vec<(Job, Freshness)>)>,
    tx: Sender<Message>,
    rx: Receiver<Message>,
    resolve: &'a Resolve,
    packages: &'a PackageSet,
    active: u32,
    pending: HashMap<(&'a PackageId, Stage), PendingBuild>,
    pkgids: HashSet<&'a PackageId>,
    printed: HashSet<&'a PackageId>,
}

/// A helper structure for metadata about the state of a building package.
struct PendingBuild {
    /// Number of jobs currently active
    amt: u32,
    /// Current freshness state of this package. Any dirty target within a
    /// package will cause the entire package to become dirty.
    fresh: Freshness,
}

/// Current stage of compilation for an individual package.
///
/// This is the second layer of keys on the dependency queue to track the state
/// of where a particular package is in the compilation pipeline. Each of these
/// stages has a network of dependencies among them, outlined by the
/// `Dependency` implementation found below.
///
/// Each build step for a package is registered with one of these stages, and
/// each stage has a vector of work to perform in parallel.
#[derive(Hash, PartialEq, Eq, Clone, PartialOrd, Ord, Debug, Copy)]
pub enum Stage {
    Start,
    BuildCustomBuild,
    RunCustomBuild,
    Libraries,
    Binaries,
    LibraryTests,
    BinaryTests,
    End,
}

type Message = (PackageId, Stage, Freshness, CargoResult<()>);

impl<'a> JobQueue<'a> {
    pub fn new(resolve: &'a Resolve, packages: &'a PackageSet, jobs: u32)
               -> JobQueue<'a> {
        let (tx, rx) = channel();
        JobQueue {
            pool: ThreadPool::new(jobs as usize),
            queue: DependencyQueue::new(),
            tx: tx,
            rx: rx,
            resolve: resolve,
            packages: packages,
            active: 0,
            pending: HashMap::new(),
            pkgids: HashSet::new(),
            printed: HashSet::new(),
        }
    }

    pub fn queue(&mut self, pkg: &'a Package, stage: Stage)
                 -> &mut Vec<(Job, Freshness)> {
        self.pkgids.insert(pkg.package_id());
        &mut self.queue.queue(&(self.resolve, self.packages), Fresh,
                              (pkg.package_id(), stage),
                              (pkg, Vec::new())).1
    }

    /// Execute all jobs necessary to build the dependency graph.
    ///
    /// This function will spawn off `config.jobs()` workers to build all of the
    /// necessary dependencies, in order. Freshness is propagated as far as
    /// possible along each dependency chain.
    pub fn execute(&mut self, config: &Config) -> CargoResult<()> {
        let _p = profile::start("executing the job graph");

        // Iteratively execute the dependency graph. Each turn of this loop will
        // schedule as much work as possible and then wait for one job to finish,
        // possibly scheduling more work afterwards.
        while self.queue.len() > 0 {
            loop {
                match self.queue.dequeue() {
                    Some((fresh, (_, stage), (pkg, jobs))) => {
                        info!("start: {} {:?}", pkg, stage);
                        try!(self.run(pkg, stage, fresh, jobs, config));
                    }
                    None => break,
                }
            }

            // Now that all possible work has been scheduled, wait for a piece
            // of work to finish. If any package fails to build then we stop
            // scheduling work as quickly as possibly.
            let (id, stage, fresh, result) = self.rx.recv().unwrap();
            info!("  end: {} {:?}", id, stage);
            let id = *self.pkgids.iter().find(|&k| *k == &id).unwrap();
            self.active -= 1;
            match result {
                Ok(()) => {
                    let state = self.pending.get_mut(&(id, stage)).unwrap();
                    state.amt -= 1;
                    state.fresh = state.fresh.combine(fresh);
                    if state.amt == 0 {
                        self.queue.finish(&(id, stage), state.fresh);
                    }
                }
                Err(e) => {
                    if self.active > 0 {
                        try!(config.shell().say(
                                    "Build failed, waiting for other \
                                     jobs to finish...", YELLOW));
                        for _ in self.rx.iter().take(self.active as usize) {}
                    }
                    return Err(e)
                }
            }
        }

        trace!("rustc jobs completed");

        Ok(())
    }

    /// Execute a stage of compilation for a package.
    ///
    /// The input freshness is from `dequeue()` and indicates the combined
    /// freshness of all upstream dependencies. This function will schedule all
    /// work in `jobs` to be executed.
    fn run(&mut self, pkg: &'a Package, stage: Stage, fresh: Freshness,
           jobs: Vec<(Job, Freshness)>, config: &Config) -> CargoResult<()> {
        let njobs = jobs.len();
        let amt = if njobs == 0 {1} else {njobs as u32};
        let id = pkg.package_id().clone();

        // While the jobs are all running, we maintain some metadata about how
        // many are running, the current state of freshness (of all the combined
        // jobs), and the stage to pass to finish() later on.
        self.active += amt;
        self.pending.insert((pkg.package_id(), stage), PendingBuild {
            amt: amt,
            fresh: fresh,
        });

        let mut total_fresh = fresh;
        let mut running = Vec::new();
        debug!("start {:?} at {:?} for {}", total_fresh, stage, pkg);
        for (job, job_freshness) in jobs.into_iter() {
            debug!("job: {:?} ({:?})", job_freshness, total_fresh);
            let fresh = job_freshness.combine(fresh);
            total_fresh = total_fresh.combine(fresh);
            let my_tx = self.tx.clone();
            let id = id.clone();
            let (desc_tx, desc_rx) = channel();
            self.pool.execute(move|| {
                my_tx.send((id, stage, fresh, job.run(fresh, desc_tx))).unwrap();
            });
            // only the first message of each job is processed
            match desc_rx.recv() {
                Ok(msg) => running.push(msg),
                Err(..) => {}
            }
        }

        // If no work was scheduled, make sure that a message is actually send
        // on this channel.
        if njobs == 0 {
            self.tx.send((id, stage, fresh, Ok(()))).unwrap();
        }

        // Print out some nice progress information
        try!(self.note_working_on(config, pkg.package_id(), stage, total_fresh,
                                  running.len()));
        for msg in running.iter() {
            try!(config.shell().verbose(|c| c.status("Running", msg)));
        }
        Ok(())
    }

    // This isn't super trivial becuase we don't want to print loads and
    // loads of information to the console, but we also want to produce a
    // faithful representation of what's happening. This is somewhat nuanced
    // as a package can start compiling *very* early on because of custom
    // build commands and such.
    //
    // In general, we try to print "Compiling" for the first nontrivial task
    // run for a package, regardless of when that is. We then don't print
    // out any more information for a package after we've printed it once.
    fn note_working_on(&mut self, config: &Config, pkg: &'a PackageId,
                       stage: Stage, fresh: Freshness, cmds_run: usize)
                       -> CargoResult<()> {
        if self.printed.contains(&pkg) { return Ok(()) }

        match fresh {
            // Any dirty stage which runs at least one command gets printed as
            // being a compiled package
            Dirty if cmds_run == 0 => {}
            Dirty => {
                self.printed.insert(pkg);
                try!(config.shell().status("Compiling", pkg));
            }
            Fresh if stage == Stage::End => {
                self.printed.insert(pkg);
                try!(config.shell().verbose(|c| c.status("Fresh", pkg)));
            }
            Fresh => {}
        }
        Ok(())
    }
}

impl<'a> Dependency for (&'a PackageId, Stage) {
    type Context = (&'a Resolve, &'a PackageSet);

    fn dependencies(&self, &(resolve, packages): &(&'a Resolve, &'a PackageSet))
                    -> Vec<(&'a PackageId, Stage)> {
        // This implementation of `Dependency` is the driver for the structure
        // of the dependency graph of packages to be built. The "key" here is
        // a pair of the package being built and the stage that it's at.
        //
        // Each stage here lists dependencies on the previous stages except for
        // the start state which depends on the ending state of all dependent
        // packages (as determined by the resolve context).
        let (id, stage) = *self;
        let pkg = packages.iter().find(|p| p.package_id() == id).unwrap();
        let deps = resolve.deps(id).into_iter().flat_map(|a| a)
                          .filter(|dep| *dep != id);
        match stage {
            Stage::Start => Vec::new(),

            // Building the build command itself starts off pretty easily,we
            // just need to depend on all of the library stages of our own build
            // dependencies (making them available to us).
            Stage::BuildCustomBuild => {
                let mut base = vec![(id, Stage::Start)];
                base.extend(deps
                    .filter(|id| pkg.dependencies().iter()
                        .find(|d| d.name() == id.name() && d.is_build())
                        .is_some())
                    .map(|id| (id, Stage::Libraries)));
                base
            }

            // When running a custom build command, we need to be sure that our
            // own custom build command is actually built, and then we need to
            // wait for all our dependencies to finish their custom build
            // commands themselves (as they may provide input to us).
            Stage::RunCustomBuild => {
                let mut base = vec![(id, Stage::BuildCustomBuild)];
                base.extend(deps
                    .filter(|id| pkg.dependencies().iter()
                        .find(|d| d.name() == id.name() && d.is_transitive())
                        .is_some())
                    .map(|id| (id, Stage::RunCustomBuild)));
                base
            }

            // Building a library depends on our own custom build command plus
            // all our transitive dependencies.
            Stage::Libraries => {
                let mut base = vec![(id, Stage::RunCustomBuild)];
                base.extend(deps
                    .filter(|id| pkg.dependencies().iter()
                        .find(|d| d.name() == id.name() && d.is_transitive())
                        .is_some())
                    .map(|id| (id, Stage::Libraries)));
                base
            }

            // Binaries only depend on libraries being available. Note that they
            // do not depend on dev-dependencies.
            Stage::Binaries => vec![(id, Stage::Libraries)],

            // Tests depend on all dependencies (including dev-dependencies) in
            // addition to the library stage for this package. Note, however,
            // that library tests only need to depend the custom build command
            // being run, not the libraries themselves.
            Stage::BinaryTests | Stage::LibraryTests => {
                let mut base = if stage == Stage::BinaryTests {
                    vec![(id, Stage::Libraries)]
                } else {
                    vec![(id, Stage::RunCustomBuild)]
                };
                base.extend(deps.map(|id| (id, Stage::Libraries)));
                base
            }

            // A marker stage to indicate when a package has entirely finished
            // compiling, nothing is actually built as part of this stage.
            Stage::End => {
                vec![(id, Stage::Binaries), (id, Stage::BinaryTests),
                     (id, Stage::LibraryTests)]
            }
        }
    }
}
<commit_msg>Formatting<commit_after>use std::collections::HashSet;
use std::collections::hash_map::HashMap;
use std::sync::mpsc::{channel, Sender, Receiver};

use threadpool::ThreadPool;
use term::color::YELLOW;

use core::{Package, PackageId, Resolve, PackageSet};
use util::{Config, DependencyQueue, Fresh, Dirty, Freshness};
use util::{CargoResult, Dependency, profile};

use super::job::Job;

/// A management structure of the entire dependency graph to compile.
///
/// This structure is backed by the `DependencyQueue` type and manages the
/// actual compilation step of each package. Packages enqueue units of work and
/// then later on the entire graph is processed and compiled.
pub struct JobQueue<'a> {
    pool: ThreadPool,
    queue: DependencyQueue<(&'a PackageId, Stage),
                           (&'a Package, Vec<(Job, Freshness)>)>,
    tx: Sender<Message>,
    rx: Receiver<Message>,
    resolve: &'a Resolve,
    packages: &'a PackageSet,
    active: u32,
    pending: HashMap<(&'a PackageId, Stage), PendingBuild>,
    pkgids: HashSet<&'a PackageId>,
    printed: HashSet<&'a PackageId>,
}

/// A helper structure for metadata about the state of a building package.
struct PendingBuild {
    /// Number of jobs currently active
    amt: u32,
    /// Current freshness state of this package. Any dirty target within a
    /// package will cause the entire package to become dirty.
    fresh: Freshness,
}

/// Current stage of compilation for an individual package.
///
/// This is the second layer of keys on the dependency queue to track the state
/// of where a particular package is in the compilation pipeline. Each of these
/// stages has a network of dependencies among them, outlined by the
/// `Dependency` implementation found below.
///
/// Each build step for a package is registered with one of these stages, and
/// each stage has a vector of work to perform in parallel.
#[derive(Hash, PartialEq, Eq, Clone, PartialOrd, Ord, Debug, Copy)]
pub enum Stage {
    Start,
    BuildCustomBuild,
    RunCustomBuild,
    Libraries,
    Binaries,
    LibraryTests,
    BinaryTests,
    End,
}

type Message = (PackageId, Stage, Freshness, CargoResult<()>);

impl<'a> JobQueue<'a> {
    pub fn new(resolve: &'a Resolve, packages: &'a PackageSet, jobs: u32)
               -> JobQueue<'a> {
        let (tx, rx) = channel();
        JobQueue {
            pool: ThreadPool::new(jobs as usize),
            queue: DependencyQueue::new(),
            tx: tx,
            rx: rx,
            resolve: resolve,
            packages: packages,
            active: 0,
            pending: HashMap::new(),
            pkgids: HashSet::new(),
            printed: HashSet::new(),
        }
    }

    pub fn queue(&mut self, pkg: &'a Package, stage: Stage)
                 -> &mut Vec<(Job, Freshness)> {
        self.pkgids.insert(pkg.package_id());
        &mut self.queue.queue(&(self.resolve, self.packages), Fresh,
                              (pkg.package_id(), stage),
                              (pkg, Vec::new())).1
    }

    /// Execute all jobs necessary to build the dependency graph.
    ///
    /// This function will spawn off `config.jobs()` workers to build all of the
    /// necessary dependencies, in order. Freshness is propagated as far as
    /// possible along each dependency chain.
    pub fn execute(&mut self, config: &Config) -> CargoResult<()> {
        let _p = profile::start("executing the job graph");

        // Iteratively execute the dependency graph. Each turn of this loop will
        // schedule as much work as possible and then wait for one job to finish,
        // possibly scheduling more work afterwards.
        while self.queue.len() > 0 {
            loop {
                match self.queue.dequeue() {
                    Some((fresh, (_, stage), (pkg, jobs))) => {
                        info!("start: {} {:?}", pkg, stage);
                        try!(self.run(pkg, stage, fresh, jobs, config));
                    }
                    None => break,
                }
            }

            // Now that all possible work has been scheduled, wait for a piece
            // of work to finish. If any package fails to build then we stop
            // scheduling work as quickly as possibly.
            let (id, stage, fresh, result) = self.rx.recv().unwrap();
            info!("  end: {} {:?}", id, stage);
            let id = *self.pkgids.iter().find(|&k| *k == &id).unwrap();
            self.active -= 1;
            match result {
                Ok(()) => {
                    let state = self.pending.get_mut(&(id, stage)).unwrap();
                    state.amt -= 1;
                    state.fresh = state.fresh.combine(fresh);
                    if state.amt == 0 {
                        self.queue.finish(&(id, stage), state.fresh);
                    }
                }
                Err(e) => {
                    if self.active > 0 {
                        try!(config.shell().say(
                                    "Build failed, waiting for other \
                                     jobs to finish...", YELLOW));
                        for _ in self.rx.iter().take(self.active as usize) {}
                    }
                    return Err(e)
                }
            }
        }

        trace!("rustc jobs completed");

        Ok(())
    }

    /// Execute a stage of compilation for a package.
    ///
    /// The input freshness is from `dequeue()` and indicates the combined
    /// freshness of all upstream dependencies. This function will schedule all
    /// work in `jobs` to be executed.
    fn run(&mut self, pkg: &'a Package, stage: Stage, fresh: Freshness,
           jobs: Vec<(Job, Freshness)>, config: &Config) -> CargoResult<()> {
        let njobs = jobs.len();
        let amt = if njobs == 0 {1} else {njobs as u32};
        let id = pkg.package_id().clone();

        // While the jobs are all running, we maintain some metadata about how
        // many are running, the current state of freshness (of all the combined
        // jobs), and the stage to pass to finish() later on.
        self.active += amt;
        self.pending.insert((pkg.package_id(), stage), PendingBuild {
            amt: amt,
            fresh: fresh,
        });

        let mut total_fresh = fresh;
        let mut running = Vec::new();
        debug!("start {:?} at {:?} for {}", total_fresh, stage, pkg);
        for (job, job_freshness) in jobs.into_iter() {
            debug!("job: {:?} ({:?})", job_freshness, total_fresh);
            let fresh = job_freshness.combine(fresh);
            total_fresh = total_fresh.combine(fresh);
            let my_tx = self.tx.clone();
            let id = id.clone();
            let (desc_tx, desc_rx) = channel();
            self.pool.execute(move|| {
                my_tx.send((id, stage, fresh, job.run(fresh, desc_tx))).unwrap();
            });
            // only the first message of each job is processed
            match desc_rx.recv() {
                Ok(msg) => running.push(msg),
                Err(..) => {}
            }
        }

        // If no work was scheduled, make sure that a message is actually send
        // on this channel.
        if njobs == 0 {
            self.tx.send((id, stage, fresh, Ok(()))).unwrap();
        }

        // Print out some nice progress information
        try!(self.note_working_on(config, pkg.package_id(), stage, total_fresh,
                                  running.len()));
        for msg in running.iter() {
            try!(config.shell().verbose(|c| c.status("Running", msg)));
        }
        Ok(())
    }

    // This isn't super trivial becuase we don't want to print loads and
    // loads of information to the console, but we also want to produce a
    // faithful representation of what's happening. This is somewhat nuanced
    // as a package can start compiling *very* early on because of custom
    // build commands and such.
    //
    // In general, we try to print "Compiling" for the first nontrivial task
    // run for a package, regardless of when that is. We then don't print
    // out any more information for a package after we've printed it once.
    fn note_working_on(&mut self, config: &Config, pkg: &'a PackageId,
                       stage: Stage, fresh: Freshness, cmds_run: usize)
                       -> CargoResult<()> {
        if self.printed.contains(&pkg) { return Ok(()) }

        match fresh {
            // Any dirty stage which runs at least one command gets printed as
            // being a compiled package
            Dirty if cmds_run == 0 => {}
            Dirty => {
                self.printed.insert(pkg);
                try!(config.shell().status("Compiling", pkg));
            }
            Fresh if stage == Stage::End => {
                self.printed.insert(pkg);
                try!(config.shell().verbose(|c| c.status("Fresh", pkg)));
            }
            Fresh => {}
        }
        Ok(())
    }
}

impl<'a> Dependency for (&'a PackageId, Stage) {
    type Context = (&'a Resolve, &'a PackageSet);

    fn dependencies(&self, &(resolve, packages): &(&'a Resolve, &'a PackageSet))
                    -> Vec<(&'a PackageId, Stage)> {
        // This implementation of `Dependency` is the driver for the structure
        // of the dependency graph of packages to be built. The "key" here is
        // a pair of the package being built and the stage that it's at.
        //
        // Each stage here lists dependencies on the previous stages except for
        // the start state which depends on the ending state of all dependent
        // packages (as determined by the resolve context).
        let (id, stage) = *self;
        let pkg = packages.iter().find(|p| p.package_id() == id).unwrap();
        let deps = resolve.deps(id).into_iter().flat_map(|a| a)
                          .filter(|dep| *dep != id);
        match stage {
            Stage::Start => Vec::new(),

            // Building the build command itself starts off pretty easily,we
            // just need to depend on all of the library stages of our own build
            // dependencies (making them available to us).
            Stage::BuildCustomBuild => {
                let mut base = vec![(id, Stage::Start)];
                base.extend(deps.filter(|id| {
                    pkg.dependencies().iter().any(|d| {
                        d.name() == id.name() && d.is_build()
                    })
                }).map(|id| (id, Stage::Libraries)));
                base
            }

            // When running a custom build command, we need to be sure that our
            // own custom build command is actually built, and then we need to
            // wait for all our dependencies to finish their custom build
            // commands themselves (as they may provide input to us).
            Stage::RunCustomBuild => {
                let mut base = vec![(id, Stage::BuildCustomBuild)];
                base.extend(deps.filter(|id| {
                    pkg.dependencies().iter().any(|d| {
                        d.name() == id.name() && d.is_transitive()
                    })
                }).map(|id| (id, Stage::RunCustomBuild)));
                base
            }

            // Building a library depends on our own custom build command plus
            // all our transitive dependencies.
            Stage::Libraries => {
                let mut base = vec![(id, Stage::RunCustomBuild)];
                base.extend(deps.filter(|id| {
                    pkg.dependencies().iter().any(|d| {
                        d.name() == id.name() && d.is_transitive()
                    })
                }).map(|id| (id, Stage::Libraries)));
                base
            }

            // Binaries only depend on libraries being available. Note that they
            // do not depend on dev-dependencies.
            Stage::Binaries => vec![(id, Stage::Libraries)],

            // Tests depend on all dependencies (including dev-dependencies) in
            // addition to the library stage for this package. Note, however,
            // that library tests only need to depend the custom build command
            // being run, not the libraries themselves.
            Stage::BinaryTests | Stage::LibraryTests => {
                let mut base = if stage == Stage::BinaryTests {
                    vec![(id, Stage::Libraries)]
                } else {
                    vec![(id, Stage::RunCustomBuild)]
                };
                base.extend(deps.map(|id| (id, Stage::Libraries)));
                base
            }

            // A marker stage to indicate when a package has entirely finished
            // compiling, nothing is actually built as part of this stage.
            Stage::End => {
                vec![(id, Stage::Binaries), (id, Stage::BinaryTests),
                     (id, Stage::LibraryTests)]
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Asynchronous I/O
//!
//! This crate contains the `AsyncRead` and `AsyncWrite` traits, the
//! asynchronous analogs to `std::io::{Read, Write}`. The primary difference is
//! that these traits integrate with the asynchronous task system.

#![no_std]
#![deny(missing_docs, missing_debug_implementations)]
#![doc(html_rnoot_url = "https://docs.rs/futures-io/0.2.0")]

macro_rules! if_std {
    ($($i:item)*) => ($(
        #[cfg(feature = "std")]
        $i
    )*)
}

if_std! {
    extern crate futures_core;
    extern crate iovec;
    extern crate std;

    use futures_core::{Poll, task};
    use std::boxed::Box;
    use std::io as StdIo;
    use std::ptr;
    use std::vec::Vec;

    // Re-export IoVec for convenience
    pub use iovec::IoVec;

    // Re-export io::Error so that users don't have to deal
    // with conflicts when `use`ing `futures::io` and `std::io`.
    pub use StdIo::Error as Error;
    pub use StdIo::ErrorKind as ErrorKind;
    pub use StdIo::Result as Result;

    /// A type used to conditionally initialize buffers passed to `AsyncRead`
    /// methods, modeled after `std`.
    #[derive(Debug)]
    pub struct Initializer(bool);

    impl Initializer {
        /// Returns a new `Initializer` which will zero out buffers.
        #[inline]
        pub fn zeroing() -> Initializer {
            Initializer(true)
        }

        /// Returns a new `Initializer` which will not zero out buffers.
        ///
        /// # Safety
        ///
        /// This method may only be called by `AsyncRead`ers which guarantee
        /// that they will not read from the buffers passed to `AsyncRead`
        /// methods, and that the return value of the method accurately reflects
        /// the number of bytes that have been written to the head of the buffer.
        #[inline]
        pub unsafe fn nop() -> Initializer {
            Initializer(false)
        }

        /// Indicates if a buffer should be initialized.
        #[inline]
        pub fn should_initialize(&self) -> bool {
            self.0
        }

        /// Initializes a buffer if necessary.
        #[inline]
        pub fn initialize(&self, buf: &mut [u8]) {
            if self.should_initialize() {
                unsafe { ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len()) }
            }
        }
    }

    /// Read bytes asynchronously.
    ///
    /// This trait is analogous to the `std::io::Read` trait, but integrates
    /// with the asynchronous task system. In particular, the `poll_read`
    /// method, unlike `Read::read`, will automatically queue the current task
    /// for wakeup and return if data is not yet available, rather than blocking
    /// the calling thread.
    pub trait AsyncRead {
        /// Determines if this `AsyncRead`er can work with buffers of
        /// uninitialized memory.
        ///
        /// The default implementation returns an initializer which will zero
        /// buffers.
        ///
        /// # Safety
        ///
        /// This method is `unsafe` because and `AsyncRead`er could otherwise
        /// return a non-zeroing `Initializer` from another `AsyncRead` type
        /// without an `unsafe` block.
        #[inline]
        unsafe fn initializer(&self) -> Initializer {
            Initializer::zeroing()
        }

        /// Attempt to read from the `AsyncRead` into `buf`.
        ///
        /// On success, returns `Ok(Async::Ready(num_bytes_read))`.
        ///
        /// If no data is available for reading, the method returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object becomes
        /// readable or is closed.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_read(&mut self, cx: &mut task::Context, buf: &mut [u8])
            -> Poll<Result<usize>>;

        /// Attempt to read from the `AsyncRead` into `vec` using vectored
        /// IO operations.
        ///
        /// This method is similar to `poll_read`, but allows data to be read
        /// into multiple buffers using a single operation.
        ///
        /// On success, returns `Ok(Async::Ready(num_bytes_read))`.
        ///
        /// If no data is available for reading, the method returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object becomes
        /// readable or is closed.
        /// By default, this method delegates to using `poll_read` on the first
        /// buffer in `vec`. Objects which support vectored IO should override
        /// this method.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_vectored_read(&mut self, cx: &mut task::Context, vec: &mut [&mut IoVec])
            -> Poll<Result<usize>>
        {
            if let Some(ref mut first_iovec) = vec.get_mut(0) {
                self.poll_read(cx, first_iovec)
            } else {
                // `vec` is empty.
                Poll::Ready(Ok(0))
            }
        }
    }

    /// Write bytes asynchronously.
    ///
    /// This trait is analogous to the `std::io::Write` trait, but integrates
    /// with the asynchronous task system. In particular, the `poll_write`
    /// method, unlike `Write::write`, will automatically queue the current task
    /// for wakeup and return if data is not yet available, rather than blocking
    /// the calling thread.
    pub trait AsyncWrite {
        /// Attempt to write bytes from `buf` into the object.
        ///
        /// On success, returns `Ok(Async::Ready(num_bytes_written))`.
        ///
        /// If the object is not ready for writing, the method returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object becomes
        /// readable or is closed.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_write(&mut self, cx: &mut task::Context, buf: &[u8])
            -> Poll<Result<usize>>;

        /// Attempt to write bytes from `vec` into the object using vectored
        /// IO operations.
        ///
        /// This method is similar to `poll_write`, but allows data from multiple buffers to be written
        /// using a single operation.
        ///
        /// On success, returns `Ok(Async::Ready(num_bytes_written))`.
        ///
        /// If the object is not ready for writing, the method returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object becomes
        /// readable or is closed.
        ///
        /// By default, this method delegates to using `poll_write` on the first
        /// buffer in `vec`. Objects which support vectored IO should override
        /// this method.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_vectored_write(&mut self, cx: &mut task::Context, vec: &[&IoVec])
            -> Poll<Result<usize>>
        {
            if let Some(ref first_iovec) = vec.get(0) {
                self.poll_write(cx, &*first_iovec)
            } else {
                // `vec` is empty.
                Poll::Ready(Ok(0))
            }
        }

        /// Attempt to flush the object, ensuring that any buffered data reach
        /// their destination.
        ///
        /// On success, returns `Ok(Async::Ready(()))`.
        ///
        /// If flushing cannot immediately complete, this method returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object can make
        /// progress towards flushing.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_flush(&mut self, cx: &mut task::Context) -> Poll<Result<()>>;

        /// Attempt to close the object.
        ///
        /// On success, returns `Ok(Async::Ready(()))`.
        ///
        /// If closing cannot immediately complete, this function returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object can make
        /// progress towards closing.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_close(&mut self, cx: &mut task::Context) -> Poll<Result<()>>;
    }

    macro_rules! deref_async_read {
        () => {
            unsafe fn initializer(&self) -> Initializer {
                (**self).initializer()
            }

            fn poll_read(&mut self, cx: &mut task::Context, buf: &mut [u8])
                -> Poll<Result<usize>>
            {
                (**self).poll_read(cx, buf)
            }

            fn poll_vectored_read(&mut self, cx: &mut task::Context, vec: &mut [&mut IoVec])
                -> Poll<Result<usize>>
            {
                (**self).poll_vectored_read(cx, vec)
            }
        }
    }

    impl<T: ?Sized + AsyncRead> AsyncRead for Box<T> {
        deref_async_read!();
    }

    impl<'a, T: ?Sized + AsyncRead> AsyncRead for &'a mut T {
        deref_async_read!();
    }

    /// `unsafe` because the `StdIo::Read` type must not access the buffer
    /// before reading data into it.
    macro_rules! unsafe_delegate_async_read_to_stdio {
        () => {
            unsafe fn initializer(&self) -> Initializer {
                Initializer::nop()
            }

            fn poll_read(&mut self, _: &mut task::Context, buf: &mut [u8])
                -> Poll<Result<usize>>
            {
                Poll::Ready(StdIo::Read::read(self, buf))
            }
        }
    }

    impl<'a> AsyncRead for &'a [u8] {
        unsafe_delegate_async_read_to_stdio!();
    }

    impl AsyncRead for StdIo::Repeat {
        unsafe_delegate_async_read_to_stdio!();
    }

    impl<T: AsRef<[u8]>> AsyncRead for StdIo::Cursor<T> {
        unsafe_delegate_async_read_to_stdio!();
    }

    macro_rules! deref_async_write {
        () => {
            fn poll_write(&mut self, cx: &mut task::Context, buf: &[u8])
                -> Poll<Result<usize>>
            {
                (**self).poll_write(cx, buf)
            }

            fn poll_vectored_write(&mut self, cx: &mut task::Context, vec: &[&IoVec])
                -> Poll<Result<usize>>
            {
                (**self).poll_vectored_write(cx, vec)
            }

            fn poll_flush(&mut self, cx: &mut task::Context) -> Poll<Result<()>> {
                (**self).poll_flush(cx)
            }

            fn poll_close(&mut self, cx: &mut task::Context) -> Poll<Result<()>> {
                (**self).poll_close(cx)
            }
        }
    }

    impl<T: ?Sized + AsyncWrite> AsyncWrite for Box<T> {
        deref_async_write!();
    }

    impl<'a, T: ?Sized + AsyncWrite> AsyncWrite for &'a mut T {
        deref_async_write!();
    }

    macro_rules! delegate_async_write_to_stdio {
        () => {
            fn poll_write(&mut self, _: &mut task::Context, buf: &[u8])
                -> Poll<Result<usize>>
            {
                Poll::Ready(StdIo::Write::write(self, buf))
            }

            fn poll_flush(&mut self, _: &mut task::Context) -> Poll<Result<()>> {
                Poll::Ready(StdIo::Write::flush(self))
            }

            fn poll_close(&mut self, cx: &mut task::Context) -> Poll<Result<()>> {
                self.poll_flush(cx)
            }
        }
    }

    impl<'a> AsyncWrite for StdIo::Cursor<&'a mut [u8]> {
        delegate_async_write_to_stdio!();
    }

    impl AsyncWrite for StdIo::Cursor<Vec<u8>> {
        delegate_async_write_to_stdio!();
    }

    impl AsyncWrite for StdIo::Cursor<Box<[u8]>> {
        delegate_async_write_to_stdio!();
    }

    impl AsyncWrite for StdIo::Sink {
        delegate_async_write_to_stdio!();
    }
}
<commit_msg>stdify futures-io<commit_after>//! Asynchronous I/O
//!
//! This crate contains the `AsyncRead` and `AsyncWrite` traits, the
//! asynchronous analogs to `std::io::{Read, Write}`. The primary difference is
//! that these traits integrate with the asynchronous task system.

#![no_std]
#![deny(missing_docs, missing_debug_implementations)]
#![doc(html_rnoot_url = "https://docs.rs/futures-io/0.2.0")]

#![feature(futures_api)]

macro_rules! if_std {
    ($($i:item)*) => ($(
        #[cfg(feature = "std")]
        $i
    )*)
}

if_std! {
    extern crate futures_core;
    extern crate iovec;
    extern crate std;

    use futures_core::{Poll, task};
    use std::boxed::Box;
    use std::io as StdIo;
    use std::ptr;
    use std::vec::Vec;

    // Re-export IoVec for convenience
    pub use iovec::IoVec;

    // Re-export io::Error so that users don't have to deal
    // with conflicts when `use`ing `futures::io` and `std::io`.
    pub use StdIo::Error as Error;
    pub use StdIo::ErrorKind as ErrorKind;
    pub use StdIo::Result as Result;

    /// A type used to conditionally initialize buffers passed to `AsyncRead`
    /// methods, modeled after `std`.
    #[derive(Debug)]
    pub struct Initializer(bool);

    impl Initializer {
        /// Returns a new `Initializer` which will zero out buffers.
        #[inline]
        pub fn zeroing() -> Initializer {
            Initializer(true)
        }

        /// Returns a new `Initializer` which will not zero out buffers.
        ///
        /// # Safety
        ///
        /// This method may only be called by `AsyncRead`ers which guarantee
        /// that they will not read from the buffers passed to `AsyncRead`
        /// methods, and that the return value of the method accurately reflects
        /// the number of bytes that have been written to the head of the buffer.
        #[inline]
        pub unsafe fn nop() -> Initializer {
            Initializer(false)
        }

        /// Indicates if a buffer should be initialized.
        #[inline]
        pub fn should_initialize(&self) -> bool {
            self.0
        }

        /// Initializes a buffer if necessary.
        #[inline]
        pub fn initialize(&self, buf: &mut [u8]) {
            if self.should_initialize() {
                unsafe { ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len()) }
            }
        }
    }

    /// Read bytes asynchronously.
    ///
    /// This trait is analogous to the `std::io::Read` trait, but integrates
    /// with the asynchronous task system. In particular, the `poll_read`
    /// method, unlike `Read::read`, will automatically queue the current task
    /// for wakeup and return if data is not yet available, rather than blocking
    /// the calling thread.
    pub trait AsyncRead {
        /// Determines if this `AsyncRead`er can work with buffers of
        /// uninitialized memory.
        ///
        /// The default implementation returns an initializer which will zero
        /// buffers.
        ///
        /// # Safety
        ///
        /// This method is `unsafe` because and `AsyncRead`er could otherwise
        /// return a non-zeroing `Initializer` from another `AsyncRead` type
        /// without an `unsafe` block.
        #[inline]
        unsafe fn initializer(&self) -> Initializer {
            Initializer::zeroing()
        }

        /// Attempt to read from the `AsyncRead` into `buf`.
        ///
        /// On success, returns `Ok(Async::Ready(num_bytes_read))`.
        ///
        /// If no data is available for reading, the method returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object becomes
        /// readable or is closed.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_read(&mut self, cx: &mut task::Context, buf: &mut [u8])
            -> Poll<Result<usize>>;

        /// Attempt to read from the `AsyncRead` into `vec` using vectored
        /// IO operations.
        ///
        /// This method is similar to `poll_read`, but allows data to be read
        /// into multiple buffers using a single operation.
        ///
        /// On success, returns `Ok(Async::Ready(num_bytes_read))`.
        ///
        /// If no data is available for reading, the method returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object becomes
        /// readable or is closed.
        /// By default, this method delegates to using `poll_read` on the first
        /// buffer in `vec`. Objects which support vectored IO should override
        /// this method.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_vectored_read(&mut self, cx: &mut task::Context, vec: &mut [&mut IoVec])
            -> Poll<Result<usize>>
        {
            if let Some(ref mut first_iovec) = vec.get_mut(0) {
                self.poll_read(cx, first_iovec)
            } else {
                // `vec` is empty.
                Poll::Ready(Ok(0))
            }
        }
    }

    /// Write bytes asynchronously.
    ///
    /// This trait is analogous to the `std::io::Write` trait, but integrates
    /// with the asynchronous task system. In particular, the `poll_write`
    /// method, unlike `Write::write`, will automatically queue the current task
    /// for wakeup and return if data is not yet available, rather than blocking
    /// the calling thread.
    pub trait AsyncWrite {
        /// Attempt to write bytes from `buf` into the object.
        ///
        /// On success, returns `Ok(Async::Ready(num_bytes_written))`.
        ///
        /// If the object is not ready for writing, the method returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object becomes
        /// readable or is closed.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_write(&mut self, cx: &mut task::Context, buf: &[u8])
            -> Poll<Result<usize>>;

        /// Attempt to write bytes from `vec` into the object using vectored
        /// IO operations.
        ///
        /// This method is similar to `poll_write`, but allows data from multiple buffers to be written
        /// using a single operation.
        ///
        /// On success, returns `Ok(Async::Ready(num_bytes_written))`.
        ///
        /// If the object is not ready for writing, the method returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object becomes
        /// readable or is closed.
        ///
        /// By default, this method delegates to using `poll_write` on the first
        /// buffer in `vec`. Objects which support vectored IO should override
        /// this method.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_vectored_write(&mut self, cx: &mut task::Context, vec: &[&IoVec])
            -> Poll<Result<usize>>
        {
            if let Some(ref first_iovec) = vec.get(0) {
                self.poll_write(cx, &*first_iovec)
            } else {
                // `vec` is empty.
                Poll::Ready(Ok(0))
            }
        }

        /// Attempt to flush the object, ensuring that any buffered data reach
        /// their destination.
        ///
        /// On success, returns `Ok(Async::Ready(()))`.
        ///
        /// If flushing cannot immediately complete, this method returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object can make
        /// progress towards flushing.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_flush(&mut self, cx: &mut task::Context) -> Poll<Result<()>>;

        /// Attempt to close the object.
        ///
        /// On success, returns `Ok(Async::Ready(()))`.
        ///
        /// If closing cannot immediately complete, this function returns
        /// `Ok(Async::Pending)` and arranges for the current task (via
        /// `cx.waker()`) to receive a notification when the object can make
        /// progress towards closing.
        ///
        /// # Implementation
        ///
        /// This function may not return errors of kind `WouldBlock` or
        /// `Interrupted`.  Implementations must convert `WouldBlock` into
        /// `Async::Pending` and either internally retry or convert
        /// `Interrupted` into another error kind.
        fn poll_close(&mut self, cx: &mut task::Context) -> Poll<Result<()>>;
    }

    macro_rules! deref_async_read {
        () => {
            unsafe fn initializer(&self) -> Initializer {
                (**self).initializer()
            }

            fn poll_read(&mut self, cx: &mut task::Context, buf: &mut [u8])
                -> Poll<Result<usize>>
            {
                (**self).poll_read(cx, buf)
            }

            fn poll_vectored_read(&mut self, cx: &mut task::Context, vec: &mut [&mut IoVec])
                -> Poll<Result<usize>>
            {
                (**self).poll_vectored_read(cx, vec)
            }
        }
    }

    impl<T: ?Sized + AsyncRead> AsyncRead for Box<T> {
        deref_async_read!();
    }

    impl<'a, T: ?Sized + AsyncRead> AsyncRead for &'a mut T {
        deref_async_read!();
    }

    /// `unsafe` because the `StdIo::Read` type must not access the buffer
    /// before reading data into it.
    macro_rules! unsafe_delegate_async_read_to_stdio {
        () => {
            unsafe fn initializer(&self) -> Initializer {
                Initializer::nop()
            }

            fn poll_read(&mut self, _: &mut task::Context, buf: &mut [u8])
                -> Poll<Result<usize>>
            {
                Poll::Ready(StdIo::Read::read(self, buf))
            }
        }
    }

    impl<'a> AsyncRead for &'a [u8] {
        unsafe_delegate_async_read_to_stdio!();
    }

    impl AsyncRead for StdIo::Repeat {
        unsafe_delegate_async_read_to_stdio!();
    }

    impl<T: AsRef<[u8]>> AsyncRead for StdIo::Cursor<T> {
        unsafe_delegate_async_read_to_stdio!();
    }

    macro_rules! deref_async_write {
        () => {
            fn poll_write(&mut self, cx: &mut task::Context, buf: &[u8])
                -> Poll<Result<usize>>
            {
                (**self).poll_write(cx, buf)
            }

            fn poll_vectored_write(&mut self, cx: &mut task::Context, vec: &[&IoVec])
                -> Poll<Result<usize>>
            {
                (**self).poll_vectored_write(cx, vec)
            }

            fn poll_flush(&mut self, cx: &mut task::Context) -> Poll<Result<()>> {
                (**self).poll_flush(cx)
            }

            fn poll_close(&mut self, cx: &mut task::Context) -> Poll<Result<()>> {
                (**self).poll_close(cx)
            }
        }
    }

    impl<T: ?Sized + AsyncWrite> AsyncWrite for Box<T> {
        deref_async_write!();
    }

    impl<'a, T: ?Sized + AsyncWrite> AsyncWrite for &'a mut T {
        deref_async_write!();
    }

    macro_rules! delegate_async_write_to_stdio {
        () => {
            fn poll_write(&mut self, _: &mut task::Context, buf: &[u8])
                -> Poll<Result<usize>>
            {
                Poll::Ready(StdIo::Write::write(self, buf))
            }

            fn poll_flush(&mut self, _: &mut task::Context) -> Poll<Result<()>> {
                Poll::Ready(StdIo::Write::flush(self))
            }

            fn poll_close(&mut self, cx: &mut task::Context) -> Poll<Result<()>> {
                self.poll_flush(cx)
            }
        }
    }

    impl<'a> AsyncWrite for StdIo::Cursor<&'a mut [u8]> {
        delegate_async_write_to_stdio!();
    }

    impl AsyncWrite for StdIo::Cursor<Vec<u8>> {
        delegate_async_write_to_stdio!();
    }

    impl AsyncWrite for StdIo::Cursor<Box<[u8]>> {
        delegate_async_write_to_stdio!();
    }

    impl AsyncWrite for StdIo::Sink {
        delegate_async_write_to_stdio!();
    }
}
<|endoftext|>