<commit_before>//
// Copyright 2020 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Shared data structures and functionality for inter-node communication.

mod decodable;
mod encodable;
mod error;
pub mod handle;
mod receiver;
mod sender;

pub use decodable::Decodable;
use either::Either;
pub use encodable::Encodable;
pub use error::OakError;
use handle::{ReadHandle, WriteHandle};
pub use oak_abi::{Handle, OakStatus};
pub use receiver::Receiver;
pub use sender::Sender;

/// A simple holder for bytes + handles, using internally owned buffers.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Message {
    pub bytes: Vec<u8>,
    pub handles: Vec<Handle>,
}

/// Implementation of [`Encodable`] for [`Either`] that encodes the variant (0 or 1) in the first
/// byte of the resulting [`Message`].
impl<L: Encodable, R: Encodable> Encodable for Either<L, R> {
    fn encode(&self) -> Result<Message, OakError> {
        let (variant, mut inner) = match self {
            // Left variant == 0.
            Either::Left(m) => (0, m.encode()?),
            // Right variant == 1.
            Either::Right(m) => (1, m.encode()?),
        };
        // Insert the variant byte as the beginning of the message bytes, and leave handles as they
        // are.
        inner.bytes.insert(0, variant);
        Ok(inner)
    }
}

/// Implementation of [`Decodable`] for [`Either`] that decodes the variant (0 or 1) from the first
/// byte of the provided [`Message`].
impl<L: Decodable, R: Decodable> Decodable for Either<L, R> {
    fn decode(message: &Message) -> Result<Self, OakError> {
        match message.bytes.get(0) {
            // Left variant == 0.
            Some(0) => {
                let inner_message = Message {
                    bytes: message.bytes[1..].to_vec(),
                    handles: message.handles.clone(),
                };
                Ok(Either::Left(L::decode(&inner_message)?))
            }
            // Right variant == 1.
            Some(1) => {
                let inner_message = Message {
                    bytes: message.bytes[1..].to_vec(),
                    handles: message.handles.clone(),
                };
                Ok(Either::Right(R::decode(&inner_message)?))
            }
            // Invalid variant, or not enough bytes.
            _ => Err(OakStatus::ErrInvalidArgs.into()),
        }
    }
}

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

    #[test]
    fn either_round_trip() {
        type T = Either<u32, u32>;

        {
            // This test case is just a baseline reference for the ones below, to spell out the
            // protobuf encoding of the inner object.
            let original = 1988;
            let encoded = original.encode().unwrap();
            assert_eq!(
                Message {
                    bytes: vec![8, 196, 15],
                    handles: vec![]
                },
                encoded
            );
            let decoded = u32::decode(&encoded).unwrap();
            assert_eq!(original, decoded);
        }

        {
            let original = T::Left(1988);
            let encoded = original.encode().unwrap();
            // Note the first byte corresponds to the variant == 0.
            assert_eq!(
                Message {
                    bytes: vec![0, 8, 196, 15],
                    handles: vec![]
                },
                encoded
            );
            let decoded = T::decode(&encoded).unwrap();
            assert_eq!(original, decoded);
        }

        {
            let original = T::Right(1988);
            let encoded = original.encode().unwrap();
            // Note the first byte corresponds to the variant == 1.
            assert_eq!(
                Message {
                    bytes: vec![1, 8, 196, 15],
                    handles: vec![]
                },
                encoded
            );
            let decoded = T::decode(&encoded).unwrap();
            assert_eq!(original, decoded);
        }

        {
            let invalid_variant = 42;
            let encoded_invalid = Message {
                bytes: vec![invalid_variant, 8, 196, 15],
                handles: vec![],
            };
            assert_matches!(
                T::decode(&encoded_invalid),
                Err(OakError::OakStatus(OakStatus::ErrInvalidArgs))
            );
        }
    }
}
<commit_msg>Define InitWrapper message (#1659)<commit_after>//
// Copyright 2020 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Shared data structures and functionality for inter-node communication.

mod decodable;
mod encodable;
mod error;
pub mod handle;
mod receiver;
mod sender;

pub use decodable::Decodable;
use either::Either;
pub use encodable::Encodable;
pub use error::OakError;
use handle::{ReadHandle, WriteHandle};
pub use oak_abi::{Handle, OakStatus};
pub use receiver::Receiver;
pub use sender::Sender;

/// A simple holder for bytes + handles, using internally owned buffers.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Message {
    pub bytes: Vec<u8>,
    pub handles: Vec<Handle>,
}

/// Implementation of [`Encodable`] for [`Either`] that encodes the variant (0 or 1) in the first
/// byte of the resulting [`Message`].
impl<L: Encodable, R: Encodable> Encodable for Either<L, R> {
    fn encode(&self) -> Result<Message, OakError> {
        let (variant, mut inner) = match self {
            // Left variant == 0.
            Either::Left(m) => (0, m.encode()?),
            // Right variant == 1.
            Either::Right(m) => (1, m.encode()?),
        };
        // Insert the variant byte as the beginning of the message bytes, and leave handles as they
        // are.
        inner.bytes.insert(0, variant);
        Ok(inner)
    }
}

/// Implementation of [`Decodable`] for [`Either`] that decodes the variant (0 or 1) from the first
/// byte of the provided [`Message`].
impl<L: Decodable, R: Decodable> Decodable for Either<L, R> {
    fn decode(message: &Message) -> Result<Self, OakError> {
        match message.bytes.get(0) {
            // Left variant == 0.
            Some(0) => {
                let inner_message = Message {
                    bytes: message.bytes[1..].to_vec(),
                    handles: message.handles.clone(),
                };
                Ok(Either::Left(L::decode(&inner_message)?))
            }
            // Right variant == 1.
            Some(1) => {
                let inner_message = Message {
                    bytes: message.bytes[1..].to_vec(),
                    handles: message.handles.clone(),
                };
                Ok(Either::Right(R::decode(&inner_message)?))
            }
            // Invalid variant, or not enough bytes.
            _ => Err(OakStatus::ErrInvalidArgs.into()),
        }
    }
}

/// A wrapper struct that holds an init message, plus the handle of a channel from which to read
/// command messages. This is useful for patterns in which an Oak node needs some data at
/// initialization time, but then handles commands of a different type and possibly coming from a
/// different channel, to be processed in an event-loop pattern.
#[derive(Clone, Debug, PartialEq)]
pub struct InitWrapper<Init, Command: Decodable> {
    init: Init,
    command_receiver: Receiver<Command>,
}

/// Implementation of [`Encodable`] for [`InitWrapper`] that encodes the handle of the command
/// receiver channel in the first handle of the resulting [`Message`].
impl<Init: Encodable, Command: Encodable + Decodable> Encodable for InitWrapper<Init, Command> {
    fn encode(&self) -> Result<Message, OakError> {
        let mut init_message = self.init.encode()?;
        // Insert the handle of the command receiver handle at the beginning of the handle list
        // (i.e. at position 0).
        init_message
            .handles
            .insert(0, self.command_receiver.handle.handle);
        Ok(init_message)
    }
}

/// Implementation of [`Decodable`] for [`InitWrapper`] that decodes the handle of the command
/// receiver channel from the first handle of the provided [`Message`].
impl<Init: Decodable, Command: Decodable> Decodable for InitWrapper<Init, Command> {
    fn decode(message: &Message) -> Result<Self, OakError> {
        match message.handles.get(0) {
            Some(handle) => {
                let init_message = Message {
                    bytes: message.bytes.clone(),
                    handles: message.handles[1..].to_vec(),
                };
                Ok(Self {
                    init: Init::decode(&init_message)?,
                    command_receiver: Receiver::new(ReadHandle::from(*handle)),
                })
            }
            _ => Err(OakStatus::ErrInvalidArgs.into()),
        }
    }
}

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

    #[derive(Debug, PartialEq)]
    struct TestStruct {
        receiver_0: Receiver<()>,
        field_0: u8,
        receiver_1: Receiver<()>,
        field_1: u8,
    }

    impl Encodable for TestStruct {
        fn encode(&self) -> Result<Message, OakError> {
            Ok(Message {
                bytes: vec![self.field_0, self.field_1],
                handles: vec![self.receiver_0.handle.handle, self.receiver_1.handle.handle],
            })
        }
    }
    impl Decodable for TestStruct {
        fn decode(message: &Message) -> Result<Self, OakError> {
            match (message.bytes.as_slice(), message.handles.as_slice()) {
                ([byte_0, byte_1], [handle_0, handle_1]) => Ok(TestStruct {
                    receiver_0: Receiver::from(ReadHandle::from(*handle_0)),
                    field_0: *byte_0,
                    receiver_1: Receiver::from(ReadHandle::from(*handle_1)),
                    field_1: *byte_1,
                }),
                _ => panic!("invalid Message for TestStruct"),
            }
        }
    }

    #[test]
    fn test_struct_round_trip() {
        let original = TestStruct {
            receiver_0: Receiver::from(ReadHandle::from(100)),
            field_0: 10,
            receiver_1: Receiver::from(ReadHandle::from(101)),
            field_1: 11,
        };
        let encoded = original.encode().unwrap();
        assert_eq!(
            Message {
                bytes: vec![10, 11],
                handles: vec![100, 101],
            },
            encoded
        );
        let decoded = TestStruct::decode(&encoded).unwrap();
        assert_eq!(original, decoded);
    }

    #[test]
    fn either_round_trip() {
        type T = Either<u32, TestStruct>;

        {
            // This test case is just a baseline reference for the ones below, to spell out the
            // protobuf encoding of the inner object.
            let original = 1988;
            let encoded = original.encode().unwrap();
            assert_eq!(
                Message {
                    bytes: vec![8, 196, 15],
                    handles: vec![],
                },
                encoded
            );
            let decoded = u32::decode(&encoded).unwrap();
            assert_eq!(original, decoded);
        }

        {
            let original = T::Left(1988);
            let encoded = original.encode().unwrap();
            // Note the first byte corresponds to the variant == 0.
            assert_eq!(
                Message {
                    bytes: vec![0, 8, 196, 15],
                    handles: vec![],
                },
                encoded
            );
            let decoded = T::decode(&encoded).unwrap();
            assert_eq!(original, decoded);
        }

        {
            let original = T::Right(TestStruct {
                receiver_0: Receiver::from(ReadHandle::from(100)),
                field_0: 10,
                receiver_1: Receiver::from(ReadHandle::from(101)),
                field_1: 11,
            });
            let encoded = original.encode().unwrap();
            // Note the first byte corresponds to the variant == 1.
            assert_eq!(
                Message {
                    bytes: vec![1, 10, 11],
                    handles: vec![100, 101],
                },
                encoded
            );
            let decoded = T::decode(&encoded).unwrap();
            assert_eq!(original, decoded);
        }

        {
            let invalid_variant = 42;
            let encoded_invalid = Message {
                bytes: vec![invalid_variant, 8, 196, 15],
                handles: vec![],
            };
            assert_matches!(
                T::decode(&encoded_invalid),
                Err(OakError::OakStatus(OakStatus::ErrInvalidArgs))
            );
        }
    }

    #[test]
    fn init_wrapper_round_trip() {
        type T = InitWrapper<TestStruct, ()>;

        {
            let original = T {
                init: TestStruct {
                    receiver_0: Receiver::from(ReadHandle::from(100)),
                    field_0: 10,
                    receiver_1: Receiver::from(ReadHandle::from(101)),
                    field_1: 11,
                },
                command_receiver: Receiver::from(ReadHandle::from(123)),
            };
            let encoded = original.encode().unwrap();
            // Note the handle list contains the command receiver handle at the beginning.
            assert_eq!(
                Message {
                    bytes: vec![10, 11],
                    handles: vec![123, 100, 101],
                },
                encoded
            );
            let decoded = T::decode(&encoded).unwrap();
            assert_eq!(original, decoded);
        }
    }
}
<|endoftext|>


<commit_before>use parser::combinators::{Parser, StrParser, ParseTo, Consumer, string, character};
use self::Token::{LParen, RParen, Whitespace, Identifier};

#[derive(Copy, Clone, Eq, Hash, Ord, PartialOrd, Debug)]
pub enum Token<'a> {
    LParen,
    RParen,
    Whitespace,
    Identifier(&'a str),
}

impl<'a,'b> PartialEq<Token<'b>> for Token<'a> {
    fn eq(&self, rhs: &Token<'b>) -> bool {
        match (*self, *rhs) {
            (LParen, LParen)                       => true,
            (RParen, RParen)                       => true,
            (Whitespace, Whitespace)               => true,
            (Identifier(ref x), Identifier(ref y)) => x == y,
            _                                      => false
        }
    }
}

pub trait LexerConsumer<D> where D: for<'a> Consumer<Token<'a>> {
    fn accept<L>(self, lexer: L) where L: for<'a> ParseTo<&'a str,D>;
}

fn mk_identifier<'a>(s: &'a str) -> Token<'a> { Identifier(s) }

#[allow(non_snake_case)]
pub fn lexer<C,D>(consumer: C) where C: LexerConsumer<D>, D: for<'a> Consumer<Token<'a>> {
    let LPAREN = string("(").map(|_| LParen);
    let RPAREN = string(")").map(|_| RParen);
    let WHITESPACE = character(char::is_whitespace).map(|_| Whitespace);
    let IDENTIFIER = character(char::is_alphabetic).and_then(character(char::is_alphanumeric).star())
                                                   .buffer().map(mk_identifier);
    let TOKEN = LPAREN.or_else(RPAREN).or_else(WHITESPACE).or_else(IDENTIFIER);
    consumer.accept(TOKEN.star())
}

#[test]
fn test_lexer() {
    impl<'a> Consumer<Token<'a>> for Vec<Token<'static>> {
        fn accept(&mut self, token: Token<'a>) {
            assert_eq!(self.remove(0), token);
        }
    }
    struct TestConsumer;
    impl<'a> LexerConsumer<Vec<Token<'static>>> for TestConsumer {
        fn accept<P>(self, mut lex: P) where P: ParseTo<&'a str,Vec<Token<'static>>> {
            let mut tokens = vec![LParen, Identifier("a123"), Whitespace, Whitespace, Identifier("bcd"), RParen];
            lex.push_to("(a123  bcd)", &mut tokens);
            assert_eq!(tokens, []);
        }
    }
    lexer(TestConsumer);
}

#[test]
fn test_partial_eq() {
    use std::fmt::Debug;
    fn foo<T,U>(lhs: T, rhs: U) where T: Debug+PartialEq<U>, U: Debug{
        assert_eq!(lhs, rhs)
    }
    fn bar<'b,T>(lhs: T, rhs: Token<'b>) where T: Debug+for<'a> PartialEq<Token<'a>> {
        foo(lhs, rhs)
    }
    let hi = String::from("hi");
    bar(Identifier("hi"),Identifier(&*hi));
    bar(Identifier(&*hi),Identifier("hi"));
}
<commit_msg>Implemented From<Token<'a>> for String.<commit_after>use parser::combinators::{Parser, StrParser, ParseTo, Consumer, string, character};
use self::Token::{LParen, RParen, Whitespace, Identifier};

#[derive(Copy, Clone, Eq, Hash, Ord, PartialOrd, Debug)]
pub enum Token<'a> {
    LParen,
    RParen,
    Whitespace,
    Identifier(&'a str),
}

impl<'a,'b> PartialEq<Token<'b>> for Token<'a> {
    fn eq(&self, rhs: &Token<'b>) -> bool {
        match (*self, *rhs) {
            (LParen, LParen)                       => true,
            (RParen, RParen)                       => true,
            (Whitespace, Whitespace)               => true,
            (Identifier(ref x), Identifier(ref y)) => x == y,
            _                                      => false
        }
    }
}

impl<'a> From<Token<'a>> for String {
    fn from(tok: Token<'a>) -> String {
        String::from(match tok {
            LParen => "(",
            RParen => ")",
            Whitespace => "<space>",
            Identifier(x) => x,
        })
    }
}

pub trait LexerConsumer<D> where D: for<'a> Consumer<Token<'a>> {
    fn accept<L>(self, lexer: L) where L: for<'a> ParseTo<&'a str,D>;
}

fn mk_identifier<'a>(s: &'a str) -> Token<'a> { Identifier(s) }

#[allow(non_snake_case)]
pub fn lexer<C,D>(consumer: C) where C: LexerConsumer<D>, D: for<'a> Consumer<Token<'a>> {
    let LPAREN = string("(").map(|_| LParen);
    let RPAREN = string(")").map(|_| RParen);
    let WHITESPACE = character(char::is_whitespace).map(|_| Whitespace);
    let IDENTIFIER = character(char::is_alphabetic).and_then(character(char::is_alphanumeric).star())
                                                   .buffer().map(mk_identifier);
    let TOKEN = LPAREN.or_else(RPAREN).or_else(WHITESPACE).or_else(IDENTIFIER);
    consumer.accept(TOKEN.star())
}

#[test]
fn test_lexer() {
    impl<'a> Consumer<Token<'a>> for Vec<Token<'static>> {
        fn accept(&mut self, token: Token<'a>) {
            assert_eq!(self.remove(0), token);
        }
    }
    struct TestConsumer;
    impl<'a> LexerConsumer<Vec<Token<'static>>> for TestConsumer {
        fn accept<P>(self, mut lex: P) where P: ParseTo<&'a str,Vec<Token<'static>>> {
            let mut tokens = vec![LParen, Identifier("a123"), Whitespace, Whitespace, Identifier("bcd"), RParen];
            lex.push_to("(a123  bcd)", &mut tokens);
            assert_eq!(tokens, []);
        }
    }
    lexer(TestConsumer);
}

#[test]
fn test_partial_eq() {
    use std::fmt::Debug;
    fn foo<T,U>(lhs: T, rhs: U) where T: Debug+PartialEq<U>, U: Debug{
        assert_eq!(lhs, rhs)
    }
    fn bar<'b,T>(lhs: T, rhs: Token<'b>) where T: Debug+for<'a> PartialEq<Token<'a>> {
        foo(lhs, rhs)
    }
    let hi = String::from("hi");
    bar(Identifier("hi"),Identifier(&*hi));
    bar(Identifier(&*hi),Identifier("hi"));
}
<|endoftext|>


<commit_before>use crate::{prelude::SignedBlock, serializer::*};
use std::convert::{TryFrom, TryInto};
use std::io::{self, Cursor, Error, Read};

#[repr(u8)]
pub enum MsgType {
    Error = 0,
    GetBlock = 1,
}

pub enum MsgRequest {
    GetBlock(u64), // height
}

impl MsgRequest {
    pub fn serialize(&self, bytes: &mut Vec<u8>) {
        match self {
            MsgRequest::GetBlock(height) => {
                bytes.push(MsgType::GetBlock as u8);
                bytes.push_u64(*height);
            }
        }
    }

    pub fn deserialize(cursor: &mut Cursor<&[u8]>) -> io::Result<Self> {
        let tag = cursor.take_u8()?;
        match tag {
            t if t == MsgType::GetBlock as u8 => {
                let height = cursor.take_u64()?;
                Ok(MsgRequest::GetBlock(height))
            }
            _ => Err(Error::new(
                io::ErrorKind::InvalidData,
                "invalid msg request",
            )),
        }
    }
}

#[repr(u16)]
pub enum ErrorKind {
    UnknownError = 0,
    InvalidHeight = 1,
}

impl TryFrom<u16> for ErrorKind {
    type Error = Error;

    fn try_from(value: u16) -> Result<ErrorKind, Error> {
        match value {
            e if e == ErrorKind::UnknownError as u16 => Ok(ErrorKind::UnknownError),
            e if e == ErrorKind::InvalidHeight as u16 => Ok(ErrorKind::InvalidHeight),
            _ => Err(Error::new(io::ErrorKind::InvalidData, "unknown error kind")),
        }
    }
}

pub enum MsgResponse {
    Error(ErrorKind, Option<String>), // code, message
    GetBlock(SignedBlock),
}

impl MsgResponse {
    pub fn serialize(self) -> Vec<u8> {
        match self {
            MsgResponse::Error(code, msg) => match msg {
                Some(msg) => {
                    let mut buf = Vec::with_capacity(3 + msg.len());
                    buf.push(MsgType::Error as u8);
                    buf.push_u16(code as u16);
                    buf.push_bytes(msg.as_bytes());
                    buf
                }
                None => {
                    let mut buf = Vec::with_capacity(7);
                    buf.push(MsgType::Error as u8);
                    buf.push_u16(code as u16);
                    buf.push_bytes(&[]);
                    buf
                }
            },
            MsgResponse::GetBlock(block) => {
                let mut buf = Vec::with_capacity(1_048_576);
                buf.push(MsgType::GetBlock as u8);
                block.encode_with_tx(&mut buf);
                buf
            }
        }
    }

    pub fn deserialize(cursor: &mut Cursor<&[u8]>) -> io::Result<Self> {
        let tag = cursor.take_u8()?;
        match tag {
            t if t == MsgType::Error as u8 => {
                let kind = cursor.take_u16()?.try_into()?;
                let msg = {
                    let mut buf = Vec::with_capacity(1024);
                    let read = cursor.read_to_end(&mut buf)?;
                    if read > 0 {
                        Some(String::from_utf8_lossy(&buf).into_owned())
                    } else {
                        None
                    }
                };
                Ok(MsgResponse::Error(kind, msg))
            }
            t if t == MsgType::GetBlock as u8 => {
                let block = SignedBlock::decode_with_tx(cursor)
                    .ok_or_else(|| Error::from(io::ErrorKind::UnexpectedEof))?;
                Ok(MsgResponse::GetBlock(block))
            }
            _ => Err(Error::new(
                io::ErrorKind::InvalidData,
                "invalid msg response",
            )),
        }
    }
}
<commit_msg>Serializing MsgRequest's is now consistent with responses<commit_after>use crate::{prelude::SignedBlock, serializer::*};
use std::convert::{TryFrom, TryInto};
use std::io::{self, Cursor, Error, Read};

#[repr(u8)]
pub enum MsgType {
    Error = 0,
    GetBlock = 1,
}

pub enum MsgRequest {
    GetBlock(u64), // height
}

impl MsgRequest {
    pub fn serialize(self) -> Vec<u8> {
        match self {
            MsgRequest::GetBlock(height) => {
                let mut buf = Vec::with_capacity(9);
                buf.push(MsgType::GetBlock as u8);
                buf.push_u64(height);
                buf
            }
        }
    }

    pub fn deserialize(cursor: &mut Cursor<&[u8]>) -> io::Result<Self> {
        let tag = cursor.take_u8()?;
        match tag {
            t if t == MsgType::GetBlock as u8 => {
                let height = cursor.take_u64()?;
                Ok(MsgRequest::GetBlock(height))
            }
            _ => Err(Error::new(
                io::ErrorKind::InvalidData,
                "invalid msg request",
            )),
        }
    }
}

#[derive(Copy, Clone, Debug)]
#[repr(u16)]
pub enum ErrorKind {
    UnknownError = 0,
    InvalidHeight = 1,
}

impl TryFrom<u16> for ErrorKind {
    type Error = Error;

    fn try_from(value: u16) -> Result<ErrorKind, Error> {
        match value {
            e if e == ErrorKind::UnknownError as u16 => Ok(ErrorKind::UnknownError),
            e if e == ErrorKind::InvalidHeight as u16 => Ok(ErrorKind::InvalidHeight),
            _ => Err(Error::new(io::ErrorKind::InvalidData, "unknown error kind")),
        }
    }
}

#[derive(Clone, Debug)]
pub enum MsgResponse {
    Error(ErrorKind, Option<String>), // code, message
    GetBlock(SignedBlock),
}

impl MsgResponse {
    pub fn serialize(self) -> Vec<u8> {
        match self {
            MsgResponse::Error(code, msg) => match msg {
                Some(msg) => {
                    let mut buf = Vec::with_capacity(3 + msg.len());
                    buf.push(MsgType::Error as u8);
                    buf.push_u16(code as u16);
                    buf.push_bytes(msg.as_bytes());
                    buf
                }
                None => {
                    let mut buf = Vec::with_capacity(7);
                    buf.push(MsgType::Error as u8);
                    buf.push_u16(code as u16);
                    buf.push_bytes(&[]);
                    buf
                }
            },
            MsgResponse::GetBlock(block) => {
                let mut buf = Vec::with_capacity(1_048_576);
                buf.push(MsgType::GetBlock as u8);
                block.encode_with_tx(&mut buf);
                buf
            }
        }
    }

    pub fn deserialize(cursor: &mut Cursor<&[u8]>) -> io::Result<Self> {
        let tag = cursor.take_u8()?;
        match tag {
            t if t == MsgType::Error as u8 => {
                let kind = cursor.take_u16()?.try_into()?;
                let msg = {
                    let mut buf = Vec::with_capacity(1024);
                    let read = cursor.read_to_end(&mut buf)?;
                    if read > 0 {
                        Some(String::from_utf8_lossy(&buf).into_owned())
                    } else {
                        None
                    }
                };
                Ok(MsgResponse::Error(kind, msg))
            }
            t if t == MsgType::GetBlock as u8 => {
                let block = SignedBlock::decode_with_tx(cursor)
                    .ok_or_else(|| Error::from(io::ErrorKind::UnexpectedEof))?;
                Ok(MsgResponse::GetBlock(block))
            }
            _ => Err(Error::new(
                io::ErrorKind::InvalidData,
                "invalid msg response",
            )),
        }
    }
}
<|endoftext|>


<commit_before>export fold;
export fold_crate, fold_mod, fold_fn;
export default_seq_fold;
export default_seq_fold_crate;
export default_seq_fold_item;
export default_seq_fold_mod;
export default_seq_fold_nmod;
export default_seq_fold_fn;
export default_seq_fold_const;
export default_seq_fold_enum;
export default_seq_fold_res;
export default_seq_fold_iface;
export default_seq_fold_impl;
export default_seq_fold_type;
export default_par_fold;
export default_par_fold_mod;
export default_par_fold_nmod;
export default_any_fold;
export default_any_fold_mod;
export default_any_fold_nmod;

enum fold<T> = t<T>;

type fold_crate<T> = fn~(fold: fold<T>, doc: doc::cratedoc) -> doc::cratedoc;
type fold_item<T> = fn~(fold: fold<T>, doc: doc::itemdoc) -> doc::itemdoc;
type fold_mod<T> = fn~(fold: fold<T>, doc: doc::moddoc) -> doc::moddoc;
type fold_nmod<T> = fn~(fold: fold<T>, doc: doc::nmoddoc) -> doc::nmoddoc;
type fold_fn<T> = fn~(fold: fold<T>, doc: doc::fndoc) -> doc::fndoc;
type fold_const<T> = fn~(fold: fold<T>, doc: doc::constdoc) -> doc::constdoc;
type fold_enum<T> = fn~(fold: fold<T>, doc: doc::enumdoc) -> doc::enumdoc;
type fold_res<T> = fn~(fold: fold<T>, doc: doc::resdoc) -> doc::resdoc;
type fold_iface<T> = fn~(fold: fold<T>, doc: doc::ifacedoc) -> doc::ifacedoc;
type fold_impl<T> = fn~(fold: fold<T>, doc: doc::impldoc) -> doc::impldoc;
type fold_type<T> = fn~(fold: fold<T>, doc: doc::tydoc) -> doc::tydoc;

type t<T> = {
    ctxt: T,
    fold_crate: fold_crate<T>,
    fold_item: fold_item<T>,
    fold_mod: fold_mod<T>,
    fold_nmod: fold_nmod<T>,
    fold_fn: fold_fn<T>,
    fold_const: fold_const<T>,
    fold_enum: fold_enum<T>,
    fold_res: fold_res<T>,
    fold_iface: fold_iface<T>,
    fold_impl: fold_impl<T>,
    fold_type: fold_type<T>
};

// This exists because fn types don't infer correctly as record
// initializers, but they do as function arguments
fn mk_fold<T:copy>(
    ctxt: T,
    fold_crate: fold_crate<T>,
    fold_item: fold_item<T>,
    fold_mod: fold_mod<T>,
    fold_nmod: fold_nmod<T>,
    fold_fn: fold_fn<T>,
    fold_const: fold_const<T>,
    fold_enum: fold_enum<T>,
    fold_res: fold_res<T>,
    fold_iface: fold_iface<T>,
    fold_impl: fold_impl<T>,
    fold_type: fold_type<T>
) -> fold<T> {
    fold({
        ctxt: ctxt,
        fold_crate: fold_crate,
        fold_item: fold_item,
        fold_mod: fold_mod,
        fold_nmod: fold_nmod,
        fold_fn: fold_fn,
        fold_const: fold_const,
        fold_enum: fold_enum,
        fold_res: fold_res,
        fold_iface: fold_iface,
        fold_impl: fold_impl,
        fold_type: fold_type
    })
}

fn default_any_fold<T:send>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_any_fold_mod(f, d)},
        {|f, d| default_any_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_seq_fold<T:copy>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_seq_fold_mod(f, d)},
        {|f, d| default_seq_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_par_fold<T:send>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_par_fold_mod(f, d)},
        {|f, d| default_par_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_seq_fold_crate<T>(
    fold: fold<T>,
    doc: doc::cratedoc
) -> doc::cratedoc {
    {
        topmod: fold.fold_mod(fold, doc.topmod)
    }
}

fn default_seq_fold_item<T>(
    _fold: fold<T>,
    doc: doc::itemdoc
) -> doc::itemdoc {
    doc
}

fn default_any_fold_mod<T:send>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::anymap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_seq_fold_mod<T>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::seqmap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_par_fold_mod<T:send>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::parmap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_any_fold_nmod<T:send>(
    fold: fold<T>,
    doc: doc::nmoddoc
) -> doc::nmoddoc {
    {
        item: fold.fold_item(fold, doc.item),
        fns: util::anymap(doc.fns) {|fndoc|
            fold.fold_fn(fold, fndoc)
        }
        with doc
    }
}

fn default_seq_fold_nmod<T>(
    fold: fold<T>,
    doc: doc::nmoddoc
) -> doc::nmoddoc {
    {
        item: fold.fold_item(fold, doc.item),
        fns: util::seqmap(doc.fns) {|fndoc|
            fold.fold_fn(fold, fndoc)
        }
        with doc
    }
}

fn default_par_fold_nmod<T:send>(
    fold: fold<T>,
    doc: doc::nmoddoc
) -> doc::nmoddoc {
    {
        item: fold.fold_item(fold, doc.item),
        fns: util::parmap(doc.fns) {|fndoc|
            fold.fold_fn(fold, fndoc)
        }
        with doc
    }
}

fn fold_itemtag<T>(fold: fold<T>, doc: doc::itemtag) -> doc::itemtag {
    alt doc {
      doc::modtag(moddoc) {
        doc::modtag(fold.fold_mod(fold, moddoc))
      }
      doc::nmodtag(nmoddoc) {
        doc::nmodtag(fold.fold_nmod(fold, nmoddoc))
      }
      doc::fntag(fndoc) {
        doc::fntag(fold.fold_fn(fold, fndoc))
      }
      doc::consttag(constdoc) {
        doc::consttag(fold.fold_const(fold, constdoc))
      }
      doc::enumtag(enumdoc) {
        doc::enumtag(fold.fold_enum(fold, enumdoc))
      }
      doc::restag(resdoc) {
        doc::restag(fold.fold_res(fold, resdoc))
      }
      doc::ifacetag(ifacedoc) {
        doc::ifacetag(fold.fold_iface(fold, ifacedoc))
      }
      doc::impltag(impldoc) {
        doc::impltag(fold.fold_impl(fold, impldoc))
      }
      doc::tytag(tydoc) {
        doc::tytag(fold.fold_type(fold, tydoc))
      }
    }
}

fn default_seq_fold_fn<T>(
    fold: fold<T>,
    doc: doc::fndoc
) -> doc::fndoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_const<T>(
    fold: fold<T>,
    doc: doc::constdoc
) -> doc::constdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_enum<T>(
    fold: fold<T>,
    doc: doc::enumdoc
) -> doc::enumdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_res<T>(
    fold: fold<T>,
    doc: doc::resdoc
) -> doc::resdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_iface<T>(
    fold: fold<T>,
    doc: doc::ifacedoc
) -> doc::ifacedoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_impl<T>(
    fold: fold<T>,
    doc: doc::impldoc
) -> doc::impldoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_type<T>(
    fold: fold<T>,
    doc: doc::tydoc
) -> doc::tydoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

#[test]
fn default_fold_should_produce_same_doc() {
    let source = "mod a { fn b() { } mod c { fn d() { } } }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_fold_should_produce_same_consts() {
    let source = "const a: int = 0;";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_fold_should_produce_same_enums() {
    let source = "enum a { b }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_parallel_fold_should_produce_same_doc() {
    let source = "mod a { fn b() { } mod c { fn d() { } } }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_par_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}
<commit_msg>rustdoc: Remove some unused exports<commit_after>export fold;
export default_seq_fold;
export default_seq_fold_crate;
export default_seq_fold_item;
export default_seq_fold_mod;
export default_seq_fold_nmod;
export default_seq_fold_fn;
export default_seq_fold_const;
export default_seq_fold_enum;
export default_seq_fold_res;
export default_seq_fold_iface;
export default_seq_fold_impl;
export default_seq_fold_type;
export default_par_fold;
export default_par_fold_mod;
export default_par_fold_nmod;
export default_any_fold;
export default_any_fold_mod;
export default_any_fold_nmod;

enum fold<T> = t<T>;

type fold_crate<T> = fn~(fold: fold<T>, doc: doc::cratedoc) -> doc::cratedoc;
type fold_item<T> = fn~(fold: fold<T>, doc: doc::itemdoc) -> doc::itemdoc;
type fold_mod<T> = fn~(fold: fold<T>, doc: doc::moddoc) -> doc::moddoc;
type fold_nmod<T> = fn~(fold: fold<T>, doc: doc::nmoddoc) -> doc::nmoddoc;
type fold_fn<T> = fn~(fold: fold<T>, doc: doc::fndoc) -> doc::fndoc;
type fold_const<T> = fn~(fold: fold<T>, doc: doc::constdoc) -> doc::constdoc;
type fold_enum<T> = fn~(fold: fold<T>, doc: doc::enumdoc) -> doc::enumdoc;
type fold_res<T> = fn~(fold: fold<T>, doc: doc::resdoc) -> doc::resdoc;
type fold_iface<T> = fn~(fold: fold<T>, doc: doc::ifacedoc) -> doc::ifacedoc;
type fold_impl<T> = fn~(fold: fold<T>, doc: doc::impldoc) -> doc::impldoc;
type fold_type<T> = fn~(fold: fold<T>, doc: doc::tydoc) -> doc::tydoc;

type t<T> = {
    ctxt: T,
    fold_crate: fold_crate<T>,
    fold_item: fold_item<T>,
    fold_mod: fold_mod<T>,
    fold_nmod: fold_nmod<T>,
    fold_fn: fold_fn<T>,
    fold_const: fold_const<T>,
    fold_enum: fold_enum<T>,
    fold_res: fold_res<T>,
    fold_iface: fold_iface<T>,
    fold_impl: fold_impl<T>,
    fold_type: fold_type<T>
};

// This exists because fn types don't infer correctly as record
// initializers, but they do as function arguments
fn mk_fold<T:copy>(
    ctxt: T,
    fold_crate: fold_crate<T>,
    fold_item: fold_item<T>,
    fold_mod: fold_mod<T>,
    fold_nmod: fold_nmod<T>,
    fold_fn: fold_fn<T>,
    fold_const: fold_const<T>,
    fold_enum: fold_enum<T>,
    fold_res: fold_res<T>,
    fold_iface: fold_iface<T>,
    fold_impl: fold_impl<T>,
    fold_type: fold_type<T>
) -> fold<T> {
    fold({
        ctxt: ctxt,
        fold_crate: fold_crate,
        fold_item: fold_item,
        fold_mod: fold_mod,
        fold_nmod: fold_nmod,
        fold_fn: fold_fn,
        fold_const: fold_const,
        fold_enum: fold_enum,
        fold_res: fold_res,
        fold_iface: fold_iface,
        fold_impl: fold_impl,
        fold_type: fold_type
    })
}

fn default_any_fold<T:send>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_any_fold_mod(f, d)},
        {|f, d| default_any_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_seq_fold<T:copy>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_seq_fold_mod(f, d)},
        {|f, d| default_seq_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_par_fold<T:send>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_par_fold_mod(f, d)},
        {|f, d| default_par_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_seq_fold_crate<T>(
    fold: fold<T>,
    doc: doc::cratedoc
) -> doc::cratedoc {
    {
        topmod: fold.fold_mod(fold, doc.topmod)
    }
}

fn default_seq_fold_item<T>(
    _fold: fold<T>,
    doc: doc::itemdoc
) -> doc::itemdoc {
    doc
}

fn default_any_fold_mod<T:send>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::anymap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_seq_fold_mod<T>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::seqmap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_par_fold_mod<T:send>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::parmap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_any_fold_nmod<T:send>(
    fold: fold<T>,
    doc: doc::nmoddoc
) -> doc::nmoddoc {
    {
        item: fold.fold_item(fold, doc.item),
        fns: util::anymap(doc.fns) {|fndoc|
            fold.fold_fn(fold, fndoc)
        }
        with doc
    }
}

fn default_seq_fold_nmod<T>(
    fold: fold<T>,
    doc: doc::nmoddoc
) -> doc::nmoddoc {
    {
        item: fold.fold_item(fold, doc.item),
        fns: util::seqmap(doc.fns) {|fndoc|
            fold.fold_fn(fold, fndoc)
        }
        with doc
    }
}

fn default_par_fold_nmod<T:send>(
    fold: fold<T>,
    doc: doc::nmoddoc
) -> doc::nmoddoc {
    {
        item: fold.fold_item(fold, doc.item),
        fns: util::parmap(doc.fns) {|fndoc|
            fold.fold_fn(fold, fndoc)
        }
        with doc
    }
}

fn fold_itemtag<T>(fold: fold<T>, doc: doc::itemtag) -> doc::itemtag {
    alt doc {
      doc::modtag(moddoc) {
        doc::modtag(fold.fold_mod(fold, moddoc))
      }
      doc::nmodtag(nmoddoc) {
        doc::nmodtag(fold.fold_nmod(fold, nmoddoc))
      }
      doc::fntag(fndoc) {
        doc::fntag(fold.fold_fn(fold, fndoc))
      }
      doc::consttag(constdoc) {
        doc::consttag(fold.fold_const(fold, constdoc))
      }
      doc::enumtag(enumdoc) {
        doc::enumtag(fold.fold_enum(fold, enumdoc))
      }
      doc::restag(resdoc) {
        doc::restag(fold.fold_res(fold, resdoc))
      }
      doc::ifacetag(ifacedoc) {
        doc::ifacetag(fold.fold_iface(fold, ifacedoc))
      }
      doc::impltag(impldoc) {
        doc::impltag(fold.fold_impl(fold, impldoc))
      }
      doc::tytag(tydoc) {
        doc::tytag(fold.fold_type(fold, tydoc))
      }
    }
}

fn default_seq_fold_fn<T>(
    fold: fold<T>,
    doc: doc::fndoc
) -> doc::fndoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_const<T>(
    fold: fold<T>,
    doc: doc::constdoc
) -> doc::constdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_enum<T>(
    fold: fold<T>,
    doc: doc::enumdoc
) -> doc::enumdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_res<T>(
    fold: fold<T>,
    doc: doc::resdoc
) -> doc::resdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_iface<T>(
    fold: fold<T>,
    doc: doc::ifacedoc
) -> doc::ifacedoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_impl<T>(
    fold: fold<T>,
    doc: doc::impldoc
) -> doc::impldoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_type<T>(
    fold: fold<T>,
    doc: doc::tydoc
) -> doc::tydoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

#[test]
fn default_fold_should_produce_same_doc() {
    let source = "mod a { fn b() { } mod c { fn d() { } } }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_fold_should_produce_same_consts() {
    let source = "const a: int = 0;";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_fold_should_produce_same_enums() {
    let source = "enum a { b }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_parallel_fold_should_produce_same_doc() {
    let source = "mod a { fn b() { } mod c { fn d() { } } }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_par_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::hashmap::HashMap;
use std::rc::{Rc, Weak};
use syntax::ast::{TokenTree, LitIntUnsuffixed};
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base::ExtCtxt;
use syntax::parse::{token, ParseSess, lexer, integer_lit};

use node;

pub struct Parser<'a> {
  pub sess: &'a ParseSess,
  reader: Box<lexer::Reader>,
  token: token::Token,
  span: Span,

  last_token: Option<Box<token::Token>>,
  last_span: Span,
}

impl<'a> Parser<'a> {
  pub fn new<'a>(cx: &'a ExtCtxt, tts: &[TokenTree]) -> Parser<'a> {
    let sess = cx.parse_sess();
    let ttsvec = tts.iter().map(|x| (*x).clone()).collect();
    let mut reader = box lexer::new_tt_reader(
        &sess.span_diagnostic, None, ttsvec) as Box<lexer::Reader>;

    let tok0 = reader.next_token();
    let token = tok0.tok;
    let span = tok0.sp;

    Parser {
      sess: sess,
      reader: reader,

      token: token,
      span: span,

      last_token: None,
      last_span: span,
    }
  }

  /// Parse the platform tree from passed in tokens.
  pub fn parse_platformtree(&mut self) -> Option<Rc<node::PlatformTree>> {
    let mut nodes: HashMap<String, Rc<node::Node>> = HashMap::new();
    let mut failed = false;
    loop {
      if self.token == token::EOF {
        break
      }

      let node = match self.parse_node(None) {
        Some(node) => node,
        None => {
          failed = true;
          self.bump();
          continue
        }
      };

      let path = node.path.clone();
      if nodes.contains_key(&path) {
        failed = true;
        self.sess.span_diagnostic.span_err(node.path_span,
            format!("duplicate node definition `{}`", path).as_slice());
        let old_node: &Rc<node::Node> = nodes.get(&path);
        self.sess.span_diagnostic.span_err(old_node.path_span,
            "previously defined here");
      } else {
        nodes.insert(node.path.clone(), node);
      }
    }

    if failed {
      None
    } else {
      let mut map = HashMap::new();
      if self.collect_node_names(&mut map, &nodes) {
        Some(Rc::new(node::PlatformTree::new(nodes, map)))
      } else {
        None
      }
    }
  }

  fn collect_node_names(&self, map: &mut HashMap<String, Weak<node::Node>>,
      nodes: &HashMap<String, Rc<node::Node>>) -> bool {
    for (_, n) in nodes.iter() {
      let mut strongmap = HashMap::new();
      n.with_subnodes_map(|sub|{
        for (k, weak_node) in sub.iter() {
          let node = weak_node.upgrade().unwrap();
          strongmap.insert(k.clone(), node);
        }
      });

      if !self.collect_node_names(map, &strongmap) {
        return false;
      }

      match n.name {
        Some(ref name) => {
          if map.contains_key(name) {
            self.sess.span_diagnostic.span_err(n.name_span, format!(
                "duplicate `{}` definition", name).as_slice());

            self.sess.span_diagnostic.span_warn(
                map.get(name).upgrade().unwrap().name_span,
                "previously defined here");
            return false;
          } else {
            map.insert(name.clone(), n.downgrade());
          }
        },
        None => (),
      }
    }
    true
  }

  fn parse_node(&mut self, parent: Option<Weak<node::Node>>)
      -> Option<Rc<node::Node>> {
    let name_span: Option<Span>;
    let node_name: Option<String>;

    //  we're here
    // /
    // v
    // NAME @ PATH { ... }
    //      ^-- peeking here
    if self.reader.peek().tok == token::AT {
      name_span = Some(self.span);
      node_name = match self.expect_ident() {
        Some(name) => Some(name),
        None => return None,
      };
      if !self.expect(&token::AT) {
        return None;
      }
    } else {
      node_name = None;
      name_span = None;
    }

    let node_span: Span;
    let node_path_span: Span;
    let attributes: HashMap<String, Rc<node::Attribute>>;
    let subnodes: node::Subnodes;

    // NAME is resolved, if it was there anyway.
    //    we're here
    //          |
    //          v
    //   NAME @ PATH { ... }
    node_path_span = self.span;
    if node_name == None {
      node_span = self.span;
    } else {
      node_span = mk_sp(name_span.unwrap().lo, self.span.hi);
    }

    let node_path = match self.token {
      token::IDENT(_, _) => {
        token::to_string(&self.bump())
      },
      token::LIT_INTEGER(intname) => {
        self.bump();

        let lit = integer_lit(intname.as_str(), &self.sess.span_diagnostic, self.span);
        match lit {
          LitIntUnsuffixed(i) => {
            format!("{}", i)
          },
          _ => {
            self.error(format!("expected unsuffixed integer but found `{}`",
                token::to_string(&self.token)));
            return None
          }
        }
      }
      ref other => {
        self.error(format!("expected node path but found `{}`",
            token::to_string(other)));
        return None;
      }
    };

    let node = Rc::new(node::Node::new(
        node_name, node_span, node_path, node_path_span, parent));
    let weak_node = node.downgrade();

    //    we're here
    //             |
    //             v
    // NAME @ PATH { ... }
    // it's either a body, or a semicolon (no body)
    match self.bump() {
      token::LBRACE => {
        let (a, s) = match self.parse_node_body(weak_node) {
          Some((attrs, subnodes)) => (attrs, subnodes),
          // TODO(farcaller): eat everything up to '}' and continue if failed
          // we can still parse further nodes.
          None => return None,
        };
        attributes = a;
        subnodes = s;

        if !self.expect(&token::RBRACE) {
          return None;
        }
      },
      token::SEMI => {
        attributes = HashMap::new();
        subnodes = node::Subnodes::new();
      },
      ref other => {
        self.error(format!("expected `{{` or `;` but found `{}`",
            token::to_string(other)));
        return None;
      }
    }

    node.attributes.borrow_mut().clone_from(&attributes);
    node.set_subnodes(subnodes);
    Some(node)
  }

  fn parse_node_body(&mut self, weak_node: Weak<node::Node>)
      -> Option<(HashMap<String, Rc<node::Attribute>>, node::Subnodes)> {
    let mut attrs = HashMap::new();
    let mut subnodes = node::Subnodes::new();

    loop {
      // break early if at brace
      if self.token == token::RBRACE {
        break;
      }

      // we're here
      // |
      // v
      // ATTR = VAL ;
      // NAME @ PATH
      // PATH { ... }
      // PATH ;
      //      ^-- peeking here
      if self.reader.peek().tok == token::EQ {
        // we're here
        // |
        // v
        // ATTR = VAL ;
        let name_span = self.span;
        let some_name = match self.expect_ident() {
          Some(name) => name,
          None => return None,
        };

        if attrs.contains_key(&some_name) {
          self.error(format!("key `{}` is already defined", some_name));
          return None;
        }

        self.bump(); // bump token::EQ

        // we're here
        //        |
        //        v
        // ATTR = VAL ;
        let attr_value_span = self.span;
        let attr_value = match self.parse_attribute_value() {
          Some(value) => value,
          None => return None,
        };

        //   we're here
        //            |
        //            v
        // ATTR = VAL ;
        if !self.expect(&token::SEMI) {
          return None;
        }

        attrs.insert(some_name, Rc::new(node::Attribute::new(
            attr_value, name_span, attr_value_span)));
      } else {
        // this should be a subnode
        let oldsp = self.span;
        let oldtok = self.token.clone();
        let node = match self.parse_node(Some(weak_node.clone())) {
          Some(node) => node,
          None => {
            self.span = oldsp;
            self.error(format!("expected `=` or node but found `{}`",
                token::to_string(&oldtok)));
            return None;
          },
        };

        let path = node.path.clone();
        if subnodes.as_map().contains_key(&path) {
          self.span = node.path_span;
          self.error(format!("duplicate node definition `{}`",
              path));
          let old_node: Rc<node::Node> = subnodes.as_map().get(&path).upgrade().unwrap();
          self.span = old_node.path_span.clone();
          self.error("previously defined here".to_string());
          return None;
        } else {
          subnodes.push(node);
        }
      }
    }

    Some((attrs, subnodes))
  }

  fn parse_attribute_value(&mut self) -> Option<node::AttributeValue> {
    match self.token {
      token::LIT_STR(string_val) => {
        self.bump();
        Some(node::StrValue(string_val.as_str().to_string()))
      },
      token::LIT_INTEGER(intname) => {
        let lit = integer_lit(intname.as_str(), &self.sess.span_diagnostic, self.span);
        match lit {
          LitIntUnsuffixed(i) => {
            self.bump();
            Some(node::IntValue(i as uint))
          },
          _ => {
            self.error(format!("expected unsuffixed integer but found `{}`",
                token::to_string(&self.token)));
            None
          }
        }
      },
      token::BINOP(token::AND) => {
        self.bump();
        let name = match self.expect_ident() {
          Some(name) => name,
          None => return None,
        };
        Some(node::RefValue(name))
      },
      ref other => {
        self.error(format!("expected attribute value but found `{}`",
            token::to_string(other)));
        None
      }
    }
  }

  fn error(&self, m: String) {
    self.sess.span_diagnostic.span_err(self.span, m.as_slice());
  }

  /// Bumps a token.
  ///
  /// This moves current token to last token, pops a new token from backlog or
  /// reader and returns the last token (i.e. the 'current' token at the time of
  /// method call).
  fn bump(&mut self) -> token::Token {
    let tok = self.token.clone();
    self.last_span = self.span;
    self.last_token = Some(box tok.clone());

    let next = self.reader.next_token();

    self.span = next.sp;
    self.token = next.tok;

    tok
  }

  /// Expects that the current token is t. Bumps on success.
  fn expect(&mut self, t: &token::Token) -> bool {
    if self.token == *t {
      self.bump();
      true
    } else {
      let token_str = token::to_string(t);
      let this_token_str = token::to_string(&self.token);
      self.error(format!("expected `{}` but found `{}`", token_str,
          this_token_str));
      false
    }
  }

  /// Expects that the current token is IDENT, returns its string value. Bumps
  /// on success.
  fn expect_ident(&mut self) -> Option<String> {
    let tok_str = token::to_string(&self.token);
    match self.token {
      token::IDENT(_, _) => {
        self.bump();
        Some(tok_str)
      },
      _ => {
        self.error(format!("expected identifier but found `{}`", tok_str));
        None
      },
    }
  }
}
<commit_msg>platformtree: Track rustc changes<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::hashmap::HashMap;
use std::rc::{Rc, Weak};
use syntax::ast::{TokenTree, LitInt, UnsuffixedIntLit};
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base::ExtCtxt;
use syntax::parse::{token, ParseSess, lexer, integer_lit};

use node;

pub struct Parser<'a> {
  pub sess: &'a ParseSess,
  reader: Box<lexer::Reader>,
  token: token::Token,
  span: Span,

  last_token: Option<Box<token::Token>>,
  last_span: Span,
}

impl<'a> Parser<'a> {
  pub fn new<'a>(cx: &'a ExtCtxt, tts: &[TokenTree]) -> Parser<'a> {
    let sess = cx.parse_sess();
    let ttsvec = tts.iter().map(|x| (*x).clone()).collect();
    let mut reader = box lexer::new_tt_reader(
        &sess.span_diagnostic, None, ttsvec) as Box<lexer::Reader>;

    let tok0 = reader.next_token();
    let token = tok0.tok;
    let span = tok0.sp;

    Parser {
      sess: sess,
      reader: reader,

      token: token,
      span: span,

      last_token: None,
      last_span: span,
    }
  }

  /// Parse the platform tree from passed in tokens.
  pub fn parse_platformtree(&mut self) -> Option<Rc<node::PlatformTree>> {
    let mut nodes: HashMap<String, Rc<node::Node>> = HashMap::new();
    let mut failed = false;
    loop {
      if self.token == token::EOF {
        break
      }

      let node = match self.parse_node(None) {
        Some(node) => node,
        None => {
          failed = true;
          self.bump();
          continue
        }
      };

      let path = node.path.clone();
      if nodes.contains_key(&path) {
        failed = true;
        self.sess.span_diagnostic.span_err(node.path_span,
            format!("duplicate node definition `{}`", path).as_slice());
        let old_node: &Rc<node::Node> = nodes.get(&path);
        self.sess.span_diagnostic.span_err(old_node.path_span,
            "previously defined here");
      } else {
        nodes.insert(node.path.clone(), node);
      }
    }

    if failed {
      None
    } else {
      let mut map = HashMap::new();
      if self.collect_node_names(&mut map, &nodes) {
        Some(Rc::new(node::PlatformTree::new(nodes, map)))
      } else {
        None
      }
    }
  }

  fn collect_node_names(&self, map: &mut HashMap<String, Weak<node::Node>>,
      nodes: &HashMap<String, Rc<node::Node>>) -> bool {
    for (_, n) in nodes.iter() {
      let mut strongmap = HashMap::new();
      n.with_subnodes_map(|sub|{
        for (k, weak_node) in sub.iter() {
          let node = weak_node.upgrade().unwrap();
          strongmap.insert(k.clone(), node);
        }
      });

      if !self.collect_node_names(map, &strongmap) {
        return false;
      }

      match n.name {
        Some(ref name) => {
          if map.contains_key(name) {
            self.sess.span_diagnostic.span_err(n.name_span, format!(
                "duplicate `{}` definition", name).as_slice());

            self.sess.span_diagnostic.span_warn(
                map.get(name).upgrade().unwrap().name_span,
                "previously defined here");
            return false;
          } else {
            map.insert(name.clone(), n.downgrade());
          }
        },
        None => (),
      }
    }
    true
  }

  fn parse_node(&mut self, parent: Option<Weak<node::Node>>)
      -> Option<Rc<node::Node>> {
    let name_span: Option<Span>;
    let node_name: Option<String>;

    //  we're here
    // /
    // v
    // NAME @ PATH { ... }
    //      ^-- peeking here
    if self.reader.peek().tok == token::AT {
      name_span = Some(self.span);
      node_name = match self.expect_ident() {
        Some(name) => Some(name),
        None => return None,
      };
      if !self.expect(&token::AT) {
        return None;
      }
    } else {
      node_name = None;
      name_span = None;
    }

    let node_span: Span;
    let node_path_span: Span;
    let attributes: HashMap<String, Rc<node::Attribute>>;
    let subnodes: node::Subnodes;

    // NAME is resolved, if it was there anyway.
    //    we're here
    //          |
    //          v
    //   NAME @ PATH { ... }
    node_path_span = self.span;
    if node_name == None {
      node_span = self.span;
    } else {
      node_span = mk_sp(name_span.unwrap().lo, self.span.hi);
    }

    let node_path = match self.token {
      token::IDENT(_, _) => {
        token::to_string(&self.bump())
      },
      token::LIT_INTEGER(intname) => {
        self.bump();

        let lit = integer_lit(intname.as_str(), &self.sess.span_diagnostic, self.span);
        match lit {
          LitInt(i, _) => {
            format!("{}", i)
          },
          _ => {
            self.error(format!("expected unsuffixed integer but found `{}`",
                token::to_string(&self.token)));
            return None
          }
        }
      }
      ref other => {
        self.error(format!("expected node path but found `{}`",
            token::to_string(other)));
        return None;
      }
    };

    let node = Rc::new(node::Node::new(
        node_name, node_span, node_path, node_path_span, parent));
    let weak_node = node.downgrade();

    //    we're here
    //             |
    //             v
    // NAME @ PATH { ... }
    // it's either a body, or a semicolon (no body)
    match self.bump() {
      token::LBRACE => {
        let (a, s) = match self.parse_node_body(weak_node) {
          Some((attrs, subnodes)) => (attrs, subnodes),
          // TODO(farcaller): eat everything up to '}' and continue if failed
          // we can still parse further nodes.
          None => return None,
        };
        attributes = a;
        subnodes = s;

        if !self.expect(&token::RBRACE) {
          return None;
        }
      },
      token::SEMI => {
        attributes = HashMap::new();
        subnodes = node::Subnodes::new();
      },
      ref other => {
        self.error(format!("expected `{{` or `;` but found `{}`",
            token::to_string(other)));
        return None;
      }
    }

    node.attributes.borrow_mut().clone_from(&attributes);
    node.set_subnodes(subnodes);
    Some(node)
  }

  fn parse_node_body(&mut self, weak_node: Weak<node::Node>)
      -> Option<(HashMap<String, Rc<node::Attribute>>, node::Subnodes)> {
    let mut attrs = HashMap::new();
    let mut subnodes = node::Subnodes::new();

    loop {
      // break early if at brace
      if self.token == token::RBRACE {
        break;
      }

      // we're here
      // |
      // v
      // ATTR = VAL ;
      // NAME @ PATH
      // PATH { ... }
      // PATH ;
      //      ^-- peeking here
      if self.reader.peek().tok == token::EQ {
        // we're here
        // |
        // v
        // ATTR = VAL ;
        let name_span = self.span;
        let some_name = match self.expect_ident() {
          Some(name) => name,
          None => return None,
        };

        if attrs.contains_key(&some_name) {
          self.error(format!("key `{}` is already defined", some_name));
          return None;
        }

        self.bump(); // bump token::EQ

        // we're here
        //        |
        //        v
        // ATTR = VAL ;
        let attr_value_span = self.span;
        let attr_value = match self.parse_attribute_value() {
          Some(value) => value,
          None => return None,
        };

        //   we're here
        //            |
        //            v
        // ATTR = VAL ;
        if !self.expect(&token::SEMI) {
          return None;
        }

        attrs.insert(some_name, Rc::new(node::Attribute::new(
            attr_value, name_span, attr_value_span)));
      } else {
        // this should be a subnode
        let oldsp = self.span;
        let oldtok = self.token.clone();
        let node = match self.parse_node(Some(weak_node.clone())) {
          Some(node) => node,
          None => {
            self.span = oldsp;
            self.error(format!("expected `=` or node but found `{}`",
                token::to_string(&oldtok)));
            return None;
          },
        };

        let path = node.path.clone();
        if subnodes.as_map().contains_key(&path) {
          self.span = node.path_span;
          self.error(format!("duplicate node definition `{}`",
              path));
          let old_node: Rc<node::Node> = subnodes.as_map().get(&path).upgrade().unwrap();
          self.span = old_node.path_span.clone();
          self.error("previously defined here".to_string());
          return None;
        } else {
          subnodes.push(node);
        }
      }
    }

    Some((attrs, subnodes))
  }

  fn parse_attribute_value(&mut self) -> Option<node::AttributeValue> {
    match self.token {
      token::LIT_STR(string_val) => {
        self.bump();
        Some(node::StrValue(string_val.as_str().to_string()))
      },
      token::LIT_INTEGER(intname) => {
        let lit = integer_lit(intname.as_str(), &self.sess.span_diagnostic, self.span);
        match lit {
          LitInt(i, UnsuffixedIntLit(_)) => {
            self.bump();
            Some(node::IntValue(i as uint))
          },
          _ => {
            self.error(format!("expected unsuffixed integer but found `{}`",
                token::to_string(&self.token)));
            None
          }
        }
      },
      token::BINOP(token::AND) => {
        self.bump();
        let name = match self.expect_ident() {
          Some(name) => name,
          None => return None,
        };
        Some(node::RefValue(name))
      },
      ref other => {
        self.error(format!("expected attribute value but found `{}`",
            token::to_string(other)));
        None
      }
    }
  }

  fn error(&self, m: String) {
    self.sess.span_diagnostic.span_err(self.span, m.as_slice());
  }

  /// Bumps a token.
  ///
  /// This moves current token to last token, pops a new token from backlog or
  /// reader and returns the last token (i.e. the 'current' token at the time of
  /// method call).
  fn bump(&mut self) -> token::Token {
    let tok = self.token.clone();
    self.last_span = self.span;
    self.last_token = Some(box tok.clone());

    let next = self.reader.next_token();

    self.span = next.sp;
    self.token = next.tok;

    tok
  }

  /// Expects that the current token is t. Bumps on success.
  fn expect(&mut self, t: &token::Token) -> bool {
    if self.token == *t {
      self.bump();
      true
    } else {
      let token_str = token::to_string(t);
      let this_token_str = token::to_string(&self.token);
      self.error(format!("expected `{}` but found `{}`", token_str,
          this_token_str));
      false
    }
  }

  /// Expects that the current token is IDENT, returns its string value. Bumps
  /// on success.
  fn expect_ident(&mut self) -> Option<String> {
    let tok_str = token::to_string(&self.token);
    match self.token {
      token::IDENT(_, _) => {
        self.bump();
        Some(tok_str)
      },
      _ => {
        self.error(format!("expected identifier but found `{}`", tok_str));
        None
      },
    }
  }
}
<|endoftext|>


<commit_before>extern crate glm;
extern crate sdl2;

use self::sdl2::rect;
use self::sdl2::render::{Renderer, Texture};

pub struct SpriteStrip {
    texture: Texture,
    dims: glm::UVec2,
    wrapping_coords: Option<glm::UVec2>,
}

impl SpriteStrip {
    pub fn new(texture: Texture, num_frames: u32, wrapping_coords: Option<glm::UVec2>) -> Self {
        let query = texture.query();
        let dims = glm::uvec2(query.width / num_frames, query.height);

        SpriteStrip {
            texture: texture,
            dims: dims,
            wrapping_coords: wrapping_coords,
        }
    }

    pub fn draw(&self,
                renderer: &mut Renderer,
                center: glm::IVec2,
                frame_num: u32)
                -> Result<(), String> {

        let source_rect = rect::Rect::new((self.dims.x * frame_num) as i32,
                                          0,
                                          self.dims.x,
                                          self.dims.y);

        self.drawing_rectangles(center)
            .iter()
            .filter(|r| r.is_some())
            .map(|&r| renderer.copy(&self.texture, Some(source_rect), r))
            .fold(Ok(()), |res, x| { if res.is_err() { res } else { x } })
    }

    pub fn get_dims(&self) -> glm::UVec2 {
        self.dims
    }

    fn drawing_rectangles(&self, center: glm::IVec2) -> [Option<rect::Rect>; 4] {
        let left = center.x - self.dims.x as i32 / 2;
        let top = center.y - self.dims.y as i32 / 2;

        let rect = rect::Rect::new(left, top, self.dims.x, self.dims.y);
        let (side_rect, vert_rect) = if let None = self.wrapping_coords {
            (None, None)
        } else {
            (self.side_rect(&rect, center), self.vert_rect(&rect, center))
        };

        let side_vert_rect = match (vert_rect, side_rect) {
            (Some(vert_unwrapped), Some(side_unwrapped)) => {
                Some(rect::Rect::new(side_unwrapped.x(),
                                     vert_unwrapped.y(),
                                     self.dims.x,
                                     self.dims.y))
            }
            _ => None,
        };

        [Some(rect), vert_rect, side_rect, side_vert_rect]
    }

    fn vert_rect(&self, original: &rect::Rect, center: glm::IVec2) -> Option<rect::Rect> {
        let bottom = center.y + self.dims.y as i32 / 2;
        let top = center.y - self.dims.y as i32 / 2;
        let max_height = self.wrapping_coords.unwrap().y as i32;

        let mut copy = original.clone();

        if top < 0 {
            copy.set_y(top + max_height);
            Some(copy)
        } else if bottom > max_height {
            copy.set_bottom(bottom % max_height);
            Some(copy)
        } else {
            None
        }
    }

    fn side_rect(&self, original: &rect::Rect, center: glm::IVec2) -> Option<rect::Rect> {
        let left = center.x - self.dims.x as i32 / 2;
        let right = center.x + self.dims.x as i32 / 2;
        let max_width = self.wrapping_coords.unwrap().x as i32;

        let mut copy = original.clone();

        if left < 0 {
            copy.set_x(left + max_width);
            Some(copy)
        } else if right > max_width {
            copy.set_right(right % max_width);
            Some(copy)
        } else {
            None
        }
    }
}
<commit_msg>use window wrapped when drawing a sprite<commit_after>extern crate glm;
extern crate sdl2;
extern crate moho;

use self::sdl2::rect;
use self::sdl2::render::{Renderer, Texture};
use self::moho::window_wrapper::*;

pub struct SpriteStrip {
    texture: Texture,
    dims: glm::UVec2,
    wrapping_coords: Option<glm::UVec2>,
}

impl SpriteStrip {
    pub fn new(texture: Texture, num_frames: u32, wrapping_coords: Option<glm::UVec2>) -> Self {
        let query = texture.query();
        let dims = glm::uvec2(query.width / num_frames, query.height);

        SpriteStrip {
            texture: texture,
            dims: dims,
            wrapping_coords: wrapping_coords,
        }
    }

    pub fn draw(&self,
                renderer: &mut Renderer,
                center: glm::IVec2,
                frame_num: u32)
                -> Result<(), String> {

        let source_rect = rect::Rect::new((self.dims.x * frame_num) as i32,
                                          0,
                                          self.dims.x,
                                          self.dims.y);

        match self.wrapping_coords {
            Some(coords) => {
                let center = glm::uvec2(center.x as u32, center.y as u32);
                get_wrapped_centers(center, self.dims, coords)
                    .iter()
                    .filter_map(|&c| c)
                    .map(|c| {
                        rect::Rect::new(c.x - self.dims.x as i32 / 2,
                                        c.y - self.dims.y as i32 / 2,
                                        self.dims.x,
                                        self.dims.y)
                    })
                    .map(|r| renderer.copy(&self.texture, Some(source_rect), Some(r)))
                    .fold(Ok(()), |res, x| { if res.is_err() { res } else { x } })
            }
            None => {
                let rect = rect::Rect::new(center.x - self.dims.x as i32 / 2,
                                           center.y - self.dims.y as i32 / 2,
                                           self.dims.x,
                                           self.dims.y);
                renderer.copy(&self.texture, Some(source_rect), Some(rect))
            }
        }
    }

    pub fn get_dims(&self) -> glm::UVec2 {
        self.dims
    }
}
<|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.

//! A handler and associated types for the filesystems action.
//!
//! The filesystems action lists all mounted filesystems on the client,
//! collecting device name, mount point, filesystem type and its options.
//! Current implementation works only in Linux systems.

use rrg_proto::{Filesystem, KeyValue, AttributedDict};
use crate::session::{self, Session};

use log::error;
use std::fmt::{Display, Formatter};

/// Enum of possible errors, which can occur during collecting filesystems data.
#[derive(Debug)]
enum Error {
    /// Missing mtab-like file error.
    MissingFile(std::io::Error),
    /// Parsing mtab-like file error.
    MountInfoParse(std::io::Error),
}

impl std::error::Error for Error {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use Error::*;

        match *self {
            MissingFile(ref error) => Some(error),
            MountInfoParse(ref error) => Some(error),
        }
    }
}

impl Display for Error {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        use Error::*;

        match *self {
            MissingFile(ref error) => {
                write!(fmt, "missed file error: {}", error)
            },
            MountInfoParse(ref error) => {
                write!(fmt, "failed to obtain mount information: {}", error)
            },
        }
    }
}

impl From<Error> for session::Error {

    fn from(error: Error) -> session::Error {
        session::Error::action(error)
    }
}

/// A response type for the filesystems action.
pub struct Response {
    /// Information about the filesystem.
    mount_info: proc_mounts::MountInfo,
}

/// Handles requests for the filesystems action.
///
/// Initially searches in `/proc/mounts`. If it's missing, falls back to
/// `/etc/mtab`.
pub fn handle<S: Session>(session: &mut S, _: ()) -> session::Result<()> {
    use proc_mounts::MountIter;

    // Check whether `/proc/mounts` exists.
    let mount_iter = match MountIter::new() {
        Ok(mount_iter) => mount_iter,
        Err(_) => {
            // `/proc/mounts` doesn't exist. Try to fall back to `/etc/mtab`.
            MountIter::new_from_file("/etc/mtab").map_err(Error::MissingFile)?
        },
    };

    for mount_info in mount_iter {
        let mount_info = mount_info.map_err(Error::MountInfoParse)?;
        session.reply(Response {
           mount_info,
        })?;
    }

    Ok(())
}

/// Converts filesystem mount option in `String` representation to
/// GRR's `KeyValue` protobuf struct representation.
fn option_to_key_value(option: String) -> KeyValue {
    match &option.split('=').collect::<Vec<&str>>()[..] {
        &[key] => KeyValue::key(String::from(key)),
        &[key, value] => KeyValue::pair(String::from(key), String::from(value)),
        _ => {
            error!("invalid mount option syntax: {}", option);
            KeyValue::empty()
        },
    }
}

impl super::Response for Response {

    const RDF_NAME: Option<&'static str> = Some("Filesystem");

    type Proto = rrg_proto::Filesystem;

    fn into_proto(self) -> Filesystem {
        let options = self.mount_info.options.into_iter()
            .map(option_to_key_value)
            .collect();

        // TODO: Remove lossy conversion of `PathBuf` to `String`
        // when `mount_point` and `device` fields of `Filesystem` message
        // will have `bytes` type instead of `string`.
        Filesystem {
            device: Some(self.mount_info.source.to_string_lossy()
                .into_owned()),
            mount_point: Some(self.mount_info.dest.to_string_lossy()
                .into_owned()),
            r#type: Some(self.mount_info.fstype),
            label: None,
            options: Some(options),
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use std::path::PathBuf;

    #[test]
    fn test_if_any_filesystem_exists() {
        let mut session = session::test::Fake::new();
        assert!(handle(&mut session, ()).is_ok());
        assert_ne!(session.reply_count(), 0);
    }

    /// Unit-like struct, representing a filesystem for testing with `fuse`.
    struct FuseFilesystem;

    impl fuse::Filesystem for FuseFilesystem {}

    #[test]
    fn test_fuse_filesystem() {
        use users::{get_current_uid, get_current_gid};

        let fs_name = PathBuf::from("fuse-test-fs");

        let tmp_dir = tempfile::tempdir().unwrap();
        let mountpoint = tmp_dir.path();

        let fs_name_option = format!("fsname={}", fs_name.to_str().unwrap());
        let options = [
            "-o", "ro",
            "-o", "nosuid",
            "-o", "nodev",
            "-o", "relatime",
            "-o", "subtype=custom-type",
            "-o", &fs_name_option,
        ];
        let options = options.iter().map(|opt| opt.as_ref())
            .collect::<Vec<&std::ffi::OsStr>>();

        // Spawn a background thread to handle filesystem operations.
        // When `_background_session` is dropped, filesystem will be unmounted.
        let background_session = unsafe {
            fuse::spawn_mount(FuseFilesystem, &mountpoint, &options).unwrap()
        };

        let mut session = session::test::Fake::new();
        assert!(handle(&mut session, ()).is_ok());

        let fuse_mounted_fs = session.replies::<Response>()
            .find(|reply| reply.mount_info.source == fs_name)
            .expect("no reply with a mounted FUSE filesystem");

        let mount_info = &fuse_mounted_fs.mount_info;
        assert_eq!(mount_info.source, fs_name);
        assert_eq!(mount_info.dest, tmp_dir.path());
        assert_eq!(mount_info.fstype, "fuse.custom-type");

        let options = &mount_info.options;
        assert!(options.iter().any(|opt| opt == "ro"));
        assert!(options.iter().any(|opt| opt == "nosuid"));
        assert!(options.iter().any(|opt| opt == "nodev"));
        assert!(options.iter().any(|opt| opt == "relatime"));

        // `user_id` and `group_id` are set by libfuse.
        // http://man7.org/linux/man-pages/man8/mount.fuse.8.html
        let current_uid_option = format!("user_id={}", get_current_uid());
        assert!(options.iter().any(|opt| *opt == current_uid_option));

        let current_gid_option = format!("group_id={}", get_current_gid());
        assert!(options.iter().any(|opt| *opt == current_gid_option));

        drop(background_session);
    }
}
<commit_msg>Add a TODO comment about useless key-value entry.<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.

//! A handler and associated types for the filesystems action.
//!
//! The filesystems action lists all mounted filesystems on the client,
//! collecting device name, mount point, filesystem type and its options.
//! Current implementation works only in Linux systems.

use rrg_proto::{Filesystem, KeyValue, AttributedDict};
use crate::session::{self, Session};

use log::error;
use std::fmt::{Display, Formatter};

/// Enum of possible errors, which can occur during collecting filesystems data.
#[derive(Debug)]
enum Error {
    /// Missing mtab-like file error.
    MissingFile(std::io::Error),
    /// Parsing mtab-like file error.
    MountInfoParse(std::io::Error),
}

impl std::error::Error for Error {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use Error::*;

        match *self {
            MissingFile(ref error) => Some(error),
            MountInfoParse(ref error) => Some(error),
        }
    }
}

impl Display for Error {

    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
        use Error::*;

        match *self {
            MissingFile(ref error) => {
                write!(fmt, "missed file error: {}", error)
            },
            MountInfoParse(ref error) => {
                write!(fmt, "failed to obtain mount information: {}", error)
            },
        }
    }
}

impl From<Error> for session::Error {

    fn from(error: Error) -> session::Error {
        session::Error::action(error)
    }
}

/// A response type for the filesystems action.
pub struct Response {
    /// Information about the filesystem.
    mount_info: proc_mounts::MountInfo,
}

/// Handles requests for the filesystems action.
///
/// Initially searches in `/proc/mounts`. If it's missing, falls back to
/// `/etc/mtab`.
pub fn handle<S: Session>(session: &mut S, _: ()) -> session::Result<()> {
    use proc_mounts::MountIter;

    // Check whether `/proc/mounts` exists.
    let mount_iter = match MountIter::new() {
        Ok(mount_iter) => mount_iter,
        Err(_) => {
            // `/proc/mounts` doesn't exist. Try to fall back to `/etc/mtab`.
            MountIter::new_from_file("/etc/mtab").map_err(Error::MissingFile)?
        },
    };

    for mount_info in mount_iter {
        let mount_info = mount_info.map_err(Error::MountInfoParse)?;
        session.reply(Response {
           mount_info,
        })?;
    }

    Ok(())
}

/// Converts filesystem mount option in `String` representation to
/// GRR's `KeyValue` protobuf struct representation.
fn option_to_key_value(option: String) -> KeyValue {
    match &option.split('=').collect::<Vec<&str>>()[..] {
        &[key] => KeyValue::key(String::from(key)),
        &[key, value] => KeyValue::pair(String::from(key), String::from(value)),
        _ => {
            error!("invalid mount option syntax: {}", option);
            // TODO: It's better not to send any key-value in this case.
            KeyValue::empty()
        },
    }
}

impl super::Response for Response {

    const RDF_NAME: Option<&'static str> = Some("Filesystem");

    type Proto = rrg_proto::Filesystem;

    fn into_proto(self) -> Filesystem {
        let options = self.mount_info.options.into_iter()
            .map(option_to_key_value)
            .collect();

        // TODO: Remove lossy conversion of `PathBuf` to `String`
        // when `mount_point` and `device` fields of `Filesystem` message
        // will have `bytes` type instead of `string`.
        Filesystem {
            device: Some(self.mount_info.source.to_string_lossy()
                .into_owned()),
            mount_point: Some(self.mount_info.dest.to_string_lossy()
                .into_owned()),
            r#type: Some(self.mount_info.fstype),
            label: None,
            options: Some(options),
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use std::path::PathBuf;

    #[test]
    fn test_if_any_filesystem_exists() {
        let mut session = session::test::Fake::new();
        assert!(handle(&mut session, ()).is_ok());
        assert_ne!(session.reply_count(), 0);
    }

    /// Unit-like struct, representing a filesystem for testing with `fuse`.
    struct FuseFilesystem;

    impl fuse::Filesystem for FuseFilesystem {}

    #[test]
    fn test_fuse_filesystem() {
        use users::{get_current_uid, get_current_gid};

        let fs_name = PathBuf::from("fuse-test-fs");

        let tmp_dir = tempfile::tempdir().unwrap();
        let mountpoint = tmp_dir.path();

        let fs_name_option = format!("fsname={}", fs_name.to_str().unwrap());
        let options = [
            "-o", "ro",
            "-o", "nosuid",
            "-o", "nodev",
            "-o", "relatime",
            "-o", "subtype=custom-type",
            "-o", &fs_name_option,
        ];
        let options = options.iter().map(|opt| opt.as_ref())
            .collect::<Vec<&std::ffi::OsStr>>();

        // Spawn a background thread to handle filesystem operations.
        // When `_background_session` is dropped, filesystem will be unmounted.
        let background_session = unsafe {
            fuse::spawn_mount(FuseFilesystem, &mountpoint, &options).unwrap()
        };

        let mut session = session::test::Fake::new();
        assert!(handle(&mut session, ()).is_ok());

        let fuse_mounted_fs = session.replies::<Response>()
            .find(|reply| reply.mount_info.source == fs_name)
            .expect("no reply with a mounted FUSE filesystem");

        let mount_info = &fuse_mounted_fs.mount_info;
        assert_eq!(mount_info.source, fs_name);
        assert_eq!(mount_info.dest, tmp_dir.path());
        assert_eq!(mount_info.fstype, "fuse.custom-type");

        let options = &mount_info.options;
        assert!(options.iter().any(|opt| opt == "ro"));
        assert!(options.iter().any(|opt| opt == "nosuid"));
        assert!(options.iter().any(|opt| opt == "nodev"));
        assert!(options.iter().any(|opt| opt == "relatime"));

        // `user_id` and `group_id` are set by libfuse.
        // http://man7.org/linux/man-pages/man8/mount.fuse.8.html
        let current_uid_option = format!("user_id={}", get_current_uid());
        assert!(options.iter().any(|opt| *opt == current_uid_option));

        let current_gid_option = format!("group_id={}", get_current_gid());
        assert!(options.iter().any(|opt| *opt == current_gid_option));

        drop(background_session);
    }
}
<|endoftext|>


<commit_before>use starred_message::StarredMessage;
use irc::client::prelude::*;
use irc::client::server::NetIrcServer;
use std::sync::Arc;

pub struct StarHandler {
	server : Arc<NetIrcServer>,
	starred: Vec<StarredMessage>,
}

impl StarHandler {
	pub fn new(server: &Arc<NetIrcServer>) -> StarHandler {
		StarHandler{
			server : server.clone(),
			starred: Vec::new(),
		}
	}

	pub fn dump(&self, onto: &str) {
		self.server.send_privmsg(onto, &*&format!("{:?}", self.starred)).unwrap()
	}

	pub fn show_board(&self, to: &str) {
		let mut sorted_stars = self.starred.clone();
		sorted_stars.sort_by(|lhs, rhs| lhs.stars.cmp(&rhs.stars));

		for message in sorted_stars.iter().take(10) {
			self.server.send_notice(to, &*&format!("{}", message)).unwrap();
		}
	}

	pub fn add_star(&mut self, starrer: &str, message: &str) {
		if let Some(star_message) = StarredMessage::from_message_content(message, starrer) {
			if match self.starred.iter_mut().find(|fmsg| (&fmsg.sender, &fmsg.message) == (&star_message.sender, &star_message.message)) {
				Some(ref mut existing_message) => {
					existing_message.stars += 1;
					existing_message.starrers.extend(star_message.starrers.clone());
					false
				},
				None => true,
			} {
				self.starred.push(star_message);  // Can't do it in match arm because it'd borrow starred as &mut twice
			}
		}
	}

	pub fn remove_star(&mut self, starrer: &str, message: &str) {
		if let Some(star_message) = StarredMessage::from_message_content(message, starrer) {
			if let Some(index) = match self.starred.iter_mut().enumerate().find(
				|fmsg| (&fmsg.1.sender, &fmsg.1.message) == (&star_message.sender, &star_message.message)
			) {
				Some((idx, ref mut existing_message)) =>
					if let Some(starrer_pos) = existing_message.starrers.iter().position(|starrer| starrer == &existing_message.starrers[0]) {
						existing_message.stars -= 1;
						existing_message.starrers.swap_remove(starrer_pos);
						Some(idx)
					} else {
						None
					},
				None => None,
			} {
				self.starred.swap_remove(index);  // Can't do it in match arm because it'd borrow starred as &mut twice
			}
		}
	}
}
<commit_msg>Extract and de-messify StarHandler add/remove functions<commit_after>use starred_message::StarredMessage;
use irc::client::prelude::*;
use irc::client::server::NetIrcServer;
use std::sync::Arc;

pub struct StarHandler {
	server : Arc<NetIrcServer>,
	starred: Vec<StarredMessage>,
}

impl StarHandler {
	pub fn new(server: &Arc<NetIrcServer>) -> StarHandler {
		StarHandler{
			server : server.clone(),
			starred: Vec::new(),
		}
	}

	pub fn dump(&self, onto: &str) {
		self.server.send_privmsg(onto, &*&format!("{:?}", self.starred)).unwrap()
	}

	pub fn show_board(&self, to: &str) {
		let mut sorted_stars = self.starred.clone();
		sorted_stars.sort_by(|lhs, rhs| lhs.stars.cmp(&rhs.stars));

		for message in sorted_stars.iter().take(10) {
			self.server.send_notice(to, &*&format!("{}", message)).unwrap();
		}
	}

	pub fn add_star(&mut self, starrer: &str, message: &str) {
		if let Some(star_message) = StarredMessage::from_message_content(message, starrer) {
			if let Some(star_message) = self.maybe_increase_starcount(star_message) {
				self.starred.push(star_message);
			}
		}
	}

	pub fn remove_star(&mut self, starrer: &str, message: &str) {
		if let Some(star_message) = StarredMessage::from_message_content(message, starrer) {
			if let Some(index) = self.maybe_decrease_starcount(star_message) {
				self.starred.swap_remove(index);
			}
		}
	}

	/// Incease the star count on an existing equivalent message or return the message for it to be added.
	fn maybe_increase_starcount(&mut self, to_star: StarredMessage) -> Option<StarredMessage> {
		match self.starred.iter_mut().find(|fmsg| (&fmsg.sender, &fmsg.message) == (&to_star.sender, &to_star.message)) {
			Some(ref mut existing_message) => {
				existing_message.stars += 1;
				existing_message.starrers.extend(to_star.starrers.clone());
				None
			},
			None => Some(to_star),
		}
	}

	/// Decrease the star count and remove the starrer from an existing equivalent message and return the message's index if it has 0 stars after decreasing.
	fn maybe_decrease_starcount(&mut self, to_unstar: StarredMessage) -> Option<usize> {
		self.starred.iter_mut().enumerate().find(
			|fmsg| (&fmsg.1.sender, &fmsg.1.message) == (&to_unstar.sender, &to_unstar.message)
		).and_then(|(idx, ref mut existing_message)|
			existing_message.starrers.iter().position(|starrer| starrer == &to_unstar.starrers[0]).and_then(|starrer_pos|
				if existing_message.stars == 1 {
					Some(idx)
				} else {
					existing_message.stars -= 1;
					existing_message.starrers.swap_remove(starrer_pos);
					None
				}
			)
		)
	}
}
<|endoftext|>