<commit_before>use std::path::Path;
use super::schedule::{Schedule, Program};

#[derive(Clone)]
pub enum Placement {
    Beginning,
    Middle(usize),
    End
}

#[derive(Clone)]
pub enum Filler {
    Once(Placement),
    Twice(Placement, Placement),
    Thrice(Placement, Placement, Placement),
    Periodic(usize),
    Bookend(usize),
    None
}

#[derive(Clone)]
pub struct BlockIterator {
    name: String,
    entries: Vec<Vec<String>>,
    fillstyle: Filler,
    filler: Vec<String>,
    repeat: Vec<usize>,
    autotag: bool,
    longest: usize,
    sched_num: usize
}

impl BlockIterator {
    pub fn new_with_filler(nom: &str, entries: &Vec<Vec<String>>, fillstyle: &Filler,
                           filler: &Vec<String>, repeat: &Vec<usize>, tag: bool) -> BlockIterator {
        BlockIterator {
            name: nom.to_string(),
            entries: entries.clone(),
            fillstyle: fillstyle.clone(),
            filler: filler.clone(),
            repeat: repeat.clone(),
            autotag: tag,
            longest: entries.iter().zip(repeat.iter()).fold(0, |len, (entry, &repetitions)| {
                let total_reps = if entry.len() % repetitions == 0 {
                    repetitions
                } else {
                    repetitions + 1
                };

                if entry.len() / total_reps  > len {
                    entry.len()
                } else {
                    len
                }}),

            sched_num: 0
        }
    }
}

impl Iterator for BlockIterator {
    type Item = Schedule;

    fn next(&mut self) -> Option<Schedule> {
        if self.sched_num == self.longest {
            None
        } else {
            let sched_name = format!("{}-{}{}", self.name, {
                if self.longest < 10 {
                    ""
                } else if self.longest < 100 {
                    if self.sched_num + 1 < 10 {
                    "0"
                    } else {
                        ""
                    }
                } else {
                    if self.sched_num + 1 < 10 {
                        "00"
                    } else if self.sched_num + 1 < 100 {
                        "0"
                    } else {
                        ""
                    }
                }}, self.sched_num + 1);

            let queue: Vec<String> = self.entries.iter().zip(self.repeat.iter()).map(|(&entry, &repeater)| {
                    entry.iter().skip(self.sched_num * repeater).take(repeater).map(|w| w.clone())
            }).collect();
            None
        }
    }
}
<commit_msg>working on block iterator<commit_after>use std::path::Path;
use super::schedule::{Schedule, Program};

#[derive(Clone)]
pub enum Placement {
    Beginning,
    Middle(usize),
    End
}

#[derive(Clone)]
pub enum Filler {
    Once(Placement),
    Twice(Placement, Placement),
    Thrice(Placement, Placement, Placement),
    Periodic(usize),
    Bookend(usize),
    None
}

#[derive(Clone)]
pub struct BlockIterator {
    name: String,
    entries: Vec<Vec<String>>,
    fillstyle: Filler,
    filler: Vec<String>,
    repeat: Vec<usize>,
    autotag: bool,
    longest: usize,
    sched_num: usize
}

impl BlockIterator {
    pub fn new_with_filler(nom: &str, entries: &Vec<Vec<String>>, fillstyle: &Filler,
                           filler: &Vec<String>, repeat: &Vec<usize>, tag: bool) -> BlockIterator {
        BlockIterator {
            name: nom.to_string(),
            entries: entries.clone(),
            fillstyle: fillstyle.clone(),
            filler: filler.clone(),
            repeat: repeat.clone(),
            autotag: tag,
            longest: entries.iter().zip(repeat.iter()).fold(0, |len, (entry, &repetitions)| {
                let total_reps = if entry.len() % repetitions == 0 {
                    repetitions
                } else {
                    repetitions + 1
                };

                if entry.len() / total_reps  > len {
                    entry.len()
                } else {
                    len
                }}),

            sched_num: 0
        }
    }
}

impl Iterator for BlockIterator {
    type Item = Schedule;

    fn next(&mut self) -> Option<Schedule> {
        if self.sched_num == self.longest {
            None
        } else {
            let sched_name = format!("{}-{}{}", self.name, {
                if self.longest < 10 {
                    ""
                } else if self.longest < 100 {
                    if self.sched_num + 1 < 10 {
                    "0"
                    } else {
                        ""
                    }
                } else {
                    if self.sched_num + 1 < 10 {
                        "00"
                    } else if self.sched_num + 1 < 100 {
                        "0"
                    } else {
                        ""
                    }
                }}, self.sched_num + 1);

            let queue: Vec<String> = self.entries.iter().zip(self.repeat.iter())
                .map(|(ref entry, &repeater)| {
                    entry.iter().skip(self.sched_num * repeater)
                        .take(repeater).map(|w| w.clone()).collect::<Vec<String>>()
                }).fold(Vec::new(), |mut sched, mut entry| {
                sched.append(&mut entry);
                sched
            });
/*            let proglist: Vec<String> = queue.into_iter().fold(Vec::new(), |mut sched, mut entry| {
                sched.append(&mut entry);
                sched
            });*/
            None
        }
    }
}
<|endoftext|>


<commit_before>use object_id::ObjectId;
use object_database::find_object_by_id;
use error::CorruptRepository;
use error::GitError;
use repository::Repository;
use commit::Commit;
use commit;
use eobject::ECommit;
use commit_sort_strategy::MostRecent;
use commit_filter::CommitFilter;

pub struct Branch {
    pub name: String,
    pub canonical_name: String,
    pub tip_id: ObjectId,
    pub tracked_branch: Option<Box<Branch>>,
    pub is_remote: bool,
    pub is_detached: bool,
}

impl Branch {
    pub fn is_tracking(&self) -> bool {
        self.tracked_branch.is_some()
    }
}

pub fn tip(repository: &Repository, branch: &Branch) -> Result<Commit, GitError> {
    match find_object_by_id(repository, &branch.tip_id) {
        Ok(box ECommit(c)) => Ok(c),
        Err(e) => Err(e),
        _ => Err(CorruptRepository("Could not find the commit the branch points to")),
    }
}
}<commit_msg>Implement a method in branch module for finding commits on that branch<commit_after>use object_id::ObjectId;
use object_database::find_object_by_id;
use error::CorruptRepository;
use error::GitError;
use repository::Repository;
use commit::Commit;
use commit;
use eobject::ECommit;
use commit_sort_strategy::MostRecent;
use commit_filter::CommitFilter;

pub struct Branch {
    pub name: String,
    pub canonical_name: String,
    pub tip_id: ObjectId,
    pub tracked_branch: Option<Box<Branch>>,
    pub is_remote: bool,
    pub is_detached: bool,
}

impl Branch {
    pub fn is_tracking(&self) -> bool {
        self.tracked_branch.is_some()
    }
}

pub fn tip(repository: &Repository, branch: &Branch) -> Result<Commit, GitError> {
    match find_object_by_id(repository, &branch.tip_id) {
        Ok(box ECommit(c)) => Ok(c),
        Err(e) => Err(e),
        _ => Err(CorruptRepository("Could not find the commit the branch points to")),
    }
}

pub fn commits(repository: &Repository, branch: &Branch) -> Vec<Commit> {
    let filter = CommitFilter {
        since: Some(vec![branch.tip_id.clone()]),
        until: None,
        limit: -1,
        offset: 0,
        sort: MostRecent,
    };

    commit::find(repository, filter)
}<|endoftext|>


<commit_before>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A stably addressed token buffer supporting efficient traversal based on a
//! cheaply copyable cursor.
//!
//! *This module is available if Syn is built with the `"parsing"` feature.*

// This module is heavily commented as it contains the only unsafe code in Syn,
// and caution should be used when editing it. The public-facing interface is
// 100% safe but the implementation is fragile internally.

#[cfg(all(
    not(all(target_arch = "wasm32", target_os = "unknown")),
    feature = "proc-macro"
))]
use proc_macro as pm;
use proc_macro2::{Delimiter, Ident, Literal, Span, TokenStream};
use proc_macro2::{Group, Punct, TokenTree};

use std::marker::PhantomData;
use std::ptr;

#[cfg(synom_verbose_trace)]
use std::fmt::{self, Debug};

/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
    // Mimicking types from proc-macro.
    Group(Span, Delimiter, TokenBuffer),
    Ident(Ident),
    Punct(Punct),
    Literal(Literal),
    // End entries contain a raw pointer to the entry from the containing
    // token tree, or null if this is the outermost level.
    End(*const Entry),
}

/// A buffer that can be efficiently traversed multiple times, unlike
/// `TokenStream` which requires a deep copy in order to traverse more than
/// once.
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
pub struct TokenBuffer {
    // NOTE: Do not derive clone on this - there are raw pointers inside which
    // will be messed up. Moving the `TokenBuffer` itself is safe as the actual
    // backing slices won't be moved.
    data: Box<[Entry]>,
}

impl TokenBuffer {
    // NOTE: DO NOT MUTATE THE `Vec` RETURNED FROM THIS FUNCTION ONCE IT
    // RETURNS, THE ADDRESS OF ITS BACKING MEMORY MUST REMAIN STABLE.
    fn inner_new(stream: TokenStream, up: *const Entry) -> TokenBuffer {
        // Build up the entries list, recording the locations of any Groups
        // in the list to be processed later.
        let mut entries = Vec::new();
        let mut seqs = Vec::new();
        for tt in stream {
            match tt {
                TokenTree::Ident(sym) => {
                    entries.push(Entry::Ident(sym));
                }
                TokenTree::Punct(op) => {
                    entries.push(Entry::Punct(op));
                }
                TokenTree::Literal(l) => {
                    entries.push(Entry::Literal(l));
                }
                TokenTree::Group(g) => {
                    // Record the index of the interesting entry, and store an
                    // `End(null)` there temporarially.
                    seqs.push((entries.len(), g.span(), g.delimiter(), g.stream().clone()));
                    entries.push(Entry::End(ptr::null()));
                }
            }
        }
        // Add an `End` entry to the end with a reference to the enclosing token
        // stream which was passed in.
        entries.push(Entry::End(up));

        // NOTE: This is done to ensure that we don't accidentally modify the
        // length of the backing buffer. The backing buffer must remain at a
        // constant address after this point, as we are going to store a raw
        // pointer into it.
        let mut entries = entries.into_boxed_slice();
        for (idx, span, delim, seq_stream) in seqs {
            // We know that this index refers to one of the temporary
            // `End(null)` entries, and we know that the last entry is
            // `End(up)`, so the next index is also valid.
            let seq_up = &entries[idx + 1] as *const Entry;

            // The end entry stored at the end of this Entry::Group should
            // point to the Entry which follows the Group in the list.
            let inner = Self::inner_new(seq_stream, seq_up);
            entries[idx] = Entry::Group(span, delim, inner);
        }

        TokenBuffer { data: entries }
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `TokenStream`.
    ///
    /// *This method is available if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", target_os = "unknown")),
        feature = "proc-macro"
    ))]
    pub fn new(stream: pm::TokenStream) -> TokenBuffer {
        Self::new2(stream.into())
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `TokenStream`.
    pub fn new2(stream: TokenStream) -> TokenBuffer {
        Self::inner_new(stream, ptr::null())
    }

    /// Creates a cursor referencing the first token in the buffer and able to
    /// traverse until the end of the buffer.
    pub fn begin(&self) -> Cursor {
        unsafe { Cursor::create(&self.data[0], &self.data[self.data.len() - 1]) }
    }
}

/// A cheaply copyable cursor into a `TokenBuffer`.
///
/// This cursor holds a shared reference into the immutable data which is used
/// internally to represent a `TokenStream`, and can be efficiently manipulated
/// and copied around.
///
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
/// object and get a cursor to its first token with `begin()`.
///
/// Two cursors are equal if they have the same location in the same input
/// stream, and have the same scope.
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Cursor<'a> {
    /// The current entry which the `Cursor` is pointing at.
    ptr: *const Entry,
    /// This is the only `Entry::End(..)` object which this cursor is allowed to
    /// point at. All other `End` objects are skipped over in `Cursor::create`.
    scope: *const Entry,
    /// This uses the &'a reference which guarantees that these pointers are
    /// still valid.
    marker: PhantomData<&'a Entry>,
}

impl<'a> Cursor<'a> {
    /// Creates a cursor referencing a static empty TokenStream.
    pub fn empty() -> Self {
        // It's safe in this situation for us to put an `Entry` object in global
        // storage, despite it not actually being safe to send across threads
        // (`Ident` is a reference into a thread-local table). This is because
        // this entry never includes a `Ident` object.
        //
        // This wrapper struct allows us to break the rules and put a `Sync`
        // object in global storage.
        struct UnsafeSyncEntry(Entry);
        unsafe impl Sync for UnsafeSyncEntry {}
        static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0 as *const Entry));

        Cursor {
            ptr: &EMPTY_ENTRY.0,
            scope: &EMPTY_ENTRY.0,
            marker: PhantomData,
        }
    }

    /// This create method intelligently exits non-explicitly-entered
    /// `None`-delimited scopes when the cursor reaches the end of them,
    /// allowing for them to be treated transparently.
    unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
        // NOTE: If we're looking at a `End(..)`, we want to advance the cursor
        // past it, unless `ptr == scope`, which means that we're at the edge of
        // our cursor's scope. We should only have `ptr != scope` at the exit
        // from None-delimited groups entered with `ignore_none`.
        while let Entry::End(exit) = *ptr {
            if ptr == scope {
                break;
            }
            ptr = exit;
        }

        Cursor {
            ptr: ptr,
            scope: scope,
            marker: PhantomData,
        }
    }

    /// Get the current entry.
    fn entry(self) -> &'a Entry {
        unsafe { &*self.ptr }
    }

    /// Bump the cursor to point at the next token after the current one. This
    /// is undefined behavior if the cursor is currently looking at an
    /// `Entry::End`.
    unsafe fn bump(self) -> Cursor<'a> {
        Cursor::create(self.ptr.offset(1), self.scope)
    }

    /// If the cursor is looking at a `None`-delimited group, move it to look at
    /// the first token inside instead. If the group is empty, this will move
    /// the cursor past the `None`-delimited group.
    ///
    /// WARNING: This mutates its argument.
    fn ignore_none(&mut self) {
        if let Entry::Group(_, Delimiter::None, ref buf) = *self.entry() {
            // NOTE: We call `Cursor::create` here to make sure that situations
            // where we should immediately exit the span after entering it are
            // handled correctly.
            unsafe {
                *self = Cursor::create(&buf.data[0], self.scope);
            }
        }
    }

    /// Checks whether the cursor is currently pointing at the end of its valid
    /// scope.
    #[inline]
    pub fn eof(self) -> bool {
        // We're at eof if we're at the end of our scope.
        self.ptr == self.scope
    }

    /// If the cursor is pointing at a `Group` with the given delimiter, returns
    /// a cursor into that group and one pointing to the next `TokenTree`.
    pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
        // If we're not trying to enter a none-delimited group, we want to
        // ignore them. We have to make sure to _not_ ignore them when we want
        // to enter them, of course. For obvious reasons.
        if delim != Delimiter::None {
            self.ignore_none();
        }

        if let Entry::Group(span, group_delim, ref buf) = *self.entry() {
            if group_delim == delim {
                return Some((buf.begin(), span, unsafe { self.bump() }));
            }
        }

        None
    }

    /// If the cursor is pointing at a `Ident`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
        self.ignore_none();
        match *self.entry() {
            Entry::Ident(ref ident) => Some((ident.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at an `Punct`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
        self.ignore_none();
        match *self.entry() {
            Entry::Punct(ref op) => Some((op.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Literal`, return it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
        self.ignore_none();
        match *self.entry() {
            Entry::Literal(ref lit) => Some((lit.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// Copies all remaining tokens visible from this cursor into a
    /// `TokenStream`.
    pub fn token_stream(self) -> TokenStream {
        let mut tts = Vec::new();
        let mut cursor = self;
        while let Some((tt, rest)) = cursor.token_tree() {
            tts.push(tt);
            cursor = rest;
        }
        tts.into_iter().collect()
    }

    /// If the cursor is pointing at a `TokenTree`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    ///
    /// Returns `None` if the cursor has reached the end of its stream.
    ///
    /// This method does not treat `None`-delimited groups as transparent, and
    /// will return a `Group(None, ..)` if the cursor is looking at one.
    pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
        let tree = match *self.entry() {
            Entry::Group(span, delim, ref buf) => {
                let stream = buf.begin().token_stream();
                let mut g = Group::new(delim, stream);
                g.set_span(span);
                TokenTree::from(g)
            }
            Entry::Literal(ref lit) => lit.clone().into(),
            Entry::Ident(ref ident) => ident.clone().into(),
            Entry::Punct(ref op) => op.clone().into(),
            Entry::End(..) => {
                return None;
            }
        };

        Some((tree, unsafe { self.bump() }))
    }

    /// Returns the `Span` of the current token, or `Span::call_site()` if this
    /// cursor points to eof.
    pub fn span(self) -> Span {
        match *self.entry() {
            Entry::Group(span, ..) => span,
            Entry::Literal(ref l) => l.span(),
            Entry::Ident(ref t) => t.span(),
            Entry::Punct(ref o) => o.span(),
            Entry::End(..) => Span::call_site(),
        }
    }
}

// We do a custom implementation for `Debug` as the default implementation is
// pretty useless.
#[cfg(synom_verbose_trace)]
impl<'a> Debug for Cursor<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Print what the cursor is currently looking at.
        // This will look like Cursor("some remaining tokens here")
        f.debug_tuple("Cursor")
            .field(&self.token_stream().to_string())
            .finish()
    }
}
<commit_msg>Remove what's left of synom_verbose_trace<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A stably addressed token buffer supporting efficient traversal based on a
//! cheaply copyable cursor.
//!
//! *This module is available if Syn is built with the `"parsing"` feature.*

// This module is heavily commented as it contains the only unsafe code in Syn,
// and caution should be used when editing it. The public-facing interface is
// 100% safe but the implementation is fragile internally.

#[cfg(all(
    not(all(target_arch = "wasm32", target_os = "unknown")),
    feature = "proc-macro"
))]
use proc_macro as pm;
use proc_macro2::{Delimiter, Ident, Literal, Span, TokenStream};
use proc_macro2::{Group, Punct, TokenTree};

use std::marker::PhantomData;
use std::ptr;

/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
    // Mimicking types from proc-macro.
    Group(Span, Delimiter, TokenBuffer),
    Ident(Ident),
    Punct(Punct),
    Literal(Literal),
    // End entries contain a raw pointer to the entry from the containing
    // token tree, or null if this is the outermost level.
    End(*const Entry),
}

/// A buffer that can be efficiently traversed multiple times, unlike
/// `TokenStream` which requires a deep copy in order to traverse more than
/// once.
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
pub struct TokenBuffer {
    // NOTE: Do not derive clone on this - there are raw pointers inside which
    // will be messed up. Moving the `TokenBuffer` itself is safe as the actual
    // backing slices won't be moved.
    data: Box<[Entry]>,
}

impl TokenBuffer {
    // NOTE: DO NOT MUTATE THE `Vec` RETURNED FROM THIS FUNCTION ONCE IT
    // RETURNS, THE ADDRESS OF ITS BACKING MEMORY MUST REMAIN STABLE.
    fn inner_new(stream: TokenStream, up: *const Entry) -> TokenBuffer {
        // Build up the entries list, recording the locations of any Groups
        // in the list to be processed later.
        let mut entries = Vec::new();
        let mut seqs = Vec::new();
        for tt in stream {
            match tt {
                TokenTree::Ident(sym) => {
                    entries.push(Entry::Ident(sym));
                }
                TokenTree::Punct(op) => {
                    entries.push(Entry::Punct(op));
                }
                TokenTree::Literal(l) => {
                    entries.push(Entry::Literal(l));
                }
                TokenTree::Group(g) => {
                    // Record the index of the interesting entry, and store an
                    // `End(null)` there temporarially.
                    seqs.push((entries.len(), g.span(), g.delimiter(), g.stream().clone()));
                    entries.push(Entry::End(ptr::null()));
                }
            }
        }
        // Add an `End` entry to the end with a reference to the enclosing token
        // stream which was passed in.
        entries.push(Entry::End(up));

        // NOTE: This is done to ensure that we don't accidentally modify the
        // length of the backing buffer. The backing buffer must remain at a
        // constant address after this point, as we are going to store a raw
        // pointer into it.
        let mut entries = entries.into_boxed_slice();
        for (idx, span, delim, seq_stream) in seqs {
            // We know that this index refers to one of the temporary
            // `End(null)` entries, and we know that the last entry is
            // `End(up)`, so the next index is also valid.
            let seq_up = &entries[idx + 1] as *const Entry;

            // The end entry stored at the end of this Entry::Group should
            // point to the Entry which follows the Group in the list.
            let inner = Self::inner_new(seq_stream, seq_up);
            entries[idx] = Entry::Group(span, delim, inner);
        }

        TokenBuffer { data: entries }
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `TokenStream`.
    ///
    /// *This method is available if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", target_os = "unknown")),
        feature = "proc-macro"
    ))]
    pub fn new(stream: pm::TokenStream) -> TokenBuffer {
        Self::new2(stream.into())
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `TokenStream`.
    pub fn new2(stream: TokenStream) -> TokenBuffer {
        Self::inner_new(stream, ptr::null())
    }

    /// Creates a cursor referencing the first token in the buffer and able to
    /// traverse until the end of the buffer.
    pub fn begin(&self) -> Cursor {
        unsafe { Cursor::create(&self.data[0], &self.data[self.data.len() - 1]) }
    }
}

/// A cheaply copyable cursor into a `TokenBuffer`.
///
/// This cursor holds a shared reference into the immutable data which is used
/// internally to represent a `TokenStream`, and can be efficiently manipulated
/// and copied around.
///
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
/// object and get a cursor to its first token with `begin()`.
///
/// Two cursors are equal if they have the same location in the same input
/// stream, and have the same scope.
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Cursor<'a> {
    /// The current entry which the `Cursor` is pointing at.
    ptr: *const Entry,
    /// This is the only `Entry::End(..)` object which this cursor is allowed to
    /// point at. All other `End` objects are skipped over in `Cursor::create`.
    scope: *const Entry,
    /// This uses the &'a reference which guarantees that these pointers are
    /// still valid.
    marker: PhantomData<&'a Entry>,
}

impl<'a> Cursor<'a> {
    /// Creates a cursor referencing a static empty TokenStream.
    pub fn empty() -> Self {
        // It's safe in this situation for us to put an `Entry` object in global
        // storage, despite it not actually being safe to send across threads
        // (`Ident` is a reference into a thread-local table). This is because
        // this entry never includes a `Ident` object.
        //
        // This wrapper struct allows us to break the rules and put a `Sync`
        // object in global storage.
        struct UnsafeSyncEntry(Entry);
        unsafe impl Sync for UnsafeSyncEntry {}
        static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0 as *const Entry));

        Cursor {
            ptr: &EMPTY_ENTRY.0,
            scope: &EMPTY_ENTRY.0,
            marker: PhantomData,
        }
    }

    /// This create method intelligently exits non-explicitly-entered
    /// `None`-delimited scopes when the cursor reaches the end of them,
    /// allowing for them to be treated transparently.
    unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
        // NOTE: If we're looking at a `End(..)`, we want to advance the cursor
        // past it, unless `ptr == scope`, which means that we're at the edge of
        // our cursor's scope. We should only have `ptr != scope` at the exit
        // from None-delimited groups entered with `ignore_none`.
        while let Entry::End(exit) = *ptr {
            if ptr == scope {
                break;
            }
            ptr = exit;
        }

        Cursor {
            ptr: ptr,
            scope: scope,
            marker: PhantomData,
        }
    }

    /// Get the current entry.
    fn entry(self) -> &'a Entry {
        unsafe { &*self.ptr }
    }

    /// Bump the cursor to point at the next token after the current one. This
    /// is undefined behavior if the cursor is currently looking at an
    /// `Entry::End`.
    unsafe fn bump(self) -> Cursor<'a> {
        Cursor::create(self.ptr.offset(1), self.scope)
    }

    /// If the cursor is looking at a `None`-delimited group, move it to look at
    /// the first token inside instead. If the group is empty, this will move
    /// the cursor past the `None`-delimited group.
    ///
    /// WARNING: This mutates its argument.
    fn ignore_none(&mut self) {
        if let Entry::Group(_, Delimiter::None, ref buf) = *self.entry() {
            // NOTE: We call `Cursor::create` here to make sure that situations
            // where we should immediately exit the span after entering it are
            // handled correctly.
            unsafe {
                *self = Cursor::create(&buf.data[0], self.scope);
            }
        }
    }

    /// Checks whether the cursor is currently pointing at the end of its valid
    /// scope.
    #[inline]
    pub fn eof(self) -> bool {
        // We're at eof if we're at the end of our scope.
        self.ptr == self.scope
    }

    /// If the cursor is pointing at a `Group` with the given delimiter, returns
    /// a cursor into that group and one pointing to the next `TokenTree`.
    pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
        // If we're not trying to enter a none-delimited group, we want to
        // ignore them. We have to make sure to _not_ ignore them when we want
        // to enter them, of course. For obvious reasons.
        if delim != Delimiter::None {
            self.ignore_none();
        }

        if let Entry::Group(span, group_delim, ref buf) = *self.entry() {
            if group_delim == delim {
                return Some((buf.begin(), span, unsafe { self.bump() }));
            }
        }

        None
    }

    /// If the cursor is pointing at a `Ident`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
        self.ignore_none();
        match *self.entry() {
            Entry::Ident(ref ident) => Some((ident.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at an `Punct`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
        self.ignore_none();
        match *self.entry() {
            Entry::Punct(ref op) => Some((op.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Literal`, return it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
        self.ignore_none();
        match *self.entry() {
            Entry::Literal(ref lit) => Some((lit.clone(), unsafe { self.bump() })),
            _ => None,
        }
    }

    /// Copies all remaining tokens visible from this cursor into a
    /// `TokenStream`.
    pub fn token_stream(self) -> TokenStream {
        let mut tts = Vec::new();
        let mut cursor = self;
        while let Some((tt, rest)) = cursor.token_tree() {
            tts.push(tt);
            cursor = rest;
        }
        tts.into_iter().collect()
    }

    /// If the cursor is pointing at a `TokenTree`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    ///
    /// Returns `None` if the cursor has reached the end of its stream.
    ///
    /// This method does not treat `None`-delimited groups as transparent, and
    /// will return a `Group(None, ..)` if the cursor is looking at one.
    pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
        let tree = match *self.entry() {
            Entry::Group(span, delim, ref buf) => {
                let stream = buf.begin().token_stream();
                let mut g = Group::new(delim, stream);
                g.set_span(span);
                TokenTree::from(g)
            }
            Entry::Literal(ref lit) => lit.clone().into(),
            Entry::Ident(ref ident) => ident.clone().into(),
            Entry::Punct(ref op) => op.clone().into(),
            Entry::End(..) => {
                return None;
            }
        };

        Some((tree, unsafe { self.bump() }))
    }

    /// Returns the `Span` of the current token, or `Span::call_site()` if this
    /// cursor points to eof.
    pub fn span(self) -> Span {
        match *self.entry() {
            Entry::Group(span, ..) => span,
            Entry::Literal(ref l) => l.span(),
            Entry::Ident(ref t) => t.span(),
            Entry::Punct(ref o) => o.span(),
            Entry::End(..) => Span::call_site(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use fleetspeak_proto::common::{Message, Address};
use fleetspeak_proto::channel::{StartupData};
use lazy_static::lazy_static;
use prost;
use prost_types;
use std::io::{Read, Write, Result};
use std::marker::{Send, Sync};
use std::sync::Mutex;

pub struct Connection<R, W> {
    pub input: R,
    pub output: W,
}

impl<R: Read, W: Write> Connection<R, W> {

    pub fn new(input: R, output: W) -> Result<Self> {
        let mut conn = Connection {
            input: input,
            output: output,
        };
        conn.handshake()?;

        Ok(conn)
    }

    pub fn heartbeat(&mut self) -> Result<()> {
        let msg = Message {
            message_type: "Heartbeat".to_string(),
            destination: Some(Address {
                service_name: "system".to_string(),
                ..Default::default()
            }),
            ..Default::default()
        };

        self.emit(msg)
    }

    pub fn startup(&mut self, version: &str) -> Result<()> {
        let data = StartupData {
            pid: std::process::id() as i64,
            version: version.to_string(),
        };

        let mut buf = Vec::new();
        prost::Message::encode(&data, &mut buf).map_err(invalid_data_error)?;

        let msg = Message {
            message_type: "StartupData".to_string(),
            destination: Some(Address {
                service_name: "system".to_string(),
                ..Default::default()
            }),
            data: Some(prost_types::Any {
                value: buf,
                type_url: "type.googleapis.com/fleetspeak.channel.StartupData".to_string(),
            }),
            ..Default::default()
        };

        self.emit(msg)
    }

    pub fn send<M>(&mut self, service: &str, kind: &str, data: M) -> Result<()>
    where
        M: prost::Message,
    {
        let mut buf = Vec::new();
        prost::Message::encode(&data, &mut buf).map_err(invalid_data_error)?;

        let msg = Message {
            message_type: kind.to_string(),
            destination: Some(Address {
                service_name: service.to_string(),
                ..Default::default()
            }),
            data: Some(prost_types::Any {
                value: buf.to_vec(),
                ..Default::default()
            }),
            ..Default::default()
        };

        self.emit(msg)
    }

    pub fn receive<M>(&mut self) -> Result<M>
    where
        M: prost::Message + Default,
    {
        let msg = self.collect()?;

        // It is not clear what is the best approach here. If there is no data,
        // should we error-out or return a default value? For the time being we
        // stick to the default approach, but if this proves to be not working
        // well in practice, it might be reconsidered.
        let data = match msg.data {
            Some(data) => data,
            None => return Ok(Default::default()),
        };

        prost::Message::decode(&data.value[..]).map_err(invalid_data_error)
    }

    fn emit(&mut self, msg: Message) -> Result<()> {
        let mut buf = Vec::new();
        prost::Message::encode(&msg, &mut buf).map_err(invalid_data_error)?;

        self.output.write_u32::<LittleEndian>(buf.len() as u32)?;
        self.output.write(&buf)?;
        self.write_magic()?;
        self.output.flush()?;

        Ok(())
    }

    fn collect(&mut self) -> Result<Message> {
        let len = self.input.read_u32::<LittleEndian>()? as usize;
        let mut buf = vec!(0; len);
        self.input.read_exact(&mut buf[..])?;
        self.read_magic()?;

        prost::Message::decode(&buf[..]).map_err(invalid_data_error)
    }

    fn handshake(&mut self) -> Result<()> {
        self.write_magic()?;
        self.output.flush()?;
        self.read_magic()?;

        Ok(())
    }

    fn write_magic(&mut self) -> Result<()> {
        self.output.write_u32::<LittleEndian>(MAGIC)?;

        Ok(())
    }

    fn read_magic(&mut self) -> Result<()> {
        let magic = self.input.read_u32::<LittleEndian>()?;
        if magic != MAGIC {
            let err = invalid_data_error(format!("invalid magic `{}`", magic));
            return Err(err);
        }

        Ok(())
    }
}

fn invalid_data_error<E>(err: E) -> std::io::Error
where
    E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
    return std::io::Error::new(std::io::ErrorKind::InvalidData, err);
}

const MAGIC: u32 = 0xf1ee1001;

fn open(var: &str) -> std::fs::File {
    let fd = match std::env::var(var) {
        Ok(fd) => fd,
        Err(err) => panic!("invalid variable `{}`: {}", var, err),
    };

    let fd = match fd.parse() {
        Ok(fd) => fd,
        Err(err) => panic!("failed to parse a file descriptor: {}", err),
    };

    // TODO: Add support for Windows.
    unsafe {
        std::os::unix::io::FromRawFd::from_raw_fd(fd)
    }
}

lazy_static! {
    static ref CONNECTION: Mutex<Connection<std::fs::File, std::fs::File>> = {
        let input = open("FLEETSPEAK_COMMS_CHANNEL_INFD");
        let output = open("FLEETSPEAK_COMMS_CHANNEL_OUTFD");

        let conn = Connection::new(input, output).expect("handshake failure");
        Mutex::new(conn)
    };
}

pub fn heartbeat() -> Result<()> {
    connected(|conn| conn.heartbeat())
}

pub fn startup(version: &str) -> Result<()> {
    connected(|conn| conn.startup(version))
}

pub fn send<M>(service: &str, kind: &str, data: M) -> Result<()>
where
    M: prost::Message,
{
    connected(|conn| conn.send(service, kind, data))
}

pub fn receive<M>() -> Result<M>
where
    M: prost::Message + Default,
{
    connected(|conn| conn.receive())
}

fn connected<F, T>(f: F) -> Result<T>
where
    F: FnOnce(&mut Connection<std::fs::File, std::fs::File>) -> Result<T>
{
    let mut conn = CONNECTION.lock().expect("poisoned connection mutex");
    f(&mut conn)
}

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

    #[test]
    fn handshake_good_magic() {
        let mut buf_in = [0; 1024];
        let mut buf_out = [0; 1024];

        let mut cur = Cursor::new(&mut buf_in[..]);
        assert!(cur.write_u32::<LittleEndian>(MAGIC).is_ok());

        let cur_in = Cursor::new(&mut buf_in[..]);
        let cur_out = Cursor::new(&mut buf_out[..]);
        assert!(Connection::new(cur_in, cur_out).is_ok());

        let mut cur = Cursor::new(&mut buf_out[..]);
        assert_eq!(cur.read_u32::<LittleEndian>().unwrap(), MAGIC);
    }

    #[test]
    fn handshake_bad_magic() {
        let mut buf_in = [0; 1024];
        let mut buf_out = [0; 1024];

        let mut cur = Cursor::new(&mut buf_in[..]);
        assert!(cur.write_u32::<LittleEndian>(0xf1ee1337).is_ok());

        let cur_in = Cursor::new(&mut buf_in[..]);
        let cur_out = Cursor::new(&mut buf_out[..]);
        assert!(Connection::new(cur_in, cur_out).is_err());
    }
}
<commit_msg>Use `String::from` for converting `&str` literals.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use fleetspeak_proto::common::{Message, Address};
use fleetspeak_proto::channel::{StartupData};
use lazy_static::lazy_static;
use prost;
use prost_types;
use std::io::{Read, Write, Result};
use std::marker::{Send, Sync};
use std::sync::Mutex;

pub struct Connection<R, W> {
    pub input: R,
    pub output: W,
}

impl<R: Read, W: Write> Connection<R, W> {

    pub fn new(input: R, output: W) -> Result<Self> {
        let mut conn = Connection {
            input: input,
            output: output,
        };
        conn.handshake()?;

        Ok(conn)
    }

    pub fn heartbeat(&mut self) -> Result<()> {
        let msg = Message {
            message_type: String::from("Heartbeat"),
            destination: Some(Address {
                service_name: String::from("system"),
                ..Default::default()
            }),
            ..Default::default()
        };

        self.emit(msg)
    }

    pub fn startup(&mut self, version: &str) -> Result<()> {
        let data = StartupData {
            pid: std::process::id() as i64,
            version: String::from(version),
        };

        let mut buf = Vec::new();
        prost::Message::encode(&data, &mut buf).map_err(invalid_data_error)?;

        let msg = Message {
            message_type: String::from("StartupData"),
            destination: Some(Address {
                service_name: String::from("system"),
                ..Default::default()
            }),
            data: Some(prost_types::Any {
                value: buf,
                type_url: String::from("type.googleapis.com/fleetspeak.channel.StartupData"),
            }),
            ..Default::default()
        };

        self.emit(msg)
    }

    pub fn send<M>(&mut self, service: &str, kind: &str, data: M) -> Result<()>
    where
        M: prost::Message,
    {
        let mut buf = Vec::new();
        prost::Message::encode(&data, &mut buf).map_err(invalid_data_error)?;

        let msg = Message {
            message_type: String::from(kind),
            destination: Some(Address {
                service_name: String::from(service),
                ..Default::default()
            }),
            data: Some(prost_types::Any {
                value: buf.to_vec(),
                ..Default::default()
            }),
            ..Default::default()
        };

        self.emit(msg)
    }

    pub fn receive<M>(&mut self) -> Result<M>
    where
        M: prost::Message + Default,
    {
        let msg = self.collect()?;

        // It is not clear what is the best approach here. If there is no data,
        // should we error-out or return a default value? For the time being we
        // stick to the default approach, but if this proves to be not working
        // well in practice, it might be reconsidered.
        let data = match msg.data {
            Some(data) => data,
            None => return Ok(Default::default()),
        };

        prost::Message::decode(&data.value[..]).map_err(invalid_data_error)
    }

    fn emit(&mut self, msg: Message) -> Result<()> {
        let mut buf = Vec::new();
        prost::Message::encode(&msg, &mut buf).map_err(invalid_data_error)?;

        self.output.write_u32::<LittleEndian>(buf.len() as u32)?;
        self.output.write(&buf)?;
        self.write_magic()?;
        self.output.flush()?;

        Ok(())
    }

    fn collect(&mut self) -> Result<Message> {
        let len = self.input.read_u32::<LittleEndian>()? as usize;
        let mut buf = vec!(0; len);
        self.input.read_exact(&mut buf[..])?;
        self.read_magic()?;

        prost::Message::decode(&buf[..]).map_err(invalid_data_error)
    }

    fn handshake(&mut self) -> Result<()> {
        self.write_magic()?;
        self.output.flush()?;
        self.read_magic()?;

        Ok(())
    }

    fn write_magic(&mut self) -> Result<()> {
        self.output.write_u32::<LittleEndian>(MAGIC)?;

        Ok(())
    }

    fn read_magic(&mut self) -> Result<()> {
        let magic = self.input.read_u32::<LittleEndian>()?;
        if magic != MAGIC {
            let err = invalid_data_error(format!("invalid magic `{}`", magic));
            return Err(err);
        }

        Ok(())
    }
}

fn invalid_data_error<E>(err: E) -> std::io::Error
where
    E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
    return std::io::Error::new(std::io::ErrorKind::InvalidData, err);
}

const MAGIC: u32 = 0xf1ee1001;

fn open(var: &str) -> std::fs::File {
    let fd = match std::env::var(var) {
        Ok(fd) => fd,
        Err(err) => panic!("invalid variable `{}`: {}", var, err),
    };

    let fd = match fd.parse() {
        Ok(fd) => fd,
        Err(err) => panic!("failed to parse a file descriptor: {}", err),
    };

    // TODO: Add support for Windows.
    unsafe {
        std::os::unix::io::FromRawFd::from_raw_fd(fd)
    }
}

lazy_static! {
    static ref CONNECTION: Mutex<Connection<std::fs::File, std::fs::File>> = {
        let input = open("FLEETSPEAK_COMMS_CHANNEL_INFD");
        let output = open("FLEETSPEAK_COMMS_CHANNEL_OUTFD");

        let conn = Connection::new(input, output).expect("handshake failure");
        Mutex::new(conn)
    };
}

pub fn heartbeat() -> Result<()> {
    connected(|conn| conn.heartbeat())
}

pub fn startup(version: &str) -> Result<()> {
    connected(|conn| conn.startup(version))
}

pub fn send<M>(service: &str, kind: &str, data: M) -> Result<()>
where
    M: prost::Message,
{
    connected(|conn| conn.send(service, kind, data))
}

pub fn receive<M>() -> Result<M>
where
    M: prost::Message + Default,
{
    connected(|conn| conn.receive())
}

fn connected<F, T>(f: F) -> Result<T>
where
    F: FnOnce(&mut Connection<std::fs::File, std::fs::File>) -> Result<T>
{
    let mut conn = CONNECTION.lock().expect("poisoned connection mutex");
    f(&mut conn)
}

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

    #[test]
    fn handshake_good_magic() {
        let mut buf_in = [0; 1024];
        let mut buf_out = [0; 1024];

        let mut cur = Cursor::new(&mut buf_in[..]);
        assert!(cur.write_u32::<LittleEndian>(MAGIC).is_ok());

        let cur_in = Cursor::new(&mut buf_in[..]);
        let cur_out = Cursor::new(&mut buf_out[..]);
        assert!(Connection::new(cur_in, cur_out).is_ok());

        let mut cur = Cursor::new(&mut buf_out[..]);
        assert_eq!(cur.read_u32::<LittleEndian>().unwrap(), MAGIC);
    }

    #[test]
    fn handshake_bad_magic() {
        let mut buf_in = [0; 1024];
        let mut buf_out = [0; 1024];

        let mut cur = Cursor::new(&mut buf_in[..]);
        assert!(cur.write_u32::<LittleEndian>(0xf1ee1337).is_ok());

        let cur_in = Cursor::new(&mut buf_in[..]);
        let cur_out = Cursor::new(&mut buf_out[..]);
        assert!(Connection::new(cur_in, cur_out).is_err());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Asynchronous input and output.
//!
//! # Example
//!
//! ```
//! use gj::{EventLoop, Promise};
//! use gj::io::{AsyncRead, AsyncWrite, Error, Slice, unix};
//!
//! fn echo(stream: unix::Stream, buf: Vec<u8>) -> Promise<(), ::std::io::Error> {
//!     stream.try_read(buf, 1).lift().then(move |(stream, buf, n)| {
//!         if n == 0 { // EOF
//!             Promise::ok(())
//!         } else {
//!             stream.write(Slice::new(buf, n)).lift().then(move |(stream, slice)| {
//!                 echo(stream, slice.buf)
//!             })
//!         }
//!     })
//! }
//!
//! EventLoop::top_level(|wait_scope| {
//!     let (stream1, stream2) = try!(unix::Stream::new_pair());
//!     let promise1 = echo(stream1, vec![0; 5]);
//!     let promise2 = stream2.write(b"hello world").lift().then(|(stream, _)| {
//!         stream.read(vec![0; 11], 11).map(|(_, buf, _)| {
//!             assert_eq!(buf, b"hello world");
//!             Ok(())
//!         }).lift()
//!     });
//!     Promise::all(vec![promise1, promise2].into_iter()).wait(wait_scope).unwrap();
//!     Ok(())
//! }).unwrap();
//! ```

use std::result::Result;
use handle_table::{HandleTable, Handle};
use {EventPort, Promise, PromiseFulfiller};
use private::{with_current_event_loop};

pub mod tcp;

#[cfg(unix)]
pub mod unix;

/// A `::std::io::Error` that also carries along some state. Useful for tasks from which you want to
/// return the state in both the error and the success cases, like `Promise<S, Error<S>>`.
pub struct Error<S> {
    pub state: S,
    pub error: ::std::io::Error,
}

impl <S> Error<S> {
    pub fn new(state: S, error: ::std::io::Error) -> Error<S> {
        Error { state: state, error: error }
    }
}

impl <S> Into<::std::io::Error> for Error<S> {
    fn into(self) -> ::std::io::Error {
        self.error
    }
}

impl <S> Into<Box<::std::error::Error>> for Error<S> {
    fn into(self) -> Box<::std::error::Error> {
        self.error.into()
    }
}

/// A nonblocking input bytestream.
pub trait AsyncRead: 'static {
    /// Attempts to read `buf.len()` bytes from the stream, writing them into `buf`.
    /// Returns `self`, the modified `buf`, and the number of bytes actually read.
    /// Returns as soon as `min_bytes` are read or EOF is encountered.
    fn try_read<T>(self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: AsMut<[u8]>, Self: Sized;

    /// Like `try_read()`, but returns an error if EOF is encountered before `min_bytes`
    /// can be read.
    fn read<T>(self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: AsMut<[u8]>, Self: Sized
    {
        self.try_read(buf, min_bytes).map(move |(s, buf, n)| {
            if n < min_bytes {
                Err(Error::new((s, buf),
                               ::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF")))
            } else {
                Ok((s, buf, n))
            }
        })
    }
}

/// A nonblocking output bytestream.
pub trait AsyncWrite: 'static {
    /// Attempts to write all `buf.len()` bytes from `buf` into the stream. Returns `self` and `buf`
    /// once all of the bytes have been written.
    fn write<T>(self, buf: T) -> Promise<(Self, T), Error<(Self, T)>>
        where T: AsRef<[u8]>, Self: Sized;
}

pub struct Slice<T> where T: AsRef<[u8]> {
    pub buf: T,
    pub end: usize,
}

impl <T> Slice<T> where T: AsRef<[u8]> {
    pub fn new(buf: T, end: usize) -> Slice<T> {
        Slice { buf: buf, end: end }
    }
}

impl <T> AsRef<[u8]> for Slice<T> where T: AsRef<[u8]> {
    fn as_ref<'a>(&'a self) -> &'a [u8] {
        &self.buf.as_ref()[0..self.end]
    }
}

fn register_new_handle<E>(evented: &E) -> Result<Handle, ::std::io::Error> where E: ::mio::Evented {
    let handle = FdObserver::new();
    let token = ::mio::Token(handle.val);
    return with_current_event_loop(move |event_loop| {
        try!(event_loop.event_port.borrow_mut().reactor.register(evented, token,
                                                                 ::mio::EventSet::writable() |
                                                                 ::mio::EventSet::readable(),
                                                                 ::mio::PollOpt::edge()));
        // XXX if this fails, the handle does not get cleaned up.
        return Ok(handle);
    });
}

trait HasHandle {
    fn get_handle(&self) -> Handle;
}

fn try_read_internal<R, T>(mut reader: R,
                           mut buf: T,
                           mut already_read: usize,
                           min_bytes: usize) -> Promise<(R, T, usize), Error<(R, T)>>
    where T: AsMut<[u8]>, R: ::std::io::Read + HasHandle
{
    use std::io::Read;

    while already_read < min_bytes {
        match reader.read(&mut buf.as_mut()[already_read..]) {
            Ok(0) => {
                // EOF
                return Promise::ok((reader, buf, already_read));
            }
            Ok(n) => {
                already_read += n;
            }
            Err(e) => {
                if e.kind() != ::std::io::ErrorKind::WouldBlock {
                    return Promise::err(Error::new((reader, buf), e))
                } else {
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[reader.get_handle()].when_becomes_readable();
                        promise.then_else(move |r| match r {
                            Ok(()) => try_read_internal(reader, buf, already_read, min_bytes),
                            Err(e) => Promise::err(Error::new((reader, buf), e))
                        })
                    });
                }
            }
        }
    }

    Promise::ok((reader, buf, already_read))
}

fn write_internal<W, T>(mut writer: W,
                        buf: T,
                        mut already_written: usize) -> Promise<(W, T), Error<(W, T)>>
    where T: AsRef<[u8]>, W: ::std::io::Write + HasHandle
{
    use ::std::io::Write;

    while already_written < buf.as_ref().len() {
        match writer.write(&buf.as_ref()[already_written..]) {
            Ok(n) => {
                already_written += n;
            }
            Err(e) => {
                if e.kind() != ::std::io::ErrorKind::WouldBlock {
                    return Promise::err(Error::new((writer, buf), e))
                } else {
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[writer.get_handle()].when_becomes_writable();
                        promise.then_else(move |r| match r {
                            Ok(()) => write_internal(writer, buf, already_written),
                            Err(e) => Promise::err(Error::new((writer, buf), e))
                        })
                    });
                }
            }
        }
    }

    Promise::ok((writer, buf))
}

struct FdObserver {
    read_fulfiller: Option<PromiseFulfiller<(), ::std::io::Error>>,
    write_fulfiller: Option<PromiseFulfiller<(), ::std::io::Error>>,
}

impl FdObserver {
    pub fn new() -> Handle {
        with_current_event_loop(move |event_loop| {

            let observer = FdObserver { read_fulfiller: None, write_fulfiller: None };
            let event_port = &mut *event_loop.event_port.borrow_mut();
            return event_port.handler.observers.push(observer);
        })
    }

    pub fn when_becomes_readable(&mut self) -> Promise<(), ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.read_fulfiller = Some(fulfiller);
        return promise;
    }

    pub fn when_becomes_writable(&mut self) -> Promise<(), ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.write_fulfiller = Some(fulfiller);
        return promise;
    }
}

#[doc(hidden)]
pub struct MioEventPort {
    handler: Handler,
    reactor: ::mio::EventLoop<Handler>,
}

struct Handler {
    observers: HandleTable<FdObserver>,
}

impl MioEventPort {
    pub fn new() -> Result<MioEventPort, ::std::io::Error> {
        Ok(MioEventPort {
            handler: Handler { observers: HandleTable::new() },
            reactor: try!(::mio::EventLoop::new()),
        })
    }
}

impl ::mio::Handler for Handler {
    type Timeout = Timeout;
    type Message = ();
    fn ready(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>,
             token: ::mio::Token, events: ::mio::EventSet) {
        if events.is_readable() {
            match ::std::mem::replace(&mut self.observers[Handle {val: token.0}].read_fulfiller, None) {
                Some(fulfiller) => {
                    fulfiller.fulfill(())
                }
                None => {
                    ()
                }
            }
        }
        if events.is_writable() {
            match ::std::mem::replace(&mut self.observers[Handle { val: token.0}].write_fulfiller, None) {
                Some(fulfiller) => fulfiller.fulfill(()),
                None => (),
            }
        }
    }
    fn timeout(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>, timeout: Timeout) {
        timeout.fulfiller.fulfill(());
    }
}

impl EventPort for MioEventPort {
    fn wait(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler, None).unwrap();
        false
    }

    fn poll(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler, None).unwrap();
        false
    }
}

pub struct Timer;

impl Timer {
    pub fn after_delay_ms(&self, delay: u64) -> Promise<(), ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        let timeout = Timeout { fulfiller: fulfiller };
        with_current_event_loop(move |event_loop| {
            let handle = match event_loop.event_port.borrow_mut().reactor.timeout_ms(timeout, delay) {
                Ok(v) => v,
                Err(_) => return Promise::err(::std::io::Error::new(::std::io::ErrorKind::Other,
                                                                    "mio timer error"))
            };
            Promise {
                node: Box::new(
                    ::private::promise_node::Wrapper::new(promise.node,
                                                          TimeoutDropper { handle: handle })) }
        })
    }

    pub fn timeout_after_ms<T>(&self, delay: u64,
                               promise: Promise<T, ::std::io::Error>) -> Promise<T, ::std::io::Error>
    {
        promise.exclusive_join(self.after_delay_ms(delay).map(|()| {
            Err(::std::io::Error::new(::std::io::ErrorKind::Other, "operation timed out"))
        }))
    }
}

struct TimeoutDropper {
    handle: ::mio::Timeout,
}

impl Drop for TimeoutDropper {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().reactor.clear_timeout(self.handle);
        });
    }
}

struct Timeout {
    fulfiller: PromiseFulfiller<(), ::std::io::Error>,
}
<commit_msg>drop unused import<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Asynchronous input and output.
//!
//! # Example
//!
//! ```
//! use gj::{EventLoop, Promise};
//! use gj::io::{AsyncRead, AsyncWrite, Slice, unix};
//!
//! fn echo(stream: unix::Stream, buf: Vec<u8>) -> Promise<(), ::std::io::Error> {
//!     stream.try_read(buf, 1).lift().then(move |(stream, buf, n)| {
//!         if n == 0 { // EOF
//!             Promise::ok(())
//!         } else {
//!             stream.write(Slice::new(buf, n)).lift().then(move |(stream, slice)| {
//!                 echo(stream, slice.buf)
//!             })
//!         }
//!     })
//! }
//!
//! EventLoop::top_level(|wait_scope| {
//!     let (stream1, stream2) = try!(unix::Stream::new_pair());
//!     let promise1 = echo(stream1, vec![0; 5]);
//!     let promise2 = stream2.write(b"hello world").lift().then(|(stream, _)| {
//!         stream.read(vec![0; 11], 11).map(|(_, buf, _)| {
//!             assert_eq!(buf, b"hello world");
//!             Ok(())
//!         }).lift()
//!     });
//!     Promise::all(vec![promise1, promise2].into_iter()).wait(wait_scope).unwrap();
//!     Ok(())
//! }).unwrap();
//! ```

use std::result::Result;
use handle_table::{HandleTable, Handle};
use {EventPort, Promise, PromiseFulfiller};
use private::{with_current_event_loop};

pub mod tcp;

#[cfg(unix)]
pub mod unix;

/// A `::std::io::Error` that also carries along some state. Useful for tasks from which you want to
/// return the state in both the error and the success cases, like `Promise<S, Error<S>>`.
pub struct Error<S> {
    pub state: S,
    pub error: ::std::io::Error,
}

impl <S> Error<S> {
    pub fn new(state: S, error: ::std::io::Error) -> Error<S> {
        Error { state: state, error: error }
    }
}

impl <S> Into<::std::io::Error> for Error<S> {
    fn into(self) -> ::std::io::Error {
        self.error
    }
}

impl <S> Into<Box<::std::error::Error>> for Error<S> {
    fn into(self) -> Box<::std::error::Error> {
        self.error.into()
    }
}

/// A nonblocking input bytestream.
pub trait AsyncRead: 'static {
    /// Attempts to read `buf.len()` bytes from the stream, writing them into `buf`.
    /// Returns `self`, the modified `buf`, and the number of bytes actually read.
    /// Returns as soon as `min_bytes` are read or EOF is encountered.
    fn try_read<T>(self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: AsMut<[u8]>, Self: Sized;

    /// Like `try_read()`, but returns an error if EOF is encountered before `min_bytes`
    /// can be read.
    fn read<T>(self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: AsMut<[u8]>, Self: Sized
    {
        self.try_read(buf, min_bytes).map(move |(s, buf, n)| {
            if n < min_bytes {
                Err(Error::new((s, buf),
                               ::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF")))
            } else {
                Ok((s, buf, n))
            }
        })
    }
}

/// A nonblocking output bytestream.
pub trait AsyncWrite: 'static {
    /// Attempts to write all `buf.len()` bytes from `buf` into the stream. Returns `self` and `buf`
    /// once all of the bytes have been written.
    fn write<T>(self, buf: T) -> Promise<(Self, T), Error<(Self, T)>>
        where T: AsRef<[u8]>, Self: Sized;
}

pub struct Slice<T> where T: AsRef<[u8]> {
    pub buf: T,
    pub end: usize,
}

impl <T> Slice<T> where T: AsRef<[u8]> {
    pub fn new(buf: T, end: usize) -> Slice<T> {
        Slice { buf: buf, end: end }
    }
}

impl <T> AsRef<[u8]> for Slice<T> where T: AsRef<[u8]> {
    fn as_ref<'a>(&'a self) -> &'a [u8] {
        &self.buf.as_ref()[0..self.end]
    }
}

fn register_new_handle<E>(evented: &E) -> Result<Handle, ::std::io::Error> where E: ::mio::Evented {
    let handle = FdObserver::new();
    let token = ::mio::Token(handle.val);
    return with_current_event_loop(move |event_loop| {
        try!(event_loop.event_port.borrow_mut().reactor.register(evented, token,
                                                                 ::mio::EventSet::writable() |
                                                                 ::mio::EventSet::readable(),
                                                                 ::mio::PollOpt::edge()));
        // XXX if this fails, the handle does not get cleaned up.
        return Ok(handle);
    });
}

trait HasHandle {
    fn get_handle(&self) -> Handle;
}

fn try_read_internal<R, T>(mut reader: R,
                           mut buf: T,
                           mut already_read: usize,
                           min_bytes: usize) -> Promise<(R, T, usize), Error<(R, T)>>
    where T: AsMut<[u8]>, R: ::std::io::Read + HasHandle
{
    use std::io::Read;

    while already_read < min_bytes {
        match reader.read(&mut buf.as_mut()[already_read..]) {
            Ok(0) => {
                // EOF
                return Promise::ok((reader, buf, already_read));
            }
            Ok(n) => {
                already_read += n;
            }
            Err(e) => {
                if e.kind() != ::std::io::ErrorKind::WouldBlock {
                    return Promise::err(Error::new((reader, buf), e))
                } else {
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[reader.get_handle()].when_becomes_readable();
                        promise.then_else(move |r| match r {
                            Ok(()) => try_read_internal(reader, buf, already_read, min_bytes),
                            Err(e) => Promise::err(Error::new((reader, buf), e))
                        })
                    });
                }
            }
        }
    }

    Promise::ok((reader, buf, already_read))
}

fn write_internal<W, T>(mut writer: W,
                        buf: T,
                        mut already_written: usize) -> Promise<(W, T), Error<(W, T)>>
    where T: AsRef<[u8]>, W: ::std::io::Write + HasHandle
{
    use ::std::io::Write;

    while already_written < buf.as_ref().len() {
        match writer.write(&buf.as_ref()[already_written..]) {
            Ok(n) => {
                already_written += n;
            }
            Err(e) => {
                if e.kind() != ::std::io::ErrorKind::WouldBlock {
                    return Promise::err(Error::new((writer, buf), e))
                } else {
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[writer.get_handle()].when_becomes_writable();
                        promise.then_else(move |r| match r {
                            Ok(()) => write_internal(writer, buf, already_written),
                            Err(e) => Promise::err(Error::new((writer, buf), e))
                        })
                    });
                }
            }
        }
    }

    Promise::ok((writer, buf))
}

struct FdObserver {
    read_fulfiller: Option<PromiseFulfiller<(), ::std::io::Error>>,
    write_fulfiller: Option<PromiseFulfiller<(), ::std::io::Error>>,
}

impl FdObserver {
    pub fn new() -> Handle {
        with_current_event_loop(move |event_loop| {

            let observer = FdObserver { read_fulfiller: None, write_fulfiller: None };
            let event_port = &mut *event_loop.event_port.borrow_mut();
            return event_port.handler.observers.push(observer);
        })
    }

    pub fn when_becomes_readable(&mut self) -> Promise<(), ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.read_fulfiller = Some(fulfiller);
        return promise;
    }

    pub fn when_becomes_writable(&mut self) -> Promise<(), ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        self.write_fulfiller = Some(fulfiller);
        return promise;
    }
}

#[doc(hidden)]
pub struct MioEventPort {
    handler: Handler,
    reactor: ::mio::EventLoop<Handler>,
}

struct Handler {
    observers: HandleTable<FdObserver>,
}

impl MioEventPort {
    pub fn new() -> Result<MioEventPort, ::std::io::Error> {
        Ok(MioEventPort {
            handler: Handler { observers: HandleTable::new() },
            reactor: try!(::mio::EventLoop::new()),
        })
    }
}

impl ::mio::Handler for Handler {
    type Timeout = Timeout;
    type Message = ();
    fn ready(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>,
             token: ::mio::Token, events: ::mio::EventSet) {
        if events.is_readable() {
            match ::std::mem::replace(&mut self.observers[Handle {val: token.0}].read_fulfiller, None) {
                Some(fulfiller) => {
                    fulfiller.fulfill(())
                }
                None => {
                    ()
                }
            }
        }
        if events.is_writable() {
            match ::std::mem::replace(&mut self.observers[Handle { val: token.0}].write_fulfiller, None) {
                Some(fulfiller) => fulfiller.fulfill(()),
                None => (),
            }
        }
    }
    fn timeout(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>, timeout: Timeout) {
        timeout.fulfiller.fulfill(());
    }
}

impl EventPort for MioEventPort {
    fn wait(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler, None).unwrap();
        false
    }

    fn poll(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler, None).unwrap();
        false
    }
}

pub struct Timer;

impl Timer {
    pub fn after_delay_ms(&self, delay: u64) -> Promise<(), ::std::io::Error> {
        let (promise, fulfiller) = Promise::and_fulfiller();
        let timeout = Timeout { fulfiller: fulfiller };
        with_current_event_loop(move |event_loop| {
            let handle = match event_loop.event_port.borrow_mut().reactor.timeout_ms(timeout, delay) {
                Ok(v) => v,
                Err(_) => return Promise::err(::std::io::Error::new(::std::io::ErrorKind::Other,
                                                                    "mio timer error"))
            };
            Promise {
                node: Box::new(
                    ::private::promise_node::Wrapper::new(promise.node,
                                                          TimeoutDropper { handle: handle })) }
        })
    }

    pub fn timeout_after_ms<T>(&self, delay: u64,
                               promise: Promise<T, ::std::io::Error>) -> Promise<T, ::std::io::Error>
    {
        promise.exclusive_join(self.after_delay_ms(delay).map(|()| {
            Err(::std::io::Error::new(::std::io::ErrorKind::Other, "operation timed out"))
        }))
    }
}

struct TimeoutDropper {
    handle: ::mio::Timeout,
}

impl Drop for TimeoutDropper {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().reactor.clear_timeout(self.handle);
        });
    }
}

struct Timeout {
    fulfiller: PromiseFulfiller<(), ::std::io::Error>,
}
<|endoftext|>