<commit_before>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#[doc(hidden)]
#[macro_export]
macro_rules! consumes_to {
    ( $_rules:ident, $tokens:expr, [] ) => {
        let rest: Vec<_> = $tokens.map(|r| r.unwrap()).collect();

        assert!(rest.is_empty(), format!("expected end of stream, but found {:?}", rest));
    };
    ( $rules:ident, $tokens:expr, [ $name:ident ( $start:expr, $end:expr ) ] ) => {
        let expected = format!("expected Start {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $start);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::Start { rule, pos } => {
                let message = format!("{} but found Start {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $start {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        let expected = format!("expected End {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $end);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::End { rule, pos } => {
                let message = format!("{} but found End {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $end {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };
    };
    ( $rules:ident, $tokens:expr, [ $name:ident ( $start:expr, $end:expr ),
                                    $( $names:ident $calls:tt ),* ] ) => {

        let expected = format!("expected Start {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $start);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::Start { rule, pos } => {
                let message = format!("{} but found Start {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $start {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        let expected = format!("expected End {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $end);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::End { rule, pos } => {
                let message = format!("{} but found End {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $end {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        consumes_to!($rules, $tokens, [ $( $names $calls ),* ]);
    };
    ( $rules:ident, $tokens:expr, [ $name:ident ( $start:expr, $end:expr,
                                                  [ $( $names:ident $calls:tt ),* ] ) ] ) => {
        let expected = format!("expected Start {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $start);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::Start { rule, pos } => {
                let message = format!("{} but found Start {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $start {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        consumes_to!($rules, $tokens, [ $( $names $calls ),* ]);

        let expected = format!("expected End {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $end);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::End { rule, pos } => {
                let message = format!("{} but found End {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $end {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };
    };
    ( $rules:ident, $tokens:expr, [ $name:ident ( $start:expr, $end:expr,
                                                  [ $( $nested_names:ident $nested_calls:tt ),* ] ),
                                    $( $names:ident $calls:tt ),* ] ) => {

        let expected = format!("expected Start {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $start);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::Start { rule, pos } => {
                let message = format!("{} but found Start {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $start {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        consumes_to!($rules, $tokens, [ $( $nested_names $nested_calls ),* ]);

        let expected = format!("expected End {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $end);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::End { rule, pos } => {
                let message = format!("{} but found End {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $end {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        consumes_to!($rules, $tokens, [ $( $names $calls ),* ]);
    };
}

/// A `macro` which facilitates grammar testing and debugging.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate pest;
/// # use std::rc::Rc;
/// # use pest::{Error, Parser};
/// # use pest::inputs::Input;
/// # use pest::iterators::Pairs;
/// # fn main() {
/// # #[allow(non_camel_case_types)]
/// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
/// # enum Rule {
/// #     a,
/// #     b,
/// #     c
/// # }
/// #
/// # struct AbcParser;
/// #
/// # impl Parser<Rule> for AbcParser {
/// #     fn parse<I: Input>(_: Rule, input: Rc<I>) -> Result<Pairs<Rule, I>, Error<Rule, I>> {
/// #         pest::state(input, |mut state, pos| {
/// #             state.rule(Rule::a, pos, |state, pos| {
/// #                 state.rule(Rule::b, pos.skip(1).unwrap(), |_, pos| {
/// #                     pos.skip(1)
/// #                 }).unwrap().skip(1)
/// #             }).and_then(|p| {
/// #                 state.rule(Rule::c, p.skip(1).unwrap(), |_, pos| {
/// #                     pos.skip(1)
/// #                 })
/// #             })
/// #         })
/// #     }
/// # }
/// parses_to! {
///     parser: AbcParser,
///     input:  "abcde",
///     rule:   Rule::a,
///     tokens: [
///         a(0, 3, [
///             b(1, 2)
///         ]),
///         c(4, 5)
///     ]
/// };
/// # }
/// ```
#[macro_export]
macro_rules! parses_to {
    ( parser: $parser:ident, input: $string:expr, rule: $rules:tt :: $rule:tt,
      tokens: [ $( $names:ident $calls:tt ),* ] ) => {

        let input = $crate::inputs::StringInput::new($string.to_owned());
        let mut tokens = $parser::parse($rules::$rule,
                                        ::std::rc::Rc::new(input)).unwrap().into_iter();

        consumes_to!($rules, tokens, [ $( $names $calls ),* ]);
    };
}

#[cfg(test)]
mod tests {
    use std::rc::Rc;

    use super::super::error::Error;
    use super::super::inputs::Input;
    use super::super::{Parser, state};
    use super::super::iterators::Pairs;

    #[allow(non_camel_case_types)]
    #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    enum Rule {
        a,
        b,
        c
    }

    struct AbcParser;

    impl Parser<Rule> for AbcParser {
        fn parse<I: Input>(_: Rule, input: Rc<I>) -> Result<Pairs<Rule, I>, Error<Rule, I>> {
            state(input, |mut state, pos| {
                state.rule(Rule::a, pos, |state, pos| {
                    state.rule(Rule::b, pos.skip(1).unwrap(), |_, pos| {
                        pos.skip(1)
                    }).unwrap().skip(1)
                }).and_then(|p| {
                    state.rule(Rule::c, p.skip(1).unwrap(), |_, pos| {
                        pos.skip(1)
                    })
                })
            })
        }
    }

    #[test]
    fn parses_to() {
        parses_to! {
            parser: AbcParser,
            input: "abcde",
            rule: Rule::a,
            tokens: [
                a(0, 3, [
                    b(1, 2)
                ]),
                c(4, 5)
            ]
        };
    }
}
<commit_msg>Fixed testing macro bug.<commit_after>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#[doc(hidden)]
#[macro_export]
macro_rules! consumes_to {
    ( $_rules:ident, $tokens:expr, [] ) => ();
    ( $rules:ident, $tokens:expr, [ $name:ident ( $start:expr, $end:expr ) ] ) => {
        let expected = format!("expected Start {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $start);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::Start { rule, pos } => {
                let message = format!("{} but found Start {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $start {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        let expected = format!("expected End {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $end);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::End { rule, pos } => {
                let message = format!("{} but found End {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $end {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };
    };
    ( $rules:ident, $tokens:expr, [ $name:ident ( $start:expr, $end:expr ),
                                    $( $names:ident $calls:tt ),* ] ) => {

        let expected = format!("expected Start {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $start);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::Start { rule, pos } => {
                let message = format!("{} but found Start {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $start {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        let expected = format!("expected End {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $end);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::End { rule, pos } => {
                let message = format!("{} but found End {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $end {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        consumes_to!($rules, $tokens, [ $( $names $calls ),* ]);
    };
    ( $rules:ident, $tokens:expr, [ $name:ident ( $start:expr, $end:expr,
                                                  [ $( $names:ident $calls:tt ),* ] ) ] ) => {
        let expected = format!("expected Start {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $start);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::Start { rule, pos } => {
                let message = format!("{} but found Start {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $start {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        consumes_to!($rules, $tokens, [ $( $names $calls ),* ]);

        let expected = format!("expected End {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $end);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::End { rule, pos } => {
                let message = format!("{} but found End {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $end {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };
    };
    ( $rules:ident, $tokens:expr, [ $name:ident ( $start:expr, $end:expr,
                                                  [ $( $nested_names:ident $nested_calls:tt ),* ] ),
                                    $( $names:ident $calls:tt ),* ] ) => {

        let expected = format!("expected Start {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $start);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::Start { rule, pos } => {
                let message = format!("{} but found Start {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $start {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        consumes_to!($rules, $tokens, [ $( $nested_names $nested_calls ),* ]);

        let expected = format!("expected End {{ rule: {:?}, pos: Position {{ pos: {} }} }}",
                               $rules::$name, $end);
        match $tokens.next().expect(&format!("{} but found nothing", expected)) {
            $crate::Token::End { rule, pos } => {
                let message = format!("{} but found End {{ rule: {:?}, pos: Position {{ {} }} }}",
                                      expected, rule, pos.pos());

                if rule != $rules::$name || pos.pos() != $end {
                    panic!("{}", message);
                }
            },
            token => panic!("{}", format!("{} but found {:?}", expected, token))
        };

        consumes_to!($rules, $tokens, [ $( $names $calls ),* ]);
    };
}

/// A `macro` which facilitates grammar testing and debugging.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # extern crate pest;
/// # use std::rc::Rc;
/// # use pest::{Error, Parser};
/// # use pest::inputs::Input;
/// # use pest::iterators::Pairs;
/// # fn main() {
/// # #[allow(non_camel_case_types)]
/// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
/// # enum Rule {
/// #     a,
/// #     b,
/// #     c
/// # }
/// #
/// # struct AbcParser;
/// #
/// # impl Parser<Rule> for AbcParser {
/// #     fn parse<I: Input>(_: Rule, input: Rc<I>) -> Result<Pairs<Rule, I>, Error<Rule, I>> {
/// #         pest::state(input, |mut state, pos| {
/// #             state.rule(Rule::a, pos, |state, pos| {
/// #                 state.rule(Rule::b, pos.skip(1).unwrap(), |_, pos| {
/// #                     pos.skip(1)
/// #                 }).unwrap().skip(1)
/// #             }).and_then(|p| {
/// #                 state.rule(Rule::c, p.skip(1).unwrap(), |_, pos| {
/// #                     pos.skip(1)
/// #                 })
/// #             })
/// #         })
/// #     }
/// # }
/// parses_to! {
///     parser: AbcParser,
///     input:  "abcde",
///     rule:   Rule::a,
///     tokens: [
///         a(0, 3, [
///             b(1, 2)
///         ]),
///         c(4, 5)
///     ]
/// };
/// # }
/// ```
#[macro_export]
macro_rules! parses_to {
    ( parser: $parser:ident, input: $string:expr, rule: $rules:tt :: $rule:tt,
      tokens: [ $( $names:ident $calls:tt ),* ] ) => {

        #[allow(unused_mut)]
        {
            let input = $crate::inputs::StringInput::new($string.to_owned());
            let mut tokens = $parser::parse($rules::$rule,
                                            ::std::rc::Rc::new(input)).unwrap().into_iter();

            consumes_to!($rules, &mut tokens, [ $( $names $calls ),* ]);

            let rest: Vec<_> = tokens.collect();

            assert!(rest.is_empty(), format!("expected end of stream, but found {:?}", rest));
        }
    };
}

#[cfg(test)]
mod tests {
    use std::rc::Rc;

    use super::super::error::Error;
    use super::super::inputs::Input;
    use super::super::{Parser, state};
    use super::super::iterators::Pairs;

    #[allow(non_camel_case_types)]
    #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    enum Rule {
        a,
        b,
        c
    }

    struct AbcParser;

    impl Parser<Rule> for AbcParser {
        fn parse<I: Input>(_: Rule, input: Rc<I>) -> Result<Pairs<Rule, I>, Error<Rule, I>> {
            state(input, |mut state, pos| {
                state.rule(Rule::a, pos, |state, pos| {
                    state.rule(Rule::b, pos.skip(1).unwrap(), |_, pos| {
                        pos.skip(1)
                    }).unwrap().skip(1)
                }).and_then(|p| {
                    state.rule(Rule::c, p.skip(1).unwrap(), |_, pos| {
                        pos.skip(1)
                    })
                })
            })
        }
    }

    #[test]
    fn parses_to() {
        parses_to! {
            parser: AbcParser,
            input: "abcde",
            rule: Rule::a,
            tokens: [
                a(0, 3, [
                    b(1, 2)
                ]),
                c(4, 5)
            ]
        };
    }

    #[test]
    #[should_panic]
    fn missing_end() {
        parses_to! {
            parser: AbcParser,
            input: "abcde",
            rule: Rule::a,
            tokens: [
                a(0, 3, [
                    b(1, 2)
                ])
            ]
        };
    }

    #[test]
    #[should_panic]
    fn empty() {
        parses_to! {
            parser: AbcParser,
            input: "abcde",
            rule: Rule::a,
            tokens: []
        };
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate gj;
extern crate nix;

use std::cell::{RefCell};
use std::rc::Rc;
use gj::{Promise, PromiseFulfiller};
use handle_table::{HandleTable, Handle};

mod handle_table;
mod sys;

/// A nonblocking input bytestream.
pub trait Read {
    /// 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>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>;

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

/// A nonblocking output bytestream.
pub trait AsyncWrite {
    /// 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: AsRef<[u8]>>(&mut self, buf: T) -> Promise<T, ::std::io::Error>;
}

#[cfg(unix)]
type RawDescriptor = std::os::unix::io::RawFd;

pub struct EventPort {
    reactor: Rc<RefCell<::sys::Reactor>>,
}

impl EventPort {
    pub fn new() -> Result<EventPort, ::std::io::Error> {
        Ok( EventPort {
            reactor: Rc::new(RefCell::new(try!(sys::Reactor::new()))),
        })
    }

    pub fn get_network(&self) -> Network {
        Network::new(self.reactor.clone())
    }
}

impl gj::EventPort<::std::io::Error> for EventPort {
    fn wait(&mut self) -> Result<(), ::std::io::Error> {
        self.reactor.borrow_mut().run_once()
    }
}

pub struct Network {
    reactor: Rc<RefCell<::sys::Reactor>>,
}

impl Network {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>) -> Network {
        Network { reactor: reactor }
    }

    fn connect_internal(&mut self, addr: ::nix::sys::socket::SockAddr)
                        -> Promise<SocketStream, ::std::io::Error>
    {
        let reactor = self.reactor.clone();
        Promise::ok(()).then(move |()| {
            let mut reactor = reactor;

            let fd = pry!(nix::sys::socket::socket(addr.family(), nix::sys::socket::SockType::Stream,
                                                   nix::sys::socket::SOCK_NONBLOCK, 0));

            pry!(::nix::sys::socket::connect(fd, &addr));
            let handle = pry!(reactor.borrow_mut().new_observer(fd));

            // TODO: if we're not already connected, maybe only register writable interest,
            // and then reregister with read/write interested once we successfully connect.

            let promise = reactor.borrow_mut().observers[handle].when_becomes_writable();
            promise.map(move |()| {
//                try!(stream.take_socket_error());
                Ok(SocketStream::new(reactor, handle, fd))
            })
        })
    }

    pub fn connect(&mut self, addr: ::std::net::SocketAddr) -> Promise<SocketStream, ::std::io::Error> {
        self.connect_internal(
            ::nix::sys::socket::SockAddr::Inet(::nix::sys::socket::InetAddr::from_std(&addr)))
    }

    fn bind_internal(&mut self, addr: ::nix::sys::socket::SockAddr)
                     -> Result<SocketListener, ::std::io::Error> {
        let fd = try!(nix::sys::socket::socket(addr.family(), nix::sys::socket::SockType::Stream,
                                               nix::sys::socket::SOCK_NONBLOCK, 0));

        try!(nix::sys::socket::bind(fd, &addr));
        let handle = try!(self.reactor.borrow_mut().new_observer(fd));
        Ok(SocketListener::new(self.reactor.clone(), handle, fd))
    }

    fn bind(&mut self, addr: ::std::net::SocketAddr)
            -> Result<SocketListener, ::std::io::Error>
    {
        self.bind_internal(::nix::sys::socket::SockAddr::Inet(::nix::sys::socket::InetAddr::from_std(&addr)))
    }
}

struct SocketListenerInner {
    reactor: Rc<RefCell<::sys::Reactor>>,
    handle: Handle,
    descriptor: RawDescriptor,
}

impl Drop for SocketListenerInner {
    fn drop(&mut self) {
        self.reactor.borrow_mut().observers.remove(self.handle);
    }
}

pub struct SocketListener {
    inner: Rc<RefCell<SocketListenerInner>>,
}

impl SocketListener {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>, handle: Handle, descriptor: RawDescriptor)
           -> SocketListener
    {
        SocketListener {
            inner: Rc::new(RefCell::new(SocketListenerInner {
                reactor: reactor,
                handle: handle,
                descriptor: descriptor,
            })),
        }
    }

    fn accept_internal(reactor: Rc<RefCell<SocketListenerInner>>) -> Promise<SocketStream, ::std::io::Error> {
        unimplemented!()
/*        match ::nix::sys::socket::accept4(self.fd, nix::sys::socket::SOCK_NONBLOCK) {
            Ok(fd) => {
                let handle = pry!(reactor.new_observer(fd));
                Promise::ok(SocketStream::new(reactor, handle, fd))
            }
            Err(e) => {
                match e.errno() {
                    ::nix::Errno::EAGAIN | nix::Errno::EWOULDBLOCK => {
                        unimplemented!()
                    }
                    _ => {
                        Promise::err(e.into())
                    }
                }
            }
        }*/
    }

    pub fn accept(&mut self) -> Promise<SocketStream, ::std::io::Error> {
        SocketListener::accept_internal(self.inner.clone())
    }
}

pub struct SocketStream {
    reactor: Rc<RefCell<::sys::Reactor>>,
    handle: Handle,
    descriptor: RawDescriptor,
}

impl Drop for SocketStream {
    fn drop(&mut self) {
        self.reactor.borrow_mut().observers.remove(self.handle);
    }
}

impl SocketStream {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>, handle: Handle, descriptor: RawDescriptor) -> SocketStream {
        SocketStream {
            reactor: reactor,
            handle: handle,
            descriptor: descriptor,
        }
    }
}

<commit_msg>Clone impls<commit_after>#[macro_use]
extern crate gj;
extern crate nix;

use std::cell::{RefCell};
use std::rc::Rc;
use gj::{Promise, PromiseFulfiller};
use handle_table::{HandleTable, Handle};

mod handle_table;
mod sys;

/// A nonblocking input bytestream.
pub trait Read {
    /// 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>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>;

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

/// A nonblocking output bytestream.
pub trait AsyncWrite {
    /// 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: AsRef<[u8]>>(&mut self, buf: T) -> Promise<T, ::std::io::Error>;
}

#[cfg(unix)]
type RawDescriptor = std::os::unix::io::RawFd;

pub struct EventPort {
    reactor: Rc<RefCell<::sys::Reactor>>,
}

impl EventPort {
    pub fn new() -> Result<EventPort, ::std::io::Error> {
        Ok( EventPort {
            reactor: Rc::new(RefCell::new(try!(sys::Reactor::new()))),
        })
    }

    pub fn get_network(&self) -> Network {
        Network::new(self.reactor.clone())
    }
}

impl gj::EventPort<::std::io::Error> for EventPort {
    fn wait(&mut self) -> Result<(), ::std::io::Error> {
        self.reactor.borrow_mut().run_once()
    }
}

pub struct Network {
    reactor: Rc<RefCell<::sys::Reactor>>,
}

impl Network {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>) -> Network {
        Network { reactor: reactor }
    }

    fn connect_internal(&mut self, addr: ::nix::sys::socket::SockAddr)
                        -> Promise<SocketStream, ::std::io::Error>
    {
        let reactor = self.reactor.clone();
        Promise::ok(()).then(move |()| {
            let mut reactor = reactor;

            let fd = pry!(nix::sys::socket::socket(addr.family(), nix::sys::socket::SockType::Stream,
                                                   nix::sys::socket::SOCK_NONBLOCK, 0));

            pry!(::nix::sys::socket::connect(fd, &addr));
            let handle = pry!(reactor.borrow_mut().new_observer(fd));

            // TODO: if we're not already connected, maybe only register writable interest,
            // and then reregister with read/write interested once we successfully connect.

            let promise = reactor.borrow_mut().observers[handle].when_becomes_writable();
            promise.map(move |()| {
//                try!(stream.take_socket_error());
                Ok(SocketStream::new(reactor, handle, fd))
            })
        })
    }

    pub fn connect(&mut self, addr: ::std::net::SocketAddr) -> Promise<SocketStream, ::std::io::Error> {
        self.connect_internal(
            ::nix::sys::socket::SockAddr::Inet(::nix::sys::socket::InetAddr::from_std(&addr)))
    }

    fn bind_internal(&mut self, addr: ::nix::sys::socket::SockAddr)
                     -> Result<SocketListener, ::std::io::Error> {
        let fd = try!(nix::sys::socket::socket(addr.family(), nix::sys::socket::SockType::Stream,
                                               nix::sys::socket::SOCK_NONBLOCK, 0));

        try!(nix::sys::socket::bind(fd, &addr));
        let handle = try!(self.reactor.borrow_mut().new_observer(fd));
        Ok(SocketListener::new(self.reactor.clone(), handle, fd))
    }

    fn bind(&mut self, addr: ::std::net::SocketAddr)
            -> Result<SocketListener, ::std::io::Error>
    {
        self.bind_internal(::nix::sys::socket::SockAddr::Inet(::nix::sys::socket::InetAddr::from_std(&addr)))
    }
}

struct SocketListenerInner {
    reactor: Rc<RefCell<::sys::Reactor>>,
    handle: Handle,
    descriptor: RawDescriptor,
}

impl Drop for SocketListenerInner {
    fn drop(&mut self) {
        self.reactor.borrow_mut().observers.remove(self.handle);
    }
}

pub struct SocketListener {
    inner: Rc<RefCell<SocketListenerInner>>,
}

impl Clone for SocketListener {
    fn clone(&self) -> SocketListener {
        SocketListener { inner: self.inner.clone() }
    }
}

impl SocketListener {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>, handle: Handle, descriptor: RawDescriptor)
           -> SocketListener
    {
        SocketListener {
            inner: Rc::new(RefCell::new(SocketListenerInner {
                reactor: reactor,
                handle: handle,
                descriptor: descriptor,
            })),
        }
    }

    fn accept_internal(reactor: Rc<RefCell<SocketListenerInner>>) -> Promise<SocketStream, ::std::io::Error> {
        unimplemented!()
/*        match ::nix::sys::socket::accept4(self.fd, nix::sys::socket::SOCK_NONBLOCK) {
            Ok(fd) => {
                let handle = pry!(reactor.new_observer(fd));
                Promise::ok(SocketStream::new(reactor, handle, fd))
            }
            Err(e) => {
                match e.errno() {
                    ::nix::Errno::EAGAIN | nix::Errno::EWOULDBLOCK => {
                        unimplemented!()
                    }
                    _ => {
                        Promise::err(e.into())
                    }
                }
            }
        }*/
    }

    pub fn accept(&mut self) -> Promise<SocketStream, ::std::io::Error> {
        SocketListener::accept_internal(self.inner.clone())
    }
}

struct SocketStreamInner {
    reactor: Rc<RefCell<::sys::Reactor>>,
    handle: Handle,
    descriptor: RawDescriptor,
}

impl Drop for SocketStreamInner {
    fn drop(&mut self) {
        self.reactor.borrow_mut().observers.remove(self.handle);
    }
}

pub struct SocketStream {
    inner: Rc<RefCell<SocketStreamInner>>,
}

impl Clone for SocketStream {
    fn clone(&self) -> SocketStream {
        SocketStream { inner: self.inner.clone() }
    }
}

impl SocketStream {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>, handle: Handle, descriptor: RawDescriptor) -> SocketStream {
        SocketStream {
            inner: Rc::new(RefCell::new(SocketStreamInner {
                reactor: reactor,
                handle: handle,
                descriptor: descriptor,
            })),
        }
    }
}

<|endoftext|>


<commit_before>mod node;
mod node_children;
mod node_text;
mod text_info;

pub(crate) use self::node::Node;
pub(crate) use self::node_children::NodeChildren;
pub(crate) use self::node_text::NodeText;
pub(crate) use self::text_info::TextInfo;

// Once size_of() is a const fn, remove this and use size_of() instead.
#[cfg(target_pointer_width = "64")]
const PTR_SIZE: usize = 8;
#[cfg(target_pointer_width = "32")]
const PTR_SIZE: usize = 4;
#[cfg(target_pointer_width = "16")]
const PTR_SIZE: usize = 2;

// Aim for nodes to be 512 - Arc counters.  This makes it easier for the
// memory allocator to avoid fragmentation.
const TARGET_NODE_SIZE: usize = 512 - (PTR_SIZE * 2);

// Node min/max values.
// Determined by TARGET_NODE_SIZE, above.
pub(crate) const MAX_CHILDREN: usize = (TARGET_NODE_SIZE - 1) / 32;
pub(crate) const MIN_CHILDREN: usize = MAX_CHILDREN - (MAX_CHILDREN / 2);
pub(crate) const MAX_BYTES: usize = TARGET_NODE_SIZE - 1 - (PTR_SIZE * 2);
pub(crate) const MIN_BYTES: usize = MAX_BYTES - (MAX_BYTES / 2);

// Type used for storing tree metadata, such as byte and char length.
pub(crate) type Count = u64;
<commit_msg>Use smaller node min/max values for testing.<commit_after>mod node;
mod node_children;
mod node_text;
mod text_info;

pub(crate) use self::node::Node;
pub(crate) use self::node_children::NodeChildren;
pub(crate) use self::node_text::NodeText;
pub(crate) use self::text_info::TextInfo;

// Once size_of() is a const fn, remove this and use size_of() instead.
#[cfg(all(not(test), target_pointer_width = "64"))]
const PTR_SIZE: usize = 8;
#[cfg(all(not(test), target_pointer_width = "32"))]
const PTR_SIZE: usize = 4;
#[cfg(all(not(test), target_pointer_width = "16"))]
const PTR_SIZE: usize = 2;

// Aim for nodes to be 512 - Arc counters.  This makes it easier for the
// memory allocator to avoid fragmentation.
#[cfg(not(test))]
const TARGET_NODE_SIZE: usize = 512 - (PTR_SIZE * 2);

// Node min/max values.
// For testing, they're set small to trigger deeper trees.  For
// non-testing, they're determined by TARGET_NODE_SIZE, above.
#[cfg(test)]
pub(crate) const MAX_CHILDREN: usize = 5;
#[cfg(not(test))]
pub(crate) const MAX_CHILDREN: usize = (TARGET_NODE_SIZE - 1) / 32;
pub(crate) const MIN_CHILDREN: usize = MAX_CHILDREN - (MAX_CHILDREN / 2);

#[cfg(test)]
pub(crate) const MAX_BYTES: usize = 2;
#[cfg(not(test))]
pub(crate) const MAX_BYTES: usize = TARGET_NODE_SIZE - 1 - (PTR_SIZE * 2);
pub(crate) const MIN_BYTES: usize = MAX_BYTES - (MAX_BYTES / 2);

// Type used for storing tree metadata, such as byte and char length.
pub(crate) type Count = u64;
<|endoftext|>


<commit_before>//! Module docs?  whatever

use path::Element;
use vertex::Vertex;
use graph::Graph;

#[derive(Debug, Display, Clone)]
pub struct TreePath {
    pub element: Element,
    pub children: Option<Box<Vec<TreePath>>>
}

impl TreePath {
    // we need to be able to use this on new graph query results because
    // we don't always start with a single vertex
    pub fn new() -> TreePath {
        TreePath{element:Element::TreeRoot, children:None}
    }
    // convenience method
    pub fn from_vertex(vertex: Vertex) -> TreePath {
        let e = Element::Vertex(vertex);
        TreePath::from_element(e)
    }

    pub fn from_element(element: Element) -> TreePath {
        TreePath{element:element, children:None}
    }

    pub fn add_child(&mut self, element: Element) {
        let child = TreePath::from_element(element);
        match self.children {
            None => {
                let mut v = Box::new(Vec::new());
                // create a new Treepath
                v.push(child);
                self.children = Some(v);
            }
            Some(ref mut children) => {
                children.push(child);
            }
        }
    }
    pub fn child_count(&self) -> usize {
        match self.children {
            None => 0,
            Some(ref x) => x.len()
        }
    }

    // iterator?
    pub fn leaves(&self)  {

    }

    // pub fn from_vertices(vlist: &[Vertex]) -> TreePath {
    //
    // }
}
<commit_msg>converted children to hashmap, removed the option<commit_after>//! Module docs?  whatever

use path::Element;
use vertex::Vertex;
use graph::Graph;
use std::collections::HashMap;

#[derive(Debug, Display, Clone)]
pub struct TreePath {
    pub element: Element,
    pub children: Box<HashMap<usize, TreePath>>,
    pub element_count: usize
}

impl TreePath {
    // we need to be able to use this on new graph query results because
    // we don't always start with a single vertex
    pub fn new() -> TreePath {

        TreePath{element:Element::TreeRoot, children:Box::new(HashMap::new()), element_count:0}
    }

    // convenience method
    pub fn from_vertex(vertex: Vertex) -> TreePath {
        let e = Element::Vertex(vertex);
        TreePath::from_element(e)
    }

    pub fn from_element(element: Element) -> TreePath {
        TreePath{element:element, children:Box::new(HashMap::new()), element_count:0}
    }

    pub fn add_child(&mut self, element: Element) {
        let child = TreePath::from_element(element);
                // create a new Treepath
        self.children.insert(self.element_count, child);
        self.element_count += 1;
    }

    pub fn child_count(&self) -> usize {
        self.children.len()
    }

    // iterator?
    pub fn leaves(&self)  {

    }

    // pub fn from_vertices(vlist: &[Vertex]) -> TreePath {
    //
    // }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
//use common::*;
use message::*;
use serialize::*;
use std::rt::io::ReaderByteConversions;

pub struct PackedInputStream<T> {
    inner : T
}

impl <T : std::rt::io::Reader> std::rt::io::Reader for PackedInputStream<T> {
    fn eof(&mut self) -> bool {
        self.inner.eof()
    }

    fn read(&mut self, outBuf: &mut [u8]) -> Option<uint> {
        let len = outBuf.len();

        if (len == 0) { return Some(0); }

        assert!(len % 8 == 0, "PackInputStream reads must be word-aligned");

        let mut outPos = 0;
        while (outPos < len && ! self.inner.eof() ) {

            let tag : u8 = self.inner.read_u8_();

            for n in range(0, 8) {
                let isNonzero = (tag & (1 as u8 << n)) != 0;//..as bool;
                if (isNonzero) {
                    // TODO capnproto-c++ gets away without using a
                    // conditional here. Can we do something like that
                    // and would it speed things up?
                    outBuf[outPos] = self.inner.read_u8_();
                    outPos += 1;
                } else {
                    outBuf[outPos] = 0;
                    outPos += 1;
                }
            }

            if (tag == 0) {

                let runLength : uint = self.inner.read_u8_() as uint * 8;

                unsafe {
                    std::ptr::set_memory(outBuf.unsafe_mut_ref(outPos),
                                         0, runLength);
                };
                outPos += runLength;

            } else if (tag == 0xff) {
                let runLength : uint = self.inner.read_u8_() as uint * 8;

                let mut bytes_read = 0;
                loop {
                    if bytes_read >= runLength { break }
                    let pos = outPos + bytes_read;
                    match self.inner.read(outBuf.mut_slice(pos, outPos + runLength)) {
                        Some(n) => bytes_read += n,
                        None => fail!("failed to read bytes")
                    }
                }
                outPos += runLength;
            }

        }

        return Some(outPos);
    }

}

pub struct PackedOutputStream<T> {
    inner : T
}

impl <T : std::rt::io::Writer> std::rt::io::Writer for PackedOutputStream<T> {
    fn write(&mut self, inBuf : &[u8]) {

        // Yuck. It'd be better to have a BufferedOutputStream, but
        // that seems difficult with the current state of Rust.
        // For now, just make this big enough to handle the worst case.
        let mut buffer : ~[u8] = std::vec::from_elem(inBuf.len() * 3 / 2, 0u8);

        let mut inPos : uint = 0;
        let mut outPos : uint = 0;

        while (inPos < inBuf.len()) {

            let tagPos = outPos;
            outPos += 1;

            let bit0 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit0 as uint; inPos += 1;

            let bit1 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit1 as uint; inPos += 1;

            let bit2 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit2 as uint; inPos += 1;

            let bit3 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit3 as uint; inPos += 1;

            let bit4 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit4 as uint; inPos += 1;

            let bit5 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit5 as uint; inPos += 1;

            let bit6 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit6 as uint; inPos += 1;

            let bit7 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit7 as uint; inPos += 1;

            let tag : u8 = (bit0 << 0) | (bit1 << 1) | (bit2 << 2) | (bit3 << 3)
                         | (bit4 << 4) | (bit5 << 5) | (bit6 << 6) | (bit7 << 7);

            buffer[tagPos] = tag;

            if (tag == 0) {
                //# An all-zero word is followed by a count of
                //# consecutive zero words (not including the first
                //# one).

                let mut count : u8 = 0;
                unsafe {
                    let mut inWord : *u64 =
                        std::cast::transmute(inBuf.unsafe_ref(inPos));
                    while (count < 255 && *inWord == 0) {
                        inWord = std::ptr::offset(inWord, 1);
                        count += 1;
                    }
                }
                buffer[outPos] = count;
                outPos += 1;

                inPos += count as uint * 8;

            } else if (tag == 0xff) {
                //# An all-nonzero word is followed by a count of
                //# consecutive uncompressed words, followed by the
                //# uncompressed words themselves.

                //# Count the number of consecutive words in the input
                //# which have no more than a single zero-byte. We look
                //# for at least two zeros because that's the point
                //# where our compression scheme becomes a net win.
                let mut count : u8 = 0;
                let runStart = inPos;
                while (inPos < inBuf.len() && count < 255) {
                    let mut c = 0;

                    for _ in range(0,8) {
                        c += (inBuf[inPos] == 0) as u8;
                        inPos += 1;
                    }

                    if (c >= 2) {
                        //# Un-read the word with multiple zeros, since
                        //# we'll want to compress that one.
                        inPos -= 8;
                        break;
                    }

                    count += 1;
                }
                buffer[outPos] = count;
                outPos += 1;

                unsafe {
                    let dst : *mut u8 = buffer.unsafe_mut_ref(outPos);
                    let src : *u8 = inBuf.unsafe_ref(runStart);
                    std::ptr::copy_memory(dst, src, 8 * count as uint);
                }
                outPos += count as uint * 8;

            }
        }

        self.inner.write(buffer.slice(0, outPos));
    }

   fn flush(&mut self) { self.inner.flush(); }
}

pub fn writePackedMessage<T : std::rt::io::Writer>(outputStream : T,
                                                   message : &MessageBuilder) {

    let mut packedOutputStream = PackedOutputStream {inner : outputStream};

    writeMessage(&mut packedOutputStream, message);
}
<commit_msg>use a while loop<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
//use common::*;
use message::*;
use serialize::*;
use std::rt::io::ReaderByteConversions;

pub struct PackedInputStream<T> {
    inner : T
}

impl <T : std::rt::io::Reader> std::rt::io::Reader for PackedInputStream<T> {
    fn eof(&mut self) -> bool {
        self.inner.eof()
    }

    fn read(&mut self, outBuf: &mut [u8]) -> Option<uint> {
        let len = outBuf.len();

        if (len == 0) { return Some(0); }

        assert!(len % 8 == 0, "PackInputStream reads must be word-aligned");

        let mut outPos = 0;
        while (outPos < len && ! self.inner.eof() ) {

            let tag : u8 = self.inner.read_u8_();

            for n in range(0, 8) {
                let isNonzero = (tag & (1 as u8 << n)) != 0;//..as bool;
                if (isNonzero) {
                    // TODO capnproto-c++ gets away without using a
                    // conditional here. Can we do something like that
                    // and would it speed things up?
                    outBuf[outPos] = self.inner.read_u8_();
                    outPos += 1;
                } else {
                    outBuf[outPos] = 0;
                    outPos += 1;
                }
            }

            if (tag == 0) {

                let runLength : uint = self.inner.read_u8_() as uint * 8;

                unsafe {
                    std::ptr::set_memory(outBuf.unsafe_mut_ref(outPos),
                                         0, runLength);
                };
                outPos += runLength;

            } else if (tag == 0xff) {
                let runLength : uint = self.inner.read_u8_() as uint * 8;

                let mut bytes_read = 0;
                while bytes_read < runLength {
                    let pos = outPos + bytes_read;
                    match self.inner.read(outBuf.mut_slice(pos, outPos + runLength)) {
                        Some(n) => bytes_read += n,
                        None => fail!("failed to read bytes")
                    }
                }
                outPos += runLength;
            }

        }

        return Some(outPos);
    }

}

pub struct PackedOutputStream<T> {
    inner : T
}

impl <T : std::rt::io::Writer> std::rt::io::Writer for PackedOutputStream<T> {
    fn write(&mut self, inBuf : &[u8]) {

        // Yuck. It'd be better to have a BufferedOutputStream, but
        // that seems difficult with the current state of Rust.
        // For now, just make this big enough to handle the worst case.
        let mut buffer : ~[u8] = std::vec::from_elem(inBuf.len() * 3 / 2, 0u8);

        let mut inPos : uint = 0;
        let mut outPos : uint = 0;

        while (inPos < inBuf.len()) {

            let tagPos = outPos;
            outPos += 1;

            let bit0 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit0 as uint; inPos += 1;

            let bit1 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit1 as uint; inPos += 1;

            let bit2 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit2 as uint; inPos += 1;

            let bit3 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit3 as uint; inPos += 1;

            let bit4 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit4 as uint; inPos += 1;

            let bit5 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit5 as uint; inPos += 1;

            let bit6 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit6 as uint; inPos += 1;

            let bit7 = (inBuf[inPos] != 0) as u8;
            buffer[outPos] = inBuf[inPos];
            outPos += bit7 as uint; inPos += 1;

            let tag : u8 = (bit0 << 0) | (bit1 << 1) | (bit2 << 2) | (bit3 << 3)
                         | (bit4 << 4) | (bit5 << 5) | (bit6 << 6) | (bit7 << 7);

            buffer[tagPos] = tag;

            if (tag == 0) {
                //# An all-zero word is followed by a count of
                //# consecutive zero words (not including the first
                //# one).

                let mut count : u8 = 0;
                unsafe {
                    let mut inWord : *u64 =
                        std::cast::transmute(inBuf.unsafe_ref(inPos));
                    while (count < 255 && *inWord == 0) {
                        inWord = std::ptr::offset(inWord, 1);
                        count += 1;
                    }
                }
                buffer[outPos] = count;
                outPos += 1;

                inPos += count as uint * 8;

            } else if (tag == 0xff) {
                //# An all-nonzero word is followed by a count of
                //# consecutive uncompressed words, followed by the
                //# uncompressed words themselves.

                //# Count the number of consecutive words in the input
                //# which have no more than a single zero-byte. We look
                //# for at least two zeros because that's the point
                //# where our compression scheme becomes a net win.
                let mut count : u8 = 0;
                let runStart = inPos;
                while (inPos < inBuf.len() && count < 255) {
                    let mut c = 0;

                    for _ in range(0,8) {
                        c += (inBuf[inPos] == 0) as u8;
                        inPos += 1;
                    }

                    if (c >= 2) {
                        //# Un-read the word with multiple zeros, since
                        //# we'll want to compress that one.
                        inPos -= 8;
                        break;
                    }

                    count += 1;
                }
                buffer[outPos] = count;
                outPos += 1;

                unsafe {
                    let dst : *mut u8 = buffer.unsafe_mut_ref(outPos);
                    let src : *u8 = inBuf.unsafe_ref(runStart);
                    std::ptr::copy_memory(dst, src, 8 * count as uint);
                }
                outPos += count as uint * 8;

            }
        }

        self.inner.write(buffer.slice(0, outPos));
    }

   fn flush(&mut self) { self.inner.flush(); }
}

pub fn writePackedMessage<T : std::rt::io::Writer>(outputStream : T,
                                                   message : &MessageBuilder) {

    let mut packedOutputStream = PackedOutputStream {inner : outputStream};

    writeMessage(&mut packedOutputStream, message);
}
<|endoftext|>


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

use rustc::hir::{self, ImplPolarity};
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::ty::{self, TyCtxt};
use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
use syntax::ast;
use rustc_data_structures::sync::Lrc;

trait Lower<T> {
    /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type.
    fn lower(&self) -> T;
}

impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
    fn lower(&self) -> Vec<U> {
        self.iter().map(|item| item.lower()).collect()
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::TraitPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::Implemented(*self)
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::ProjectionEq(*self)
    }
}

impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::Holds(self.lower())
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::RegionOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::RegionOutlives(*self)
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::TypeOutlives(*self)
    }
}

/// `ty::Binder` is used for wrapping a rustc construction possibly containing generic
/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things
/// in that leaf-form (i.e. `Holds(Implemented(Binder<TraitPredicate>))` in the previous
/// example), we model them with quantified goals, e.g. as for the previous example:
/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
/// `Binder<Holds(Implemented(TraitPredicate))>`.
///
/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we
/// can directly lower to a leaf goal instead of a quantified goal.
impl<'tcx, T> Lower<Goal<'tcx>> for ty::Binder<T>
    where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> + Copy
{
    fn lower(&self) -> Goal<'tcx> {
        match self.no_late_bound_regions() {
            Some(p) => p.lower().into(),
            None => Goal::Quantified(
                QuantifierKind::Universal,
                Box::new(self.map_bound(|p| p.lower().into()))
            ),
        }
    }
}

impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
    fn lower(&self) -> Goal<'tcx> {
        use rustc::ty::Predicate::*;

        match self {
            Trait(predicate) => predicate.lower(),
            RegionOutlives(predicate) => predicate.lower(),
            TypeOutlives(predicate) => predicate.lower(),
            Projection(predicate) => predicate.lower(),
            WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(),
            ObjectSafe(..) |
            ClosureKind(..) |
            Subtype(..) |
            ConstEvaluatable(..) => unimplemented!(),
        }
    }
}

crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
    let item = tcx.hir.expect_item(node_id);
    match item.node {
        hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),

        // FIXME: other constructions e.g. traits, associated types...
        _ => Lrc::new(vec![]),
    }
}

fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
        return Lrc::new(vec![]);
    }

    // Rule Implemented-From-Impl
    //
    // (see rustc guide)

    let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
    let trait_ref = ty::TraitPredicate { trait_ref }.lower();
    let where_clauses = tcx.predicates_of(def_id).predicates.lower();

    let clause = Clause::Implies(where_clauses, trait_ref);
    Lrc::new(vec![clause])
}

pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
    if !tcx.features().rustc_attrs {
        return;
    }

    let mut visitor = ClauseDumper { tcx };
    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
}

struct ClauseDumper<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
    fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
        let def_id = self.tcx.hir.local_def_id(node_id);
        for attr in attrs {
            if attr.check_name("rustc_dump_program_clauses") {
                let clauses = self.tcx.program_clauses_for(def_id);
                for clause in &*clauses {
                    self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
                }
            }
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
    }

    fn visit_item(&mut self, item: &'tcx hir::Item) {
        self.process_attrs(item.id, &item.attrs);
        intravisit::walk_item(self, item);
    }

    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
        self.process_attrs(trait_item.id, &trait_item.attrs);
        intravisit::walk_trait_item(self, trait_item);
    }

    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
        self.process_attrs(impl_item.id, &impl_item.attrs);
        intravisit::walk_impl_item(self, impl_item);
    }

    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
        self.process_attrs(s.id, &s.attrs);
        intravisit::walk_struct_field(self, s);
    }
}
<commit_msg>Improve comments for Rule Implemented-From-Impl<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::hir::{self, ImplPolarity};
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::ty::{self, TyCtxt};
use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
use syntax::ast;
use rustc_data_structures::sync::Lrc;

trait Lower<T> {
    /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type.
    fn lower(&self) -> T;
}

impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
    fn lower(&self) -> Vec<U> {
        self.iter().map(|item| item.lower()).collect()
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::TraitPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::Implemented(*self)
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::ProjectionEq(*self)
    }
}

impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::Holds(self.lower())
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::RegionOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::RegionOutlives(*self)
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::TypeOutlives(*self)
    }
}

/// `ty::Binder` is used for wrapping a rustc construction possibly containing generic
/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things
/// in that leaf-form (i.e. `Holds(Implemented(Binder<TraitPredicate>))` in the previous
/// example), we model them with quantified goals, e.g. as for the previous example:
/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
/// `Binder<Holds(Implemented(TraitPredicate))>`.
///
/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we
/// can directly lower to a leaf goal instead of a quantified goal.
impl<'tcx, T> Lower<Goal<'tcx>> for ty::Binder<T>
    where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> + Copy
{
    fn lower(&self) -> Goal<'tcx> {
        match self.no_late_bound_regions() {
            Some(p) => p.lower().into(),
            None => Goal::Quantified(
                QuantifierKind::Universal,
                Box::new(self.map_bound(|p| p.lower().into()))
            ),
        }
    }
}

impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
    fn lower(&self) -> Goal<'tcx> {
        use rustc::ty::Predicate::*;

        match self {
            Trait(predicate) => predicate.lower(),
            RegionOutlives(predicate) => predicate.lower(),
            TypeOutlives(predicate) => predicate.lower(),
            Projection(predicate) => predicate.lower(),
            WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(),
            ObjectSafe(..) |
            ClosureKind(..) |
            Subtype(..) |
            ConstEvaluatable(..) => unimplemented!(),
        }
    }
}

crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
    let item = tcx.hir.expect_item(node_id);
    match item.node {
        hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),

        // FIXME: other constructions e.g. traits, associated types...
        _ => Lrc::new(vec![]),
    }
}

fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
        return Lrc::new(vec![]);
    }

    // Rule Implemented-From-Impl (see rustc guide)
    //
    // `impl<P0..Pn> Trait<A1..An> for A0 where WC { .. }`
    //
    // ```
    // forall<P0..Pn> {
    //   Implemented(A0: Trait<A1..An>) :- WC
    // }
    // ```

    let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
    // `Implemented(A0: Trait<A1..An>)`
    let trait_pred = ty::TraitPredicate { trait_ref }.lower();
     // `WC`
    let where_clauses = tcx.predicates_of(def_id).predicates.lower();

     // `Implemented(A0: Trait<A1..An>) :- WC`
    let clause = Clause::Implies(where_clauses, trait_pred);
    Lrc::new(vec![clause])
}

pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
    if !tcx.features().rustc_attrs {
        return;
    }

    let mut visitor = ClauseDumper { tcx };
    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
}

struct ClauseDumper<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
    fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
        let def_id = self.tcx.hir.local_def_id(node_id);
        for attr in attrs {
            if attr.check_name("rustc_dump_program_clauses") {
                let clauses = self.tcx.program_clauses_for(def_id);
                for clause in &*clauses {
                    self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
                }
            }
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
    }

    fn visit_item(&mut self, item: &'tcx hir::Item) {
        self.process_attrs(item.id, &item.attrs);
        intravisit::walk_item(self, item);
    }

    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
        self.process_attrs(trait_item.id, &trait_item.attrs);
        intravisit::walk_trait_item(self, trait_item);
    }

    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
        self.process_attrs(impl_item.id, &impl_item.attrs);
        intravisit::walk_impl_item(self, impl_item);
    }

    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
        self.process_attrs(s.id, &s.attrs);
        intravisit::walk_struct_field(self, s);
    }
}
<|endoftext|>


<commit_before>use super::collect_versions;
use crate::{config::Config, env::Env, file_saver::save_to_file, nameutil, version::Version};
use log::info;
use std::{collections::HashMap, fs::File, io::prelude::*};
use toml::{self, value::Table, Value};

pub fn generate(env: &Env) -> String {
    info!("Generating sys Cargo.toml for {}", env.config.library_name);

    let path = env.config.target_path.join("Cargo.toml");

    let mut toml_str = String::new();
    if let Ok(mut file) = File::open(&path) {
        file.read_to_string(&mut toml_str).unwrap();
    }
    let empty = toml_str.trim().is_empty();
    let mut root_table = toml::from_str(&toml_str).unwrap_or_else(|_| Table::new());
    let crate_name = get_crate_name(&env.config, &root_table);

    if empty {
        fill_empty(&mut root_table, env, &crate_name);
    }
    fill_in(&mut root_table, env);

    save_to_file(&path, env.config.make_backup, |w| {
        w.write_all(toml::to_string(&root_table).unwrap().as_bytes())
    });

    crate_name
}

fn fill_empty(root: &mut Table, env: &Env, crate_name: &str) {
    let package_name = nameutil::exported_crate_name(crate_name);

    {
        let package = upsert_table(root, "package");
        set_string(package, "name", package_name);
        set_string(package, "version", "0.0.1");
        set_string(
            package,
            "links",
            nameutil::crate_name(&env.config.library_name),
        );
    }

    {
        let lib = upsert_table(root, "lib");
        set_string(lib, "name", crate_name);
    }

    let deps = upsert_table(root, "dependencies");
    for ext_lib in &env.config.external_libraries {
        let ext_package = if ext_lib.crate_name == "cairo" {
            format!("{}-sys-rs", ext_lib.crate_name)
        } else if ext_lib.crate_name == "gdk_pixbuf" {
            "gdk-pixbuf-sys".into()
        } else {
            format!("{}-sys", ext_lib.crate_name)
        };
        let dep = upsert_table(deps, &*ext_package);
        if ext_lib.crate_name == "cairo" {
            set_string(dep, "git", "https://github.com/gtk-rs/cairo");
        } else if ext_package.starts_with("sourceview") {
            set_string(dep, "git", "https://github.com/gtk-rs/sourceview");
        } else {
            set_string(dep, "git", "https://github.com/gtk-rs/sys");
        }
    }
}

fn fill_in(root: &mut Table, env: &Env) {
    {
        let package = upsert_table(root, "package");
        set_string(package, "build", "build.rs");
        //set_string(package, "version", "0.2.0");
    }

    {
        let deps = upsert_table(root, "dependencies");
        set_string(deps, "libc", "0.2");
    }

    {
        let build_deps = upsert_table(root, "build-dependencies");
        set_string(build_deps, "system-deps", "1.3");
        unset(build_deps, "pkg-config");
    }

    {
        let dev_deps = upsert_table(root, "dev-dependencies");
        set_string(dev_deps, "shell-words", "0.1.0");
        set_string(dev_deps, "tempfile", "3");
        unset(dev_deps, "tempdir");
    }

    {
        let features = upsert_table(root, "features");
        let versions = collect_versions(env);
        versions.keys().fold(None::<Version>, |prev, &version| {
            let prev_array: Vec<Value> =
                get_feature_dependencies(version, prev, &env.config.feature_dependencies)
                    .iter()
                    .map(|s| Value::String(s.clone()))
                    .collect();
            features.insert(version.to_feature(), Value::Array(prev_array));
            Some(version)
        });
        features.insert("dox".to_string(), Value::Array(Vec::new()));
    }

    {
        let meta = upsert_table(root, "package");
        let meta = upsert_table(meta, "metadata");
        let meta = upsert_table(meta, "system-deps");

        let ns = env.namespaces.main();
        let lib_name = ns.package_name.as_ref().unwrap();

        let meta = upsert_table(meta, nameutil::lib_name_to_toml(lib_name));
        set_string(meta, "name", lib_name);
        set_string(meta, "version", env.config.min_cfg_version.to_string());

        let versions = upsert_table(meta, "feature-versions");
        env.namespaces
            .main()
            .versions
            .iter()
            .filter(|&&v| v > env.config.min_cfg_version)
            .for_each(|v| {
                set_string(versions, &v.to_feature(), v.to_string());
            });
    }

    {
        // Small trick to prevent having double quotes around it since toml doesn't like having '.'
        let docs_rs_metadata = upsert_table(root, "package");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "metadata");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "docs");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "rs");
        let mut docs_rs_features = env.config.docs_rs_features.clone();
        docs_rs_features.push("dox".to_owned());
        docs_rs_metadata.insert(
            "features".to_string(),
            Value::Array(
                docs_rs_features
                    .into_iter()
                    .map(Value::String)
                    .collect::<Vec<_>>(),
            ),
        );
    }
}

fn get_feature_dependencies(
    version: Version,
    prev_version: Option<Version>,
    feature_dependencies: &HashMap<Version, Vec<String>>,
) -> Vec<String> {
    let mut vec = Vec::with_capacity(10);
    if let Some(v) = prev_version {
        vec.push(v.to_feature());
    }
    if let Some(dependencies) = feature_dependencies.get(&version) {
        vec.extend_from_slice(dependencies);
    }
    vec
}

/// Returns the name of crate being currently generated.
fn get_crate_name(config: &Config, root: &Table) -> String {
    if let Some(&Value::Table(ref lib)) = root.get("lib") {
        if let Some(&Value::String(ref lib_name)) = lib.get("name") {
            //Converting don't needed as library target names cannot contain hyphens
            return lib_name.to_owned();
        }
    }
    if let Some(&Value::Table(ref package)) = root.get("package") {
        if let Some(&Value::String(ref package_name)) = package.get("name") {
            return nameutil::crate_name(package_name);
        }
    }
    return format!("{}_sys", nameutil::crate_name(&config.library_name));
}

fn set_string<S: Into<String>>(table: &mut Table, name: &str, new_value: S) {
    if let Some(v) = table.get_mut(name) {
        *v = Value::String(new_value.into());
        return;
    }
    table.insert(name.into(), Value::String(new_value.into()));
}

fn unset(table: &mut Table, name: &str) {
    table.remove(name);
}

fn upsert_table<S: Into<String>>(parent: &mut Table, name: S) -> &mut Table {
    if let Value::Table(ref mut table) = *parent
        .entry(name.into())
        .or_insert_with(|| Value::Table(toml::map::Map::new()))
    {
        table
    } else {
        unreachable!()
    }
}
<commit_msg>cargo_toml: set feature-versions for all versions<commit_after>use super::collect_versions;
use crate::{config::Config, env::Env, file_saver::save_to_file, nameutil, version::Version};
use log::info;
use std::{collections::HashMap, fs::File, io::prelude::*};
use toml::{self, value::Table, Value};

pub fn generate(env: &Env) -> String {
    info!("Generating sys Cargo.toml for {}", env.config.library_name);

    let path = env.config.target_path.join("Cargo.toml");

    let mut toml_str = String::new();
    if let Ok(mut file) = File::open(&path) {
        file.read_to_string(&mut toml_str).unwrap();
    }
    let empty = toml_str.trim().is_empty();
    let mut root_table = toml::from_str(&toml_str).unwrap_or_else(|_| Table::new());
    let crate_name = get_crate_name(&env.config, &root_table);

    if empty {
        fill_empty(&mut root_table, env, &crate_name);
    }
    fill_in(&mut root_table, env);

    save_to_file(&path, env.config.make_backup, |w| {
        w.write_all(toml::to_string(&root_table).unwrap().as_bytes())
    });

    crate_name
}

fn fill_empty(root: &mut Table, env: &Env, crate_name: &str) {
    let package_name = nameutil::exported_crate_name(crate_name);

    {
        let package = upsert_table(root, "package");
        set_string(package, "name", package_name);
        set_string(package, "version", "0.0.1");
        set_string(
            package,
            "links",
            nameutil::crate_name(&env.config.library_name),
        );
    }

    {
        let lib = upsert_table(root, "lib");
        set_string(lib, "name", crate_name);
    }

    let deps = upsert_table(root, "dependencies");
    for ext_lib in &env.config.external_libraries {
        let ext_package = if ext_lib.crate_name == "cairo" {
            format!("{}-sys-rs", ext_lib.crate_name)
        } else if ext_lib.crate_name == "gdk_pixbuf" {
            "gdk-pixbuf-sys".into()
        } else {
            format!("{}-sys", ext_lib.crate_name)
        };
        let dep = upsert_table(deps, &*ext_package);
        if ext_lib.crate_name == "cairo" {
            set_string(dep, "git", "https://github.com/gtk-rs/cairo");
        } else if ext_package.starts_with("sourceview") {
            set_string(dep, "git", "https://github.com/gtk-rs/sourceview");
        } else {
            set_string(dep, "git", "https://github.com/gtk-rs/sys");
        }
    }
}

fn fill_in(root: &mut Table, env: &Env) {
    {
        let package = upsert_table(root, "package");
        set_string(package, "build", "build.rs");
        //set_string(package, "version", "0.2.0");
    }

    {
        let deps = upsert_table(root, "dependencies");
        set_string(deps, "libc", "0.2");
    }

    {
        let build_deps = upsert_table(root, "build-dependencies");
        set_string(build_deps, "system-deps", "1.3");
        unset(build_deps, "pkg-config");
    }

    {
        let dev_deps = upsert_table(root, "dev-dependencies");
        set_string(dev_deps, "shell-words", "0.1.0");
        set_string(dev_deps, "tempfile", "3");
        unset(dev_deps, "tempdir");
    }

    {
        let features = upsert_table(root, "features");
        let versions = collect_versions(env);
        versions.keys().fold(None::<Version>, |prev, &version| {
            let prev_array: Vec<Value> =
                get_feature_dependencies(version, prev, &env.config.feature_dependencies)
                    .iter()
                    .map(|s| Value::String(s.clone()))
                    .collect();
            features.insert(version.to_feature(), Value::Array(prev_array));
            Some(version)
        });
        features.insert("dox".to_string(), Value::Array(Vec::new()));
    }

    {
        let meta = upsert_table(root, "package");
        let meta = upsert_table(meta, "metadata");
        let meta = upsert_table(meta, "system-deps");

        let ns = env.namespaces.main();
        let lib_name = ns.package_name.as_ref().unwrap();

        let meta = upsert_table(meta, nameutil::lib_name_to_toml(lib_name));
        set_string(meta, "name", lib_name);
        set_string(meta, "version", env.config.min_cfg_version.to_string());

        let versions = upsert_table(meta, "feature-versions");
        collect_versions(env)
            .keys()
            .filter(|&&v| v > env.config.min_cfg_version)
            .for_each(|v| {
                set_string(versions, &v.to_feature(), v.to_string());
            });
    }

    {
        // Small trick to prevent having double quotes around it since toml doesn't like having '.'
        let docs_rs_metadata = upsert_table(root, "package");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "metadata");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "docs");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "rs");
        let mut docs_rs_features = env.config.docs_rs_features.clone();
        docs_rs_features.push("dox".to_owned());
        docs_rs_metadata.insert(
            "features".to_string(),
            Value::Array(
                docs_rs_features
                    .into_iter()
                    .map(Value::String)
                    .collect::<Vec<_>>(),
            ),
        );
    }
}

fn get_feature_dependencies(
    version: Version,
    prev_version: Option<Version>,
    feature_dependencies: &HashMap<Version, Vec<String>>,
) -> Vec<String> {
    let mut vec = Vec::with_capacity(10);
    if let Some(v) = prev_version {
        vec.push(v.to_feature());
    }
    if let Some(dependencies) = feature_dependencies.get(&version) {
        vec.extend_from_slice(dependencies);
    }
    vec
}

/// Returns the name of crate being currently generated.
fn get_crate_name(config: &Config, root: &Table) -> String {
    if let Some(&Value::Table(ref lib)) = root.get("lib") {
        if let Some(&Value::String(ref lib_name)) = lib.get("name") {
            //Converting don't needed as library target names cannot contain hyphens
            return lib_name.to_owned();
        }
    }
    if let Some(&Value::Table(ref package)) = root.get("package") {
        if let Some(&Value::String(ref package_name)) = package.get("name") {
            return nameutil::crate_name(package_name);
        }
    }
    return format!("{}_sys", nameutil::crate_name(&config.library_name));
}

fn set_string<S: Into<String>>(table: &mut Table, name: &str, new_value: S) {
    if let Some(v) = table.get_mut(name) {
        *v = Value::String(new_value.into());
        return;
    }
    table.insert(name.into(), Value::String(new_value.into()));
}

fn unset(table: &mut Table, name: &str) {
    table.remove(name);
}

fn upsert_table<S: Into<String>>(parent: &mut Table, name: S) -> &mut Table {
    if let Value::Table(ref mut table) = *parent
        .entry(name.into())
        .or_insert_with(|| Value::Table(toml::map::Map::new()))
    {
        table
    } else {
        unreachable!()
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

use chrono::Datelike;

use convert::{ DateConvert, TimeConvert, WeekdayConvert };

pub fn validate(spec: &::contract::LeagueSpec) -> Vec<&'static str> {

    let mut result: Vec<&str> = Vec::new();

    let temp = (*spec).start_date;
    let start_date_opt = temp.to_naive_date_opt();

    //let start_date_opt = spec.start_date.to_naive_date_opt();
    let end_date_opt = spec.end_date.to_naive_date_opt();

    match (start_date_opt, end_date_opt) {
        (Some(start_date), Some(end_date)) => {
            // Check for a start and end dates starting on appropriate week days
            let good_start_date = spec.game_weekday.day.to_chrono_weekday() == start_date.weekday();
            let good_end_date = spec.game_weekday.day.to_chrono_weekday() == end_date.weekday();

            if !good_start_date {
                result.push("The start date does not occur on the day of the week.");
            }
            if !good_end_date {
                result.push("The end date does not occur on the start day of the week.");
            }
            if end_date.succ_opt().is_none() {
                result.push("The end date occurs too far in the future");
            }

            // Check that start date is before end date
            if start_date >= end_date {
                result.push("The start date must occur before end date.");
            }

        }
        (None, None) => {
            result.push("Start date is an invalid date");
            result.push("End date is an invalid date");
        }
        (None, _) => result.push("Start date is an invalid date"),
        (_, None) => result.push("End date is an invalid date")
    }

    // Make sure all locations are used at least once
    let mut used_locations: HashSet<String> = HashSet::new();
    for game_time in spec.game_weekday.game_times.iter() {
        for location_id in game_time.location_ids.iter() {
            used_locations.insert(location_id.clone());
        }
    }

    if used_locations.ne(&spec.locations.iter().map(|x| x.0.clone()).collect()) {
        result.push("Locations used in game_weekday are not equal to the list of locations");
    }

    // Make sure there's at least 2 teams
    if spec.teams.len() < 2 {
        result.push("There must be at least two teams");
    }

    // Make sure there's at least one location
    if spec.locations.len() == 0 {
        result.push("There must be at least one location");
    }

    // Make sure there's at least one time for each the weekday
    // Make sure there's at least one location for each time for the weekday
    let has_times = spec.game_weekday.game_times.len() > 0;
    let mut has_locations = true;
    for game_time in spec.game_weekday.game_times.iter() {
        has_locations = has_locations && game_time.location_ids.len() > 0;
    }

    if !has_times {
        result.push("There must be at least one game time for the game weekday");
    }
    if !has_locations {
        result.push("There must be at least one location id for each game time for the game weekday");
    }

    // Check that times don't repeat on a given day
    let mut has_time_repeats = false;
    let set: HashSet<usize> = spec.game_weekday.game_times.iter()
        .map(|time| time.time.hour as usize * 60 + time.time.min as usize).collect();
    has_time_repeats = has_time_repeats || set.len() != spec.game_weekday.game_times.len();

    if has_time_repeats {
        result.push("There cannot be repeating game times on a particular day");
    }

    // Check for all valid times
    let has_invalid_times = spec.game_weekday.game_times.iter()
        .map(|time| time.time.to_naive_time_opt())
        .any(|chrono_time_opt| chrono_time_opt.is_none());
    if has_invalid_times {
        result.push("All game times must be valid times");
    }

    // Check for a valid number of games per week given the team count
    let required_games_per_week = spec.teams.len() / 2;
    let actual_games_per_week = spec.game_weekday.game_times.iter()
        .fold(0, |sum, time| sum + time.location_ids.len());

    if required_games_per_week > actual_games_per_week {
        result.push(
            "There are less possible game location/time combinations per week than team matchups");
    }

    result

}
<commit_msg>fixed an error<commit_after>use std::collections::HashSet;

use chrono::Datelike;

use convert::{ DateConvert, TimeConvert, WeekdayConvert };

pub fn validate(spec: &::contract::LeagueSpec) -> Vec<&'static str> {

    let mut result: Vec<&str> = Vec::new();

    let temp = (*spec).start_date;
    let start_date_opt = temp.to_naive_date_opt();

    //let start_date_opt = spec.start_date.to_naive_date_opt();
    let end_date_opt = spec.end_date.to_naive_date_opt();

    match (start_date_opt, end_date_opt) {
        (Some(start_date), Some(end_date)) => {
            // Check for a start and end dates starting on appropriate week days
            let good_start_date = spec.game_weekday.day.to_chrono_weekday() == start_date.weekday();
            let good_end_date = spec.game_weekday.day.to_chrono_weekday() == end_date.weekday();

            if !good_start_date {
                result.push("The start date does not occur on the day of the week.");
            }
            if !good_end_date {
                result.push("The end date does not occur on the day of the week.");
            }
            if end_date.succ_opt().is_none() {
                result.push("The end date occurs too far in the future");
            }

            // Check that start date is before end date
            if start_date >= end_date {
                result.push("The start date must occur before end date.");
            }

        }
        (None, None) => {
            result.push("Start date is an invalid date");
            result.push("End date is an invalid date");
        }
        (None, _) => result.push("Start date is an invalid date"),
        (_, None) => result.push("End date is an invalid date")
    }

    // Make sure all locations are used at least once
    let mut used_locations: HashSet<String> = HashSet::new();
    for game_time in spec.game_weekday.game_times.iter() {
        for location_id in game_time.location_ids.iter() {
            used_locations.insert(location_id.clone());
        }
    }

    if used_locations.ne(&spec.locations.iter().map(|x| x.0.clone()).collect()) {
        result.push("Locations used in game_weekday are not equal to the list of locations");
    }

    // Make sure there's at least 2 teams
    if spec.teams.len() < 2 {
        result.push("There must be at least two teams");
    }

    // Make sure there's at least one location
    if spec.locations.len() == 0 {
        result.push("There must be at least one location");
    }

    // Make sure there's at least one time for each the weekday
    // Make sure there's at least one location for each time for the weekday
    let has_times = spec.game_weekday.game_times.len() > 0;
    let mut has_locations = true;
    for game_time in spec.game_weekday.game_times.iter() {
        has_locations = has_locations && game_time.location_ids.len() > 0;
    }

    if !has_times {
        result.push("There must be at least one game time for the game weekday");
    }
    if !has_locations {
        result.push("There must be at least one location id for each game time for the game weekday");
    }

    // Check that times don't repeat on a given day
    let mut has_time_repeats = false;
    let set: HashSet<usize> = spec.game_weekday.game_times.iter()
        .map(|time| time.time.hour as usize * 60 + time.time.min as usize).collect();
    has_time_repeats = has_time_repeats || set.len() != spec.game_weekday.game_times.len();

    if has_time_repeats {
        result.push("There cannot be repeating game times on a particular day");
    }

    // Check for all valid times
    let has_invalid_times = spec.game_weekday.game_times.iter()
        .map(|time| time.time.to_naive_time_opt())
        .any(|chrono_time_opt| chrono_time_opt.is_none());
    if has_invalid_times {
        result.push("All game times must be valid times");
    }

    // Check for a valid number of games per week given the team count
    let required_games_per_week = spec.teams.len() / 2;
    let actual_games_per_week = spec.game_weekday.game_times.iter()
        .fold(0, |sum, time| sum + time.location_ids.len());

    if required_games_per_week > actual_games_per_week {
        result.push(
            "There are less possible game location/time combinations per week than team matchups");
    }

    result

}
<|endoftext|>