<commit_before>use elapsed::measure_time;

use fall_tree::{NodeType, ERROR, TextRange, FileStats, INode, TextUnit, Language};
use lex::{Token, LexRule, tokenize};

#[derive(Clone, Copy, Debug)]
pub struct TokenSequence<'a> {
    text: &'a str,
    start: usize,
    non_ws_indexes: &'a [usize],
    original_tokens: &'a [Token],
}

#[derive(Debug)]
pub enum Node {
    Leaf {
        ty: Option<NodeType>,
        token_idx: usize
    },
    Composite {
        ty: Option<NodeType>,
        children: Vec<Node>,
    }
}

impl Node {
    pub fn error() -> Node {
        Self::composite(Some(ERROR))
    }

    pub fn composite(ty: Option<NodeType>) -> Node {
        Node::Composite { ty: ty, children: Vec::new() }
    }

    pub fn success<'t>(ts: TokenSequence<'t>) -> (Node, TokenSequence<'t>) {
        (Self::composite(None), ts)
    }
}

impl<'a> TokenSequence<'a> {
    pub fn prefix(&self, suffix: TokenSequence<'a>) -> TokenSequence<'a> {
        TokenSequence {
            text: self.text,
            start: self.start,
            non_ws_indexes: &self.non_ws_indexes[..suffix.start - self.start],
            original_tokens: self.original_tokens
        }
    }

    pub fn current(&self) -> Option<Token> {
        self.non_ws_indexes.first().map(|&idx| {
            self.original_tokens[idx]
        })
    }

    pub fn bump(&self) -> (Node, TokenSequence<'a>) {
        let token = self.current().expect("Can't bump an empty token sequence");
        let node = Node::Leaf { ty: Some(token.ty), token_idx: self.non_ws_indexes[0] };
        let mut text_len = 0;
        let next_idx = self.non_ws_indexes.get(1).map(|&i| i).unwrap_or(self.original_tokens.len());
        for i in self.non_ws_indexes[0]..next_idx {
            text_len += self.original_tokens[i].len.as_u32() as usize;
        }
        let rest = TokenSequence {
            text: &self.text[text_len..],
            start: self.start + 1,
            non_ws_indexes: &self.non_ws_indexes[1..],
            original_tokens: self.original_tokens,
        };
        (node, rest)
    }

    pub fn bump_by_text(&self, ty: NodeType, text: &str) -> Option<(Node, TokenSequence<'a>)> {
        if self.text.starts_with(text) {
            let mut children = Vec::new();
            let mut leftover = TextUnit::from_usize(text.len());
            let mut rest = *self;
            while leftover > TextUnit::zero() {
                leftover -= rest.current().unwrap().len;
                let p = rest.bump();
                children.push(match p.0 {
                    Node::Leaf { ty: _, token_idx } => Node::Leaf { ty: None, token_idx: token_idx },
                    _ => unreachable!()
                });
                rest = p.1;
            }

            Some((Node::Composite { ty: Some(ty), children: children }, rest))
        } else {
            None
        }
    }
}

impl Node {
    pub fn push_child(&mut self, child: Node) {
        match *self {
            Node::Composite { ref mut children, .. } => children.push(child),
            Node::Leaf { .. } => panic!("Can't add children to a leaf node"),
        }
    }

    pub fn debug(&self, tokens: &TokenSequence) -> String {
        let (l, r) = match (self.left_idx(), self.right_idx()) {
            (Some(l), Some(r)) => (l, r),
            _ => return "EMPTY-NODE".to_owned()
        };
        let mut result = String::new();
        let mut start = tokens.original_tokens[..l].iter().map(|t| t.len).sum::<TextUnit>();
        for t in tokens.original_tokens[l..r].iter() {
            result += &tokens.text[TextRange::from_len(start, t.len)];
            start += t.len;
        }
        result
    }

    fn right_idx(&self) -> Option<usize> {
        match *self {
            Node::Leaf { token_idx, .. } => Some(token_idx),
            Node::Composite { ref children, .. } => children.iter().rev().filter_map(|n| {
                n.right_idx()
            }).next(),
        }
    }

    fn left_idx(&self) -> Option<usize> {
        match *self {
            Node::Leaf { token_idx, .. } => Some(token_idx),
            Node::Composite { ref children, .. } => match children.first() {
                None => None,
                Some(child) => child.left_idx()
            },
        }
    }
}

fn is_ws(lang: &Language, token: Token) -> bool {
    lang.node_type_info(token.ty).whitespace_like
}

pub fn parse(
    text: &str,
    lang: &Language,
    tokenizer: &[LexRule],
    parser: &Fn(TokenSequence, &mut FileStats) -> Node
) -> (FileStats, INode) {
    let mut stats = FileStats::new();
    let (lex_time, owned_tokens) = measure_time(|| tokenize(&text, tokenizer).collect::<Vec<_>>());
    stats.lexing_time = lex_time.duration();
    stats.reparsed_region = TextRange::from_to(TextUnit::zero(), TextUnit::from_usize(text.len()));
    let non_ws_indexes: Vec<usize> = owned_tokens.iter().enumerate().filter_map(|(i, &t)| {
        if is_ws(lang, t) { None } else { Some(i) }
    }).collect();

    let ws_len = owned_tokens.iter()
        .take_while(|&&t| is_ws(lang, t))
        .map(|t| t.len.as_u32() as usize)
        .sum();
    let (parse_time, node) = {
        let tokens = TokenSequence {
            text: &text[ws_len..],
            start: 0,
            non_ws_indexes: &non_ws_indexes,
            original_tokens: &owned_tokens,
        };
        measure_time(|| parser(tokens, &mut stats))
    };
    stats.parsing_time = parse_time.duration();

    let ws_node = to_ws_node(lang, node, &owned_tokens);
    let inode = ws_node.into_inode().unwrap();
    (stats, inode)
}

#[derive(Debug)]
struct WsNode {
    ty: Option<NodeType>,
    len: TextUnit,
    children: Vec<WsNode>,
    first: Option<usize>,
    last: Option<usize>
}

impl WsNode {
    fn push_child(&mut self, lang: &Language, child: WsNode, tokens: &[Token]) {
        match (self.last, child.first) {
            (Some(l), Some(r)) if l + 1 < r => {
                for idx in l + 1..r {
                    let t = tokens[idx];
                    assert!(is_ws(lang, t), "expected whitespace, got {:?}", t.ty);
                    self.push_child_raw(token_ws_node(idx, t))
                }
            }
            _ => {}
        }
        self.push_child_raw(child)
    }

    fn push_child_raw(&mut self, child: WsNode) {
        self.last = child.last.or(self.last);
        self.first = self.first.or(child.first);
        self.len += child.len;
        self.children.push(child);
    }

    fn attach_to_inode(self, parent: &mut INode) {
        if self.children.is_empty() {
            match self.ty {
                Some(ty) => parent.push_child(INode::new_leaf(ty, self.len)),
                None => parent.push_token_part(self.len),
            }
            return;
        }
        match self.into_inode() {
            Ok(node) => parent.push_child(node),
            Err(this) => {
                for child in this.children {
                    child.attach_to_inode(parent);
                }
            }
        }
    }

    fn into_inode(self) -> Result<INode, WsNode> {
        if let Some(ty) = self.ty {
            let mut node = INode::new(ty);
            for child in self.children {
                child.attach_to_inode(&mut node);
            }
            Ok(node)
        } else {
            Err(self)
        }
    }
}

fn token_ws_node(idx: usize, t: Token) -> WsNode {
    WsNode {
        ty: Some(t.ty),
        len: t.len,
        children: Vec::new(),
        first: Some(idx),
        last: Some(idx),
    }
}

fn to_ws_node(lang: &Language, file_node: Node, tokens: &[Token]) -> WsNode {
    let (ty, children) = match file_node {
        Node::Composite { ty, children, .. } => (ty.unwrap(), children),
        _ => panic!("Root node must be composite")
    };
    let mut result = WsNode {
        ty: Some(ty),
        len: TextUnit::zero(),
        children: Vec::new(),
        first: None,
        last: None,
    };

    for (i, &t) in tokens.iter().enumerate() {
        if !is_ws(lang, t) {
            break
        }
        result.push_child_raw(token_ws_node(i, t))
    }

    for child in children {
        add_child(lang, &mut result, &child, tokens)
    }
    if let Some(idx) = result.last {
        for idx in idx + 1..tokens.len() {
            let t = tokens[idx];
            assert!(is_ws(lang, t));
            result.push_child_raw(token_ws_node(idx, t))
        }
    }
    result
}

fn add_child(lang: &Language, parent: &mut WsNode, node: &Node, tokens: &[Token]) {
    match *node {
        Node::Leaf { ty, token_idx } => {
            let mut node = token_ws_node(token_idx, tokens[token_idx]);
            node.ty = ty;
            parent.push_child(lang, node, tokens)
        }
        Node::Composite { ty, ref children } => {
            let mut p = WsNode {
                ty: ty,
                len: TextUnit::zero(),
                children: Vec::new(),
                first: None,
                last: None,
            };
            for child in children {
                add_child(lang, &mut p, child, tokens);
            }
            parent.push_child(lang, p, tokens)
        }
    }
}
<commit_msg>Simplify<commit_after>use elapsed::measure_time;

use fall_tree::{NodeType, ERROR, TextRange, FileStats, INode, TextUnit, Language};
use lex::{Token, LexRule, tokenize};

#[derive(Clone, Copy, Debug)]
pub struct TokenSequence<'a> {
    text: &'a str,
    start: usize,
    non_ws_indexes: &'a [usize],
    original_tokens: &'a [Token],
}

impl<'a> TokenSequence<'a> {
    pub fn prefix(&self, suffix: TokenSequence<'a>) -> TokenSequence<'a> {
        TokenSequence {
            text: self.text,
            start: self.start,
            non_ws_indexes: &self.non_ws_indexes[..suffix.start - self.start],
            original_tokens: self.original_tokens
        }
    }

    pub fn current(&self) -> Option<Token> {
        self.non_ws_indexes.first().map(|&idx| {
            self.original_tokens[idx]
        })
    }

    pub fn bump(&self) -> (Node, TokenSequence<'a>) {
        let token = self.current().expect("Can't bump an empty token sequence");
        let node = Node::Leaf { ty: Some(token.ty), token_idx: self.non_ws_indexes[0] };
        let mut text_len = 0;
        let next_idx = self.non_ws_indexes.get(1).map(|&i| i).unwrap_or(self.original_tokens.len());
        for i in self.non_ws_indexes[0]..next_idx {
            text_len += self.original_tokens[i].len.as_u32() as usize;
        }
        let rest = TokenSequence {
            text: &self.text[text_len..],
            start: self.start + 1,
            non_ws_indexes: &self.non_ws_indexes[1..],
            original_tokens: self.original_tokens,
        };
        (node, rest)
    }

    pub fn bump_by_text(&self, ty: NodeType, text: &str) -> Option<(Node, TokenSequence<'a>)> {
        if self.text.starts_with(text) {
            let mut children = Vec::new();
            let mut leftover = TextUnit::from_usize(text.len());
            let mut rest = *self;
            while leftover > TextUnit::zero() {
                leftover -= rest.current().unwrap().len;
                let p = rest.bump();
                children.push(match p.0 {
                    Node::Leaf { ty: _, token_idx } => Node::Leaf { ty: None, token_idx: token_idx },
                    _ => unreachable!()
                });
                rest = p.1;
            }

            Some((Node::Composite { ty: Some(ty), children: children }, rest))
        } else {
            None
        }
    }
}

#[derive(Debug)]
pub enum Node {
    Leaf {
        ty: Option<NodeType>,
        token_idx: usize
    },
    Composite {
        ty: Option<NodeType>,
        children: Vec<Node>,
    }
}

impl Node {
    pub fn error() -> Node {
        Self::composite(Some(ERROR))
    }

    pub fn composite(ty: Option<NodeType>) -> Node {
        Node::Composite { ty: ty, children: Vec::new() }
    }

    pub fn success<'t>(ts: TokenSequence<'t>) -> (Node, TokenSequence<'t>) {
        (Self::composite(None), ts)
    }

    pub fn push_child(&mut self, child: Node) {
        match *self {
            Node::Composite { ref mut children, .. } => children.push(child),
            Node::Leaf { .. } => panic!("Can't add children to a leaf node"),
        }
    }

    pub fn debug(&self, tokens: &TokenSequence) -> String {
        let (l, r) = match (self.left_idx(), self.right_idx()) {
            (Some(l), Some(r)) => (l, r),
            _ => return "EMPTY-NODE".to_owned()
        };
        let mut result = String::new();
        let mut start = tokens.original_tokens[..l].iter().map(|t| t.len).sum::<TextUnit>();
        for t in tokens.original_tokens[l..r].iter() {
            result += &tokens.text[TextRange::from_len(start, t.len)];
            start += t.len;
        }
        result
    }

    fn right_idx(&self) -> Option<usize> {
        match *self {
            Node::Leaf { token_idx, .. } => Some(token_idx),
            Node::Composite { ref children, .. } =>
                children.iter().rev()
                    .filter_map(|n| n.right_idx())
                    .next(),
        }
    }

    fn left_idx(&self) -> Option<usize> {
        match *self {
            Node::Leaf { token_idx, .. } => Some(token_idx),
            Node::Composite { ref children, .. } =>
                children.first()
                    .and_then(|child| child.left_idx()),
        }
    }
}

fn is_ws(lang: &Language, token: Token) -> bool {
    lang.node_type_info(token.ty).whitespace_like
}

pub fn parse(
    text: &str,
    lang: &Language,
    tokenizer: &[LexRule],
    parser: &Fn(TokenSequence, &mut FileStats) -> Node
) -> (FileStats, INode) {
    let mut stats = FileStats::new();
    let (lex_time, owned_tokens) = measure_time(|| tokenize(&text, tokenizer).collect::<Vec<_>>());
    stats.lexing_time = lex_time.duration();
    stats.reparsed_region = TextRange::from_to(TextUnit::zero(), TextUnit::from_usize(text.len()));
    let non_ws_indexes: Vec<usize> = owned_tokens.iter().enumerate().filter_map(|(i, &t)| {
        if is_ws(lang, t) { None } else { Some(i) }
    }).collect();

    let ws_len = owned_tokens.iter()
        .take_while(|&&t| is_ws(lang, t))
        .map(|t| t.len.as_u32() as usize)
        .sum();
    let (parse_time, node) = {
        let tokens = TokenSequence {
            text: &text[ws_len..],
            start: 0,
            non_ws_indexes: &non_ws_indexes,
            original_tokens: &owned_tokens,
        };
        measure_time(|| parser(tokens, &mut stats))
    };
    stats.parsing_time = parse_time.duration();

    let ws_node = to_ws_node(lang, node, &owned_tokens);
    let inode = ws_node.into_inode().unwrap();
    (stats, inode)
}

#[derive(Debug)]
struct WsNode {
    ty: Option<NodeType>,
    len: TextUnit,
    children: Vec<WsNode>,
    first: Option<usize>,
    last: Option<usize>
}

impl WsNode {
    fn push_child(&mut self, lang: &Language, child: WsNode, tokens: &[Token]) {
        match (self.last, child.first) {
            (Some(l), Some(r)) if l + 1 < r => {
                for idx in l + 1..r {
                    let t = tokens[idx];
                    assert!(is_ws(lang, t), "expected whitespace, got {:?}", t.ty);
                    self.push_child_raw(token_ws_node(idx, t))
                }
            }
            _ => {}
        }
        self.push_child_raw(child)
    }

    fn push_child_raw(&mut self, child: WsNode) {
        self.last = child.last.or(self.last);
        self.first = self.first.or(child.first);
        self.len += child.len;
        self.children.push(child);
    }

    fn attach_to_inode(self, parent: &mut INode) {
        if self.children.is_empty() {
            match self.ty {
                Some(ty) => parent.push_child(INode::new_leaf(ty, self.len)),
                None => parent.push_token_part(self.len),
            }
            return;
        }
        match self.into_inode() {
            Ok(node) => parent.push_child(node),
            Err(this) => {
                for child in this.children {
                    child.attach_to_inode(parent);
                }
            }
        }
    }

    fn into_inode(self) -> Result<INode, WsNode> {
        if let Some(ty) = self.ty {
            let mut node = INode::new(ty);
            for child in self.children {
                child.attach_to_inode(&mut node);
            }
            Ok(node)
        } else {
            Err(self)
        }
    }
}

fn token_ws_node(idx: usize, t: Token) -> WsNode {
    WsNode {
        ty: Some(t.ty),
        len: t.len,
        children: Vec::new(),
        first: Some(idx),
        last: Some(idx),
    }
}

fn to_ws_node(lang: &Language, file_node: Node, tokens: &[Token]) -> WsNode {
    let (ty, children) = match file_node {
        Node::Composite { ty, children, .. } => (ty.unwrap(), children),
        _ => panic!("Root node must be composite")
    };
    let mut result = WsNode {
        ty: Some(ty),
        len: TextUnit::zero(),
        children: Vec::new(),
        first: None,
        last: None,
    };

    for (i, &t) in tokens.iter().enumerate() {
        if !is_ws(lang, t) {
            break
        }
        result.push_child_raw(token_ws_node(i, t))
    }

    for child in children {
        add_child(lang, &mut result, &child, tokens)
    }
    if let Some(idx) = result.last {
        for idx in idx + 1..tokens.len() {
            let t = tokens[idx];
            assert!(is_ws(lang, t));
            result.push_child_raw(token_ws_node(idx, t))
        }
    }
    result
}

fn add_child(lang: &Language, parent: &mut WsNode, node: &Node, tokens: &[Token]) {
    match *node {
        Node::Leaf { ty, token_idx } => {
            let mut node = token_ws_node(token_idx, tokens[token_idx]);
            node.ty = ty;
            parent.push_child(lang, node, tokens)
        }
        Node::Composite { ty, ref children } => {
            let mut p = WsNode {
                ty: ty,
                len: TextUnit::zero(),
                children: Vec::new(),
                first: None,
                last: None,
            };
            for child in children {
                add_child(lang, &mut p, child, tokens);
            }
            parent.push_child(lang, p, tokens)
        }
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt;
use std::io;
use std::str;

use crate::wire_format::WireType;

pub type ProtobufResult<T> = Result<T, ProtobufError>;

/// Enum values added here for diagnostic purposes.
/// Users should not depend on specific values.
#[derive(Debug)]
pub enum WireError {
    UnexpectedEof,
    UnexpectedWireType(WireType),
    IncorrectTag(u32),
    // unused since https://github.com/stepancheg/rust-protobuf/issues/318
    IncompleteMap,
    IncorrectVarint,
    Utf8Error,
    InvalidEnumValue(i32),
    OverRecursionLimit,
    TruncatedMessage,
    Other,
}

#[derive(Debug)]
pub enum ProtobufError {
    IoError(io::Error),
    WireError(WireError),
    Utf8(str::Utf8Error),
    /// Not all required fields of message set.
    MessageNotInitialized(&'static str),
}

impl fmt::Display for ProtobufError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }
}

impl Error for ProtobufError {
    fn description(&self) -> &str {
        match self {
            // not sure that cause should be included in message
            &ProtobufError::IoError(ref e) => e.description(),
            &ProtobufError::WireError(ref e) => match *e {
                WireError::Utf8Error => "invalid UTF-8 sequence",
                WireError::UnexpectedWireType(..) => "unexpected wire type",
                WireError::InvalidEnumValue(..) => "invalid enum value",
                WireError::IncorrectTag(..) => "incorrect tag",
                WireError::IncorrectVarint => "incorrect varint",
                WireError::IncompleteMap => "incomplete map",
                WireError::UnexpectedEof => "unexpected EOF",
                WireError::OverRecursionLimit => "over recursion limit",
                WireError::TruncatedMessage => "truncated message",
                WireError::Other => "other error",
            },
            &ProtobufError::Utf8(ref e) => &e.description(),
            &ProtobufError::MessageNotInitialized { .. } => "not all message fields set",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &ProtobufError::IoError(ref e) => Some(e),
            &ProtobufError::Utf8(ref e) => Some(e),
            &ProtobufError::WireError(..) => None,
            &ProtobufError::MessageNotInitialized { .. } => None,
        }
    }
}

impl From<io::Error> for ProtobufError {
    fn from(err: io::Error) -> Self {
        ProtobufError::IoError(err)
    }
}

impl From<str::Utf8Error> for ProtobufError {
    fn from(err: str::Utf8Error) -> Self {
        ProtobufError::Utf8(err)
    }
}

impl From<ProtobufError> for io::Error {
    fn from(err: ProtobufError) -> Self {
        match err {
            ProtobufError::IoError(e) => e,
            ProtobufError::WireError(e) => {
                io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e))
            }
            ProtobufError::MessageNotInitialized(message) => io::Error::new(
                io::ErrorKind::InvalidInput,
                ProtobufError::MessageNotInitialized(message),
            ),
            e => io::Error::new(io::ErrorKind::Other, Box::new(e)),
        }
    }
}
<commit_msg>ProtobufError rustdoc<commit_after>use std::error::Error;
use std::fmt;
use std::io;
use std::str;

use crate::wire_format::WireType;

pub type ProtobufResult<T> = Result<T, ProtobufError>;

/// Enum values added here for diagnostic purposes.
/// Users should not depend on specific values.
#[derive(Debug)]
pub enum WireError {
    UnexpectedEof,
    UnexpectedWireType(WireType),
    IncorrectTag(u32),
    // unused since https://github.com/stepancheg/rust-protobuf/issues/318
    IncompleteMap,
    IncorrectVarint,
    Utf8Error,
    InvalidEnumValue(i32),
    OverRecursionLimit,
    TruncatedMessage,
    Other,
}

/// Generic protobuf error
#[derive(Debug)]
pub enum ProtobufError {
    /// I/O error when reading or writing
    IoError(io::Error),
    /// Malformed input
    WireError(WireError),
    /// Protocol contains a string which is not valid UTF-8 string
    Utf8(str::Utf8Error),
    /// Not all required fields of message set.
    MessageNotInitialized(&'static str),
}

impl fmt::Display for ProtobufError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }
}

impl Error for ProtobufError {
    fn description(&self) -> &str {
        match self {
            // not sure that cause should be included in message
            &ProtobufError::IoError(ref e) => e.description(),
            &ProtobufError::WireError(ref e) => match *e {
                WireError::Utf8Error => "invalid UTF-8 sequence",
                WireError::UnexpectedWireType(..) => "unexpected wire type",
                WireError::InvalidEnumValue(..) => "invalid enum value",
                WireError::IncorrectTag(..) => "incorrect tag",
                WireError::IncorrectVarint => "incorrect varint",
                WireError::IncompleteMap => "incomplete map",
                WireError::UnexpectedEof => "unexpected EOF",
                WireError::OverRecursionLimit => "over recursion limit",
                WireError::TruncatedMessage => "truncated message",
                WireError::Other => "other error",
            },
            &ProtobufError::Utf8(ref e) => &e.description(),
            &ProtobufError::MessageNotInitialized { .. } => "not all message fields set",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self {
            &ProtobufError::IoError(ref e) => Some(e),
            &ProtobufError::Utf8(ref e) => Some(e),
            &ProtobufError::WireError(..) => None,
            &ProtobufError::MessageNotInitialized { .. } => None,
        }
    }
}

impl From<io::Error> for ProtobufError {
    fn from(err: io::Error) -> Self {
        ProtobufError::IoError(err)
    }
}

impl From<str::Utf8Error> for ProtobufError {
    fn from(err: str::Utf8Error) -> Self {
        ProtobufError::Utf8(err)
    }
}

impl From<ProtobufError> for io::Error {
    fn from(err: ProtobufError) -> Self {
        match err {
            ProtobufError::IoError(e) => e,
            ProtobufError::WireError(e) => {
                io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e))
            }
            ProtobufError::MessageNotInitialized(message) => io::Error::new(
                io::ErrorKind::InvalidInput,
                ProtobufError::MessageNotInitialized(message),
            ),
            e => io::Error::new(io::ErrorKind::Other, Box::new(e)),
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp;
use std::borrow::Borrow;

use std::io;
use std::io::BufReader;
use std::io::prelude::*;

use std::ptr;

/// A struct implementing `Read` that will yield bytes until it sees a given sequence.
#[derive(Debug)]
pub struct BoundaryReader<R> {
    buffer: BufReader<R>,
    boundary: Vec<u8>,
    search_idx: usize,
    boundary_read: bool,
}

impl<R> BoundaryReader<R> where R: Read {
    #[doc(hidden)]
    pub fn from_reader<B: Into<Vec<u8>>>(reader: R, boundary: B) -> BoundaryReader<R> {
        BoundaryReader {
            buffer: BufReader::new(reader),
            boundary: boundary.into(),
            search_idx: 0,
            boundary_read: false,
        }
    }

    fn read_to_boundary(&mut self) -> io::Result<&[u8]> {
        let buf = try!(self.buffer.fill_buf());

        if !self.boundary_read {
            let boundary_0 = self.boundary[0];

            // Style advice requested
            for (search_idx, maybe_boundary)
            in buf[self.search_idx..].windows(self.boundary.len()).enumerate()
                .filter(|&(_, window)| window[0] == boundary_0)
            {
                self.boundary_read = self.boundary == maybe_boundary;
                self.search_idx += search_idx;
            }
        }

        Ok(&buf[..self.search_idx])
    }

    #[doc(hidden)]
    pub fn consume_boundary(&mut self) -> io::Result<()> {
        while !self.boundary_read {
            let buf_len = try!(self.read_to_boundary()).len();
            self.consume(buf_len);
        }

        let consume_amt = {
            let boundary_len = self.boundary.len();
            let buf = try!(self.read_to_boundary());
            buf.len() + boundary_len
        };

        self.buffer.consume(consume_amt);
        self.search_idx = 0;
        self.boundary_read = false;

        Ok(())
    }

    #[allow(unused)]
    #[doc(hidden)]
    pub fn set_boundary<B: Into<Vec<u8>>>(&mut self, boundary: B) {
        self.boundary = boundary.into();
    }
}

impl<R: Read> Borrow<R> for BoundaryReader<R> {
    fn borrow(&self) -> &R {
        self.buffer.get_ref()
    }
}

impl<R> Read for BoundaryReader<R> where R: Read {
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        let consume_len = {
            let buf = try!(self.read_to_boundary());
            let trunc_len = cmp::min(buf.len(), out.len());
            copy_bytes(&buf[..trunc_len], out);
            trunc_len
        };

        self.consume(consume_len);

        Ok(consume_len)
    }
}

impl<R> BufRead for BoundaryReader<R> where R: Read {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.read_to_boundary()
    }

    fn consume(&mut self, amt: usize) {
        let true_amt = cmp::min(amt, self.search_idx);
        self.buffer.consume(true_amt);
        self.search_idx -= true_amt;
    }
}

// copied from `std::slice::bytes` due to unstable
fn copy_bytes(src: &[u8], dst: &mut [u8]) {
    let len_src = src.len();
    assert!(dst.len() >= len_src);
    // `dst` is unaliasable, so we know statically it doesn't overlap with `src`.
    unsafe {
        ptr::copy_nonoverlapping(
            src.as_ptr(),
            dst.as_mut_ptr(),
            len_src
        );
    }
}

#[test]
fn test_boundary() {
    use std::io::BufReader;

    const BOUNDARY: &'static str = "--boundary\r\n";
    const TEST_VAL: &'static str = "\r
--boundary\r
dashed-value-1\r
--boundary\r
dashed-value-2\r
--boundary\r
";

    let src = &mut TEST_VAL.as_bytes();
    let mut reader = BoundaryReader::from_reader(src, BOUNDARY);

    let ref mut buf = String::new();

    debug!("Read 1");
    let _ = reader.read_to_string(buf).unwrap();
    debug!("{}", buf);
    assert!(buf.trim().is_empty());

    buf.clear();

    debug!("Consume 1");
    reader.consume_boundary().unwrap();

    debug!("Read 2");
    let _ = reader.read_to_string(buf).unwrap();
    assert_eq!(buf.trim(), "dashed-value-1");
    buf.clear();

    debug!("Consume 2");
    reader.consume_boundary().unwrap();

    debug!("Read 3");
    let _ = reader.read_to_string(buf).unwrap();
    assert_eq!(buf.trim(), "dashed-value-2");

    debug!("Consume 3");
    reader.consume_boundary().unwrap();
}
<commit_msg>Clean up iterator expression<commit_after>use std::cmp;
use std::borrow::Borrow;

use std::io;
use std::io::BufReader;
use std::io::prelude::*;

use std::ptr;

/// A struct implementing `Read` that will yield bytes until it sees a given sequence.
#[derive(Debug)]
pub struct BoundaryReader<R> {
    buffer: BufReader<R>,
    boundary: Vec<u8>,
    search_idx: usize,
    boundary_read: bool,
}

impl<R> BoundaryReader<R> where R: Read {
    #[doc(hidden)]
    pub fn from_reader<B: Into<Vec<u8>>>(reader: R, boundary: B) -> BoundaryReader<R> {
        BoundaryReader {
            buffer: BufReader::new(reader),
            boundary: boundary.into(),
            search_idx: 0,
            boundary_read: false,
        }
    }

    fn read_to_boundary(&mut self) -> io::Result<&[u8]> {
        let buf = try!(self.buffer.fill_buf());

        if !self.boundary_read {
            let boundary_0 = self.boundary[0];

            let lookahead_iter = buf[self.search_idx..].windows(self.boundary.len()).enumerate();

            for (search_idx, maybe_boundary) in lookahead_iter {
                if maybe_boundary[0] == self.boundary[0] {
                    self.boundary_read = self.boundary == maybe_boundary;
                    self.search_idx += search_idx;
                }
            }
        }

        Ok(&buf[..self.search_idx])
    }

    #[doc(hidden)]
    pub fn consume_boundary(&mut self) -> io::Result<()> {
        while !self.boundary_read {
            let buf_len = try!(self.read_to_boundary()).len();
            self.consume(buf_len);
        }

        let consume_amt = {
            let boundary_len = self.boundary.len();
            let buf = try!(self.read_to_boundary());
            buf.len() + boundary_len
        };

        self.buffer.consume(consume_amt);
        self.search_idx = 0;
        self.boundary_read = false;

        Ok(())
    }

    #[allow(unused)]
    #[doc(hidden)]
    pub fn set_boundary<B: Into<Vec<u8>>>(&mut self, boundary: B) {
        self.boundary = boundary.into();
    }
}

impl<R: Read> Borrow<R> for BoundaryReader<R> {
    fn borrow(&self) -> &R {
        self.buffer.get_ref()
    }
}

impl<R> Read for BoundaryReader<R> where R: Read {
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        let consume_len = {
            let buf = try!(self.read_to_boundary());
            let trunc_len = cmp::min(buf.len(), out.len());
            copy_bytes(&buf[..trunc_len], out);
            trunc_len
        };

        self.consume(consume_len);

        Ok(consume_len)
    }
}

impl<R> BufRead for BoundaryReader<R> where R: Read {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.read_to_boundary()
    }

    fn consume(&mut self, amt: usize) {
        let true_amt = cmp::min(amt, self.search_idx);
        self.buffer.consume(true_amt);
        self.search_idx -= true_amt;
    }
}

// copied from `std::slice::bytes` due to unstable
fn copy_bytes(src: &[u8], dst: &mut [u8]) {
    let len_src = src.len();
    assert!(dst.len() >= len_src);
    // `dst` is unaliasable, so we know statically it doesn't overlap with `src`.
    unsafe {
        ptr::copy_nonoverlapping(
            src.as_ptr(),
            dst.as_mut_ptr(),
            len_src
        );
    }
}

#[test]
fn test_boundary() {
    use std::io::BufReader;

    const BOUNDARY: &'static str = "--boundary\r\n";
    const TEST_VAL: &'static str = "\r
--boundary\r
dashed-value-1\r
--boundary\r
dashed-value-2\r
--boundary\r
";

    let src = &mut TEST_VAL.as_bytes();
    let mut reader = BoundaryReader::from_reader(src, BOUNDARY);

    let ref mut buf = String::new();

    debug!("Read 1");
    let _ = reader.read_to_string(buf).unwrap();
    debug!("{}", buf);
    assert!(buf.trim().is_empty());

    buf.clear();

    debug!("Consume 1");
    reader.consume_boundary().unwrap();

    debug!("Read 2");
    let _ = reader.read_to_string(buf).unwrap();
    assert_eq!(buf.trim(), "dashed-value-1");
    buf.clear();

    debug!("Consume 2");
    reader.consume_boundary().unwrap();

    debug!("Read 3");
    let _ = reader.read_to_string(buf).unwrap();
    assert_eq!(buf.trim(), "dashed-value-2");

    debug!("Consume 3");
    reader.consume_boundary().unwrap();
}
<|endoftext|>


<commit_before>use std::iter::FromIterator;
use std::iter::repeat;

use set1::challenge2::fixed_xor;
use set1::utils::bytes_to_hex;

fn repeating_xor(text: &[u8], key: &[u8]) -> String {
    bytes_to_hex(&fixed_xor(text,
                            &(repeat(key)
                                .take(text.len() / 3 + 1)
                                .flat_map(|x| x.iter().cloned())
                                .collect::<Vec<_>>())))

}

#[test]
fn test_repeating_xor() {
    assert_eq!(repeating_xor("Burning 'em, if you ain't quick and nimble\nI go crazy when I hear a cymbal".as_bytes(),
                             "ICE".as_bytes()),
               "0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a31\
               24333a653e2b2027630c692b20283165286326302e27282f")
}
<commit_msg>set1: Remove unneeded import in challenge 5<commit_after>use std::iter::repeat;

use set1::challenge2::fixed_xor;
use set1::utils::bytes_to_hex;

fn repeating_xor(text: &[u8], key: &[u8]) -> String {
    bytes_to_hex(&fixed_xor(text,
                            &(repeat(key)
                                .take(text.len() / 3 + 1)
                                .flat_map(|x| x.iter().cloned())
                                .collect::<Vec<_>>())))

}

#[test]
fn test_repeating_xor() {
    assert_eq!(repeating_xor("Burning 'em, if you ain't quick and nimble\nI go crazy when I hear a cymbal".as_bytes(),
                             "ICE".as_bytes()),
               "0b3637272a2b2e63622c2e69692a23693a2a3c6324202d623d63343c2a26226324272765272a282b2f20430a652e2c652a31\
               24333a653e2b2027630c692b20283165286326302e27282f")
}
<|endoftext|>


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

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

struct Observer {
    read_overlapped: *mut ::miow::Overlapped,
    write_overlapped: *mut ::miow::Overlapped,
    read_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
    write_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
}

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

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

pub struct Reactor {
    cp: ::miow::iocp::CompletionPort,
    observers: HandleTable<Observer>,
    statuses: Vec<::miow::iocp::CompletionStatus>,
}

impl Reactor {
    pub fn new() -> Result<Reactor, ::std::io::Error> {
        Ok(Reactor {
            cp: try!(::miow::iocp::CompletionPort::new(1)),
            observers: HandleTable::new(),
            statuses: vec![::miow::iocp::CompletionStatus::zero(); 1024]
        })
    }

    pub fn run_once(&mut self, maybe_timeout: Option<::time::Duration>)
                    -> Result<(), ::std::io::Error>
    {
        let timeout = maybe_timeout.map(|t| t.num_milliseconds() as u32); // XXX check for overflow

        //let mut statu

        {
            let statuses = try!(self.cp.get_many(&mut self.statuses[..], timeout));
            for status in statuses {
                println!("got token: {}", status.token());
            }
        }
        unimplemented!()
    }

    fn add_socket<T>(&mut self, sock: &T,
                     read_overlapped: *mut ::miow::Overlapped,
                     write_overlapped: *mut ::miow::Overlapped)
                     -> Result<Handle, ::std::io::Error>
        where T : ::std::os::windows::io::AsRawSocket
    {
        let observer = Observer {
            read_overlapped: read_overlapped,
            write_overlapped: write_overlapped,
            read_fulfiller: None,
            write_fulfiller: None,
        };
        let handle = self.observers.push(observer);
        try!(self.cp.add_socket(handle.val, sock));
        Ok(handle)
    }
}

#[derive(Clone)]
pub struct SocketAddressInner {
    reactor: Rc<RefCell<Reactor>>,
    addr: ::std::net::SocketAddr,
}

impl SocketAddressInner {
    pub fn new_tcp(reactor: Rc<RefCell<Reactor>>, addr: ::std::net::SocketAddr)
                   -> SocketAddressInner
    {
        SocketAddressInner {
            reactor: reactor,
            addr: addr,
        }
    }

    pub fn connect(&self) -> Promise<SocketStreamInner, ::std::io::Error> {
        use miow::net::TcpBuilderExt;
        let builder = match self.addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };
        let mut overlapped = ::miow::Overlapped::zero();
        let (stream, ready) = unsafe {
            pry!(builder.connect_overlapped(&self.addr, &mut overlapped))
        };

        if ready {
            Promise::ok(SocketStreamInner::new(self.reactor.clone(), stream))
        } else {
            unimplemented!()
        }
    }

    pub fn listen(&mut self) -> Result<SocketListenerInner, ::std::io::Error> {
        let listener = try!(::std::net::TcpListener::bind(self.addr));
        Ok(SocketListenerInner::new(self.reactor.clone(), listener, self.addr))
    }
}

pub struct SocketListenerInner {
    reactor: Rc<RefCell<Reactor>>,
    listener: ::std::net::TcpListener,
    addr: ::std::net::SocketAddr,
    read_overlapped: ::miow::Overlapped,
    pub queue: Option<Promise<(),()>>,
}

impl SocketListenerInner {
    fn new(reactor: Rc<RefCell<Reactor>>, listener: ::std::net::TcpListener,
           addr: ::std::net::SocketAddr)
           -> SocketListenerInner
    {
        SocketListenerInner {
            reactor: reactor,
            listener: listener,
            addr: addr,
            read_overlapped: ::miow::Overlapped::zero(),
            queue: None,
        }
    }

    pub fn accept_internal(inner: Rc<RefCell<SocketListenerInner>>)
                           -> Promise<SocketStreamInner, ::std::io::Error>
    {
        use miow::net::TcpListenerExt;
        let builder = match inner.borrow().addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };

        let mut accept_addrs = ::miow::net::AcceptAddrsBuf::new();

        let &mut SocketListenerInner {
            reactor: ref reactor,
            listener: ref mut listener,
            read_overlapped: ref mut read_overlapped,
            ..
        } =  &mut *inner.borrow_mut();

        let (stream, ready) = unsafe {
            pry!(listener.accept_overlapped(&builder,
                                            &mut accept_addrs,
                                            read_overlapped))
        };

        if ready {
            Promise::ok(SocketStreamInner::new(reactor.clone(), stream))
        } else {
            let handle = pry!(reactor.borrow_mut().add_socket(&stream,
                                                              read_overlapped,
                                                              ::std::ptr::null_mut()));

            let reactor2 = reactor.clone();
            reactor.borrow_mut().observers[handle].when_read_done().map(move |_| {
                Ok(SocketStreamInner::new(reactor2, stream))
            })
        }
    }
}

pub struct SocketStreamInner {
    reactor: Rc<RefCell<Reactor>>,
    stream: ::std::net::TcpStream,
    pub read_queue: Option<Promise<(),()>>,
    pub write_queue: Option<Promise<(),()>>,
}

impl SocketStreamInner {
    fn new(reactor: Rc<RefCell<Reactor>>, stream: ::std::net::TcpStream) -> SocketStreamInner {
        SocketStreamInner {
            reactor: reactor,
            stream: stream,
            read_queue: None,
            write_queue: None,
        }
    }

    pub fn try_read_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                                mut buf: T,
                                already_read: usize,
                                min_bytes: usize)
                                ->Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        use ::miow::net::TcpStreamExt;
        let mut overlapped = ::miow::Overlapped::zero();
        let pending = unsafe {
            pry!(inner.borrow().stream.read_overlapped(buf.as_mut(), &mut overlapped))
        };
        unimplemented!()
    }

    pub fn write_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                             buf: T,
                             mut already_written: usize) -> Promise<T, ::std::io::Error>
        where T: AsRef<[u8]>
    {
        use ::miow::net::TcpStreamExt;
        let mut overlapped = ::miow::Overlapped::zero();
        let pending = unsafe {
            pry!(inner.borrow().stream.write_overlapped(buf.as_ref(), &mut overlapped))
        };

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

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

struct Observer {
    read_overlapped: *mut ::miow::Overlapped,
    write_overlapped: *mut ::miow::Overlapped,
    read_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
    write_fulfiller: Option<PromiseFulfiller<u32, ::std::io::Error>>,
}

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

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

pub struct Reactor {
    cp: ::miow::iocp::CompletionPort,
    observers: HandleTable<Observer>,
    statuses: Vec<::miow::iocp::CompletionStatus>,
}

impl Reactor {
    pub fn new() -> Result<Reactor, ::std::io::Error> {
        Ok(Reactor {
            cp: try!(::miow::iocp::CompletionPort::new(1)),
            observers: HandleTable::new(),
            statuses: vec![::miow::iocp::CompletionStatus::zero(); 1024]
        })
    }

    pub fn run_once(&mut self, maybe_timeout: Option<::time::Duration>)
                    -> Result<(), ::std::io::Error>
    {
        let timeout = maybe_timeout.map(|t| t.num_milliseconds() as u32); // XXX check for overflow

        //let mut statu

        {
            let statuses = try!(self.cp.get_many(&mut self.statuses[..], timeout));
            for status in statuses {
                println!("got token: {}", status.token());
            }
        }
        unimplemented!()
    }

    fn add_socket<T>(&mut self, sock: &T,
                     read_overlapped: *mut ::miow::Overlapped,
                     write_overlapped: *mut ::miow::Overlapped)
                     -> Result<Handle, ::std::io::Error>
        where T : ::std::os::windows::io::AsRawSocket
    {
        let observer = Observer {
            read_overlapped: read_overlapped,
            write_overlapped: write_overlapped,
            read_fulfiller: None,
            write_fulfiller: None,
        };
        let handle = self.observers.push(observer);
        try!(self.cp.add_socket(handle.val, sock));
        Ok(handle)
    }
}

#[derive(Clone)]
pub struct SocketAddressInner {
    reactor: Rc<RefCell<Reactor>>,
    addr: ::std::net::SocketAddr,
}

impl SocketAddressInner {
    pub fn new_tcp(reactor: Rc<RefCell<Reactor>>, addr: ::std::net::SocketAddr)
                   -> SocketAddressInner
    {
        SocketAddressInner {
            reactor: reactor,
            addr: addr,
        }
    }

    pub fn connect(&self) -> Promise<SocketStreamInner, ::std::io::Error> {
        use miow::net::TcpBuilderExt;
        let builder = match self.addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };
        let mut overlapped = ::miow::Overlapped::zero();
        let (stream, ready) = unsafe {
            pry!(builder.connect_overlapped(&self.addr, &mut overlapped))
        };

        if ready {
            Promise::ok(SocketStreamInner::new(self.reactor.clone(), stream))
        } else {
            unimplemented!()
        }
    }

    pub fn listen(&mut self) -> Result<SocketListenerInner, ::std::io::Error> {
        let listener = try!(::std::net::TcpListener::bind(self.addr));
        Ok(SocketListenerInner::new(self.reactor.clone(), listener, self.addr))
    }
}

pub struct SocketListenerInner {
    reactor: Rc<RefCell<Reactor>>,
    listener: ::std::net::TcpListener,
    addr: ::std::net::SocketAddr,
    read_overlapped: ::miow::Overlapped,
    pub queue: Option<Promise<(),()>>,
}

impl SocketListenerInner {
    fn new(reactor: Rc<RefCell<Reactor>>, listener: ::std::net::TcpListener,
           addr: ::std::net::SocketAddr)
           -> SocketListenerInner
    {
        SocketListenerInner {
            reactor: reactor,
            listener: listener,
            addr: addr,
            read_overlapped: ::miow::Overlapped::zero(),
            queue: None,
        }
    }

    pub fn accept_internal(inner: Rc<RefCell<SocketListenerInner>>)
                           -> Promise<SocketStreamInner, ::std::io::Error>
    {
        use miow::net::TcpListenerExt;
        let builder = match inner.borrow().addr {
            ::std::net::SocketAddr::V4(_) => pry!(::net2::TcpBuilder::new_v4()),
            ::std::net::SocketAddr::V6(_) => pry!(::net2::TcpBuilder::new_v6()),
        };

        let mut accept_addrs = ::miow::net::AcceptAddrsBuf::new();

        let &mut SocketListenerInner {
            reactor: ref reactor,
            listener: ref mut listener,
            read_overlapped: ref mut read_overlapped,
            ..
        } =  &mut *inner.borrow_mut();

        let (stream, ready) = unsafe {
            pry!(listener.accept_overlapped(&builder,
                                            &mut accept_addrs,
                                            read_overlapped))
        };

        if ready {
            Promise::ok(SocketStreamInner::new(reactor.clone(), stream))
        } else {
            let handle = pry!(reactor.borrow_mut().add_socket(listener,
                                                              read_overlapped,
                                                              ::std::ptr::null_mut()));

            let reactor2 = reactor.clone();
            reactor.borrow_mut().observers[handle].when_read_done().map(move |_| {
                Ok(SocketStreamInner::new(reactor2, stream))
            })
        }
    }
}

pub struct SocketStreamInner {
    reactor: Rc<RefCell<Reactor>>,
    stream: ::std::net::TcpStream,
    pub read_queue: Option<Promise<(),()>>,
    pub write_queue: Option<Promise<(),()>>,
}

impl SocketStreamInner {
    fn new(reactor: Rc<RefCell<Reactor>>, stream: ::std::net::TcpStream) -> SocketStreamInner {
        SocketStreamInner {
            reactor: reactor,
            stream: stream,
            read_queue: None,
            write_queue: None,
        }
    }

    pub fn try_read_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                                mut buf: T,
                                already_read: usize,
                                min_bytes: usize)
                                ->Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        use ::miow::net::TcpStreamExt;
        let mut overlapped = ::miow::Overlapped::zero();
        let pending = unsafe {
            pry!(inner.borrow().stream.read_overlapped(buf.as_mut(), &mut overlapped))
        };
        unimplemented!()
    }

    pub fn write_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                             buf: T,
                             mut already_written: usize) -> Promise<T, ::std::io::Error>
        where T: AsRef<[u8]>
    {
        use ::miow::net::TcpStreamExt;
        let mut overlapped = ::miow::Overlapped::zero();
        let pending = unsafe {
            pry!(inner.borrow().stream.write_overlapped(buf.as_ref(), &mut overlapped))
        };

        unimplemented!()
    }
}
<|endoftext|>


<commit_before>use super::Vector;
use super::Vector3;

pub struct Vector3f {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

impl Vector<f32> for Vector3f {
    fn add(&mut self, v: &Vector3f) -> &mut Vector3f {
        self.x += v.x;
        self.y += v.y;
        self.z += v.z;
        self
    }

    fn add_into(&self, v: &Vector3f, dest: &mut Vector3f) {
        dest.x = self.x + v.x;
        dest.y = self.y + v.y;
        dest.z = self.z + v.z;
    }

    fn angle(&self, v: &Vector3f) -> f32 {
        unimplemented!()
    }

    fn angle_cos(&self, v: &Vector3f) -> f32 {
        unimplemented!()
    }

    fn distance(&self, v: &Vector3f) -> f32 {
        self.distance_squared(v).sqrt()
    }

    fn distance_squared(&self, v: &Vector3f) -> f32 {
        let dx = self.x - v.x;
        let dy = self.y - v.y;
        let dz = self.z - v.z;
        (dx * dx) + (dy * dy) + (dz * dz)
    }

    fn dot(&self, v: &Vector3f) -> f32 {
        (self.x * v.x) + (self.y * v.y) + (self.z * v.z)
    }

    fn fma_scalar(&mut self, a: f32, b: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn fma_scalar_into(&self, a: f32, b: &Vector3f, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn fma_vector(&mut self, a: &Vector3f, b: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn fma_vector_into(&self, a: &Vector3f, b: &Vector3f, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn length(&self) -> f32 {
        unimplemented!()
    }

    fn length_squared(&self) -> f32 {
        unimplemented!()
    }

    fn lerp(&mut self, other: &Vector3f, t: f32) -> &mut Vector3f {
        unimplemented!()
    }

    fn lerp_into(&self, other: &Vector3f, t: f32, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn mul_scalar(&mut self, s: f32) -> &mut Vector3f {
        unimplemented!()
    }

    fn mul_scalar_into(&self, s: f32, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn mul_vector(&mut self, v: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn mul_vector_into(&self, v: &Vector3f, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn negate(&mut self) -> &mut Vector3f {
        unimplemented!()
    }

    fn negate_into(&self, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn normalize(&mut self) -> &mut Vector3f {
        unimplemented!()
    }

    fn normalize_into(&self, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn set(&mut self, v: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn sub(&mut self, v: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn sub_into(&self, v: &Vector3f, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn zero(&mut self) -> &mut Vector3f {
        unimplemented!()
    }
}

impl Vector3<f32> for Vector3f {
    fn new(x: f32, y: f32, z: f32) -> Vector3f {
        Vector3f {
            x: x,
            y: y,
            z: z,
        }
    }

    fn add_components(&mut self, x: f32, y: f32, z: f32) -> &mut Vector3f {
        unimplemented!()
    }

    fn add_components_into(&self, x: f32, y: f32, z: f32, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn cross(&mut self, v: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn cross_into(&self, v: &Vector3f, dest: &mut Vector3f) {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use super::super::Vector;
    use super::super::Vector3;
    use super::Vector3f;

    use std;

    #[test]
    fn test_new() {
        let a = Vector3f::new(1f32, 2f32, 3f32);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);
        assert_eq!(a.z, 3f32);
    }

    #[test]
    fn test_add() {
        let mut a = Vector3f::new(1f32, 2f32, 3f32);
        let b = Vector3f::new(1f32, 2f32, 3f32);

        a.add(&b);

        assert_eq!(a.x, 2f32);
        assert_eq!(a.y, 4f32);
        assert_eq!(a.z, 6f32);
    }

    #[test]
    fn test_add_into() {
        let a = Vector3f::new(1f32, 2f32, 3f32);
        let b = Vector3f::new(1f32, 2f32, 3f32);
        let mut c = Vector3f::new(0f32, 0f32, 0f32);

        a.add_into(&b, &mut c);

        assert_eq!(c.x, 2f32);
        assert_eq!(c.y, 4f32);
        assert_eq!(c.z, 6f32);
    }

    #[test]
    fn test_distance() {
        let a = Vector3f::new(1f32, 2f32, 3f32);
        let b = Vector3f::new(-1f32, 2f32, 3f32);

        let target_distance = 2f32;
        let distance = a.distance(&b);

        assert_eq!(target_distance, distance);
    }

    #[test]
    fn test_distance_squared() {
        let a = Vector3f::new(1f32, 2f32, 3f32);
        let b = Vector3f::new(-1f32, 2f32, 3f32);

        let target_distance_sq = 4f32; // target distance is 2
        let distance_sq = a.distance_squared(&b);

        assert_eq!(target_distance_sq, distance_sq);
    }

    #[test]
    fn test_dot() {
        let a = Vector3f::new(1f32, 2f32, 3f32);
        let b = Vector3f::new(1f32, 2f32, 3f32);

        let target_dot = 14f32;
        let dot = a.dot(&b);

        assert_eq!(target_dot, dot);
    }
}
<commit_msg>add length and length_squared impls<commit_after>use super::Vector;
use super::Vector3;

pub struct Vector3f {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

impl Vector<f32> for Vector3f {
    fn add(&mut self, v: &Vector3f) -> &mut Vector3f {
        self.x += v.x;
        self.y += v.y;
        self.z += v.z;
        self
    }

    fn add_into(&self, v: &Vector3f, dest: &mut Vector3f) {
        dest.x = self.x + v.x;
        dest.y = self.y + v.y;
        dest.z = self.z + v.z;
    }

    fn angle(&self, v: &Vector3f) -> f32 {
        unimplemented!()
    }

    fn angle_cos(&self, v: &Vector3f) -> f32 {
        unimplemented!()
    }

    fn distance(&self, v: &Vector3f) -> f32 {
        self.distance_squared(v).sqrt()
    }

    fn distance_squared(&self, v: &Vector3f) -> f32 {
        let dx = self.x - v.x;
        let dy = self.y - v.y;
        let dz = self.z - v.z;
        (dx * dx) + (dy * dy) + (dz * dz)
    }

    fn dot(&self, v: &Vector3f) -> f32 {
        (self.x * v.x) + (self.y * v.y) + (self.z * v.z)
    }

    fn fma_scalar(&mut self, a: f32, b: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn fma_scalar_into(&self, a: f32, b: &Vector3f, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn fma_vector(&mut self, a: &Vector3f, b: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn fma_vector_into(&self, a: &Vector3f, b: &Vector3f, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn length(&self) -> f32 {
        self.length_squared().sqrt()
    }

    fn length_squared(&self) -> f32 {
        (self.x * self.x) + (self.y * self.y) + (self.z * self.z)
    }

    fn lerp(&mut self, other: &Vector3f, t: f32) -> &mut Vector3f {
        unimplemented!()
    }

    fn lerp_into(&self, other: &Vector3f, t: f32, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn mul_scalar(&mut self, s: f32) -> &mut Vector3f {
        unimplemented!()
    }

    fn mul_scalar_into(&self, s: f32, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn mul_vector(&mut self, v: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn mul_vector_into(&self, v: &Vector3f, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn negate(&mut self) -> &mut Vector3f {
        unimplemented!()
    }

    fn negate_into(&self, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn normalize(&mut self) -> &mut Vector3f {
        unimplemented!()
    }

    fn normalize_into(&self, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn set(&mut self, v: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn sub(&mut self, v: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn sub_into(&self, v: &Vector3f, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn zero(&mut self) -> &mut Vector3f {
        unimplemented!()
    }
}

impl Vector3<f32> for Vector3f {
    fn new(x: f32, y: f32, z: f32) -> Vector3f {
        Vector3f {
            x: x,
            y: y,
            z: z,
        }
    }

    fn add_components(&mut self, x: f32, y: f32, z: f32) -> &mut Vector3f {
        unimplemented!()
    }

    fn add_components_into(&self, x: f32, y: f32, z: f32, dest: &mut Vector3f) {
        unimplemented!()
    }

    fn cross(&mut self, v: &Vector3f) -> &mut Vector3f {
        unimplemented!()
    }

    fn cross_into(&self, v: &Vector3f, dest: &mut Vector3f) {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use super::super::Vector;
    use super::super::Vector3;
    use super::Vector3f;

    use std;

    #[test]
    fn test_new() {
        let a = Vector3f::new(1f32, 2f32, 3f32);

        assert_eq!(a.x, 1f32);
        assert_eq!(a.y, 2f32);
        assert_eq!(a.z, 3f32);
    }

    #[test]
    fn test_add() {
        let mut a = Vector3f::new(1f32, 2f32, 3f32);
        let b = Vector3f::new(1f32, 2f32, 3f32);

        a.add(&b);

        assert_eq!(a.x, 2f32);
        assert_eq!(a.y, 4f32);
        assert_eq!(a.z, 6f32);
    }

    #[test]
    fn test_add_into() {
        let a = Vector3f::new(1f32, 2f32, 3f32);
        let b = Vector3f::new(1f32, 2f32, 3f32);
        let mut c = Vector3f::new(0f32, 0f32, 0f32);

        a.add_into(&b, &mut c);

        assert_eq!(c.x, 2f32);
        assert_eq!(c.y, 4f32);
        assert_eq!(c.z, 6f32);
    }

    #[test]
    fn test_distance() {
        let a = Vector3f::new(1f32, 2f32, 3f32);
        let b = Vector3f::new(-1f32, 2f32, 3f32);

        let target_distance = 2f32;
        let distance = a.distance(&b);

        assert_eq!(target_distance, distance);
    }

    #[test]
    fn test_distance_squared() {
        let a = Vector3f::new(1f32, 2f32, 3f32);
        let b = Vector3f::new(-1f32, 2f32, 3f32);

        let target_distance_sq = 4f32; // target distance is 2
        let distance_sq = a.distance_squared(&b);

        assert_eq!(target_distance_sq, distance_sq);
    }

    #[test]
    fn test_dot() {
        let a = Vector3f::new(1f32, 2f32, 3f32);
        let b = Vector3f::new(1f32, 2f32, 3f32);

        let target_dot = 14f32;
        let dot = a.dot(&b);

        assert_eq!(target_dot, dot);
    }

    #[test]
    fn test_length() {
        let a = Vector3f::new(1f32, 2f32, 2f32);

        let target_length = 3f32;
        let length = a.length();

        assert_eq!(target_length, length);
    }

    #[test]
    fn test_length_squared() {
        let a = Vector3f::new(1f32, 2f32, 3f32);

        let target_length_sq = 14f32;
        let length_sq = a.length_squared();

        assert_eq!(target_length_sq, length_sq);
    }
}
<|endoftext|>


<commit_before>
use std::fmt::{Display, Formatter, Error};

pub use self::Block::*;

macro_rules! consume_token { ($i:tt) => (0) }

macro_rules! offsets {
    ($first:ident, $($other:ident),*) => (
        #[allow(non_upper_case_globals)]
        pub const $first: usize = 0;
        offsets!(prev($first), $($other),*);
    );
    (prev($prev:ident), $first:ident, $($other:ident),*) => (
        #[allow(non_upper_case_globals)]
        pub const $first: usize = $prev + internal_sizes::$prev;
        offsets!(prev($first), $($other),*);
    );
    (prev($prev:ident), $first:ident) => (
        #[allow(non_upper_case_globals)]
        pub const $first: usize = $prev + internal_sizes::$prev;
    )
}

macro_rules! define_blocks {
    (
        $(
            $name:ident {
                props {
                    $(
                        $fname:ident : $ftype:ty = [$($val:expr),+],
                    )*
                },
                data $datafunc:expr,
                material $mat:expr,
                model $model:expr,
                variant $variant:expr,
            }
        )+
    ) => (
        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
        pub enum Block {
            $(
                $name {
                    $(
                        $fname : $ftype,
                    )*
                },
            )+
        }
        mod internal_ids {
            create_ids!(usize, $($name),+);
        }
        mod internal_sizes {
            $(
                #[allow(non_upper_case_globals)]
                pub const $name : usize = $(($(1 + consume_token!($val) + )+ 0) *  )* 1;
            )+
        }
        mod internal_offsets {
            use super::internal_sizes;
            offsets!($($name),+);
        }
        mod internal_offset_max {
            use super::internal_sizes;
            use super::internal_offsets;
            $(
                #[allow(non_upper_case_globals)]
                pub const $name: usize = internal_offsets::$name + internal_sizes::$name - 1;
            )+
        }

        impl Block {
            #[allow(unused_variables, unused_mut, unused_assignments)]
            pub fn get_steven_id(&self) -> usize {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            let mut offset = internal_offsets::$name;
                            let mut mul = 1;
                            $(
                                offset += [$($val),+].into_iter().position(|v| *v == $fname).unwrap() * mul;
                                mul *= $(1 + consume_token!($val) + )+ 0;
                            )*
                            offset
                        },
                    )+
                }
            }

            #[allow(unused_variables, unused_assignments)]
            pub fn by_steven_id(id: usize) -> Block {
                match id {
                    $(
                        mut data @ internal_offsets::$name ... internal_offset_max::$name=> {
                            data -= internal_offsets::$name;
                            $(
                                let vals = [$($val),+];
                                let $fname = vals[data % vals.len()];
                                data /= vals.len();
                            )*
                            Block::$name {
                                $(
                                    $fname: $fname,
                                )*
                            }
                        },
                    )*
                    _ => Block::Missing {}
                }
            }

            #[allow(unused_variables)]
            pub fn get_vanilla_id(&self) -> Option<usize> {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            ($datafunc).map(|v| v + (internal_ids::$name << 4))
                        }
                    )+
                }
            }

            pub fn by_vanilla_id(id: usize) -> Block {
                VANILLA_ID_MAP.get(id).and_then(|v| *v).unwrap_or(Block::Missing{})
            }

            #[allow(unused_variables)]
            pub fn get_material(&self) -> Material {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            $mat
                        }
                    )+
                }
            }

            #[allow(unused_variables)]
            pub fn get_model(&self) -> (String, String) {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            let parts = $model;
                            (String::from(parts.0), String::from(parts.1))
                        }
                    )+
                }
            }

            #[allow(unused_variables)]
            pub fn get_model_variant(&self) -> String {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            String::from($variant)
                        }
                    )+
                }
            }
        }

        lazy_static! {
            static ref VANILLA_ID_MAP: Vec<Option<Block>> = {
                let mut blocks = vec![];
                for i in 0 .. internal_offsets::Missing {
                    let block = Block::by_steven_id(i);
                    if let Some(id) = block.get_vanilla_id() {
                        if blocks.len() <= id {
                            blocks.resize(id + 1, None);
                        }
                        blocks[id] = Some(block);
                    }
                }
                blocks
            };
        }
    );
}

pub struct Material {
    pub renderable: bool,
    pub should_cull_against: bool,
    pub force_shade: bool,
}

define_blocks! {
    Air {
        props {},
        data { Some(0) },
        material Material {
            renderable: false,
            should_cull_against: false,
            force_shade: false,
        },
        model { ("minecraft", "air" ) },
        variant "normal",
    }
    Stone {
        props {
            variant: StoneVariant = [
                StoneVariant::Normal,
                StoneVariant::Granite, StoneVariant::SmoothGranite,
                StoneVariant::Diorite, StoneVariant::SmoothDiorite,
                StoneVariant::Andesite, StoneVariant::SmoothAndesite
            ],
        },
        data { Some(variant.data()) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", variant.as_string() ) },
        variant "normal",
    }
    Grass {
        props {
            snowy: bool = [false, true],
        },
        data { if snowy { None } else { Some(0) } },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "grass" ) },
        variant format!("snowy={}", snowy),
    }
    Dirt {
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "dirt" ) },
        variant "normal",
    }
    Cobblestone {
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "cobblestone" ) },
        variant "normal",
    }
    Planks { // TODO
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "planks" ) },
        variant "normal",
    }
    Sapling { // TODO
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: false,
            force_shade: false,
        },
        model { ("minecraft", "sapling" ) },
        variant "normal",
    }
    Bedrock {
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "bedrock" ) },
        variant "normal",
    }
    FlowingWater { // TODO
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "water" ) },
        variant "normal",
    }
    Water { // TODO
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "water" ) },
        variant "normal",
    }
    FlowingLava { // TODO
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "lava" ) },
        variant "normal",
    }
    Lava {
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "lava" ) },
        variant "normal",
    }
    Sand { // TODO
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "sand" ) },
        variant "normal",
    }
    Gravel {
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "gravel" ) },
        variant "normal",
    }
    GoldOre {
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "gold_ore" ) },
        variant "normal",
    }
    IronOre {
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "iron_ore" ) },
        variant "normal",
    }
    CoalOre {
        props {
        },
        data { Some(0) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "coal_ore" ) },
        variant "normal",
    }
    Log {
        props {
            variant: TreeVariant = [
                TreeVariant::Oak, TreeVariant::Spruce,
                TreeVariant::Birch, TreeVariant::Jungle
            ],
            axis: Axis = [Axis::Y, Axis::Z, Axis::X, Axis::None],
        },
        data { Some(variant.data() | (axis.data() << 2)) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", format!("{}_log", variant.as_string()) ) },
        variant format!("axis={}", axis.as_string()),
    }
    Leaves {
        props {
            variant: TreeVariant = [
                TreeVariant::Oak, TreeVariant::Spruce,
                TreeVariant::Birch, TreeVariant::Jungle
            ],
            decayable: bool = [false, true],
            check_decay: bool = [false, true],
        },
        data { Some(variant.data()
                    | (if decayable { 0x4 } else { 0x0 })
                    | (if check_decay { 0x8 } else { 0x0 })
        ) },
        material Material {
            renderable: true,
            should_cull_against: false,
            force_shade: true,
        },
        model { ("minecraft", format!("{}_leaves", variant.as_string()) ) },
        variant "normal",
    }
    Missing {
        props {},
        data { None::<usize> },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("steven", "missing_block" ) },
        variant "normal",
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Axis {
    Y,
    Z,
    X,
    None
}

impl Axis {
    pub fn as_string(&self) -> &'static str {
        match *self {
            Axis::X => "x",
            Axis::Y => "y",
            Axis::Z => "z",
            Axis::None => "none",
        }
    }
    fn data(&self) -> usize {
        match *self {
            Axis::Y => 0,
            Axis::Z => 1,
            Axis::X => 2,
            Axis::None => 3,
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum TreeVariant {
    Oak,
    Spruce,
    Birch,
    Jungle,
    Acacia,
    DarkOak
}

impl TreeVariant {
    pub fn as_string(&self) -> &'static str {
        match *self {
            TreeVariant::Oak => "oak",
            TreeVariant::Spruce => "spruce",
            TreeVariant::Birch => "birch",
            TreeVariant::Jungle => "jungle",
            TreeVariant::Acacia => "acacia",
            TreeVariant::DarkOak => "dark_oak",
        }
    }
    pub fn data(&self) -> usize {
        match *self {
            TreeVariant::Oak => 0,
            TreeVariant::Spruce => 1,
            TreeVariant::Birch => 2,
            TreeVariant::Jungle => 3,
            TreeVariant::Acacia => 0,
            TreeVariant::DarkOak => 1,
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum StoneVariant {
    Normal,
    Granite,
    SmoothGranite,
    Diorite,
    SmoothDiorite,
    Andesite,
    SmoothAndesite,
}

impl Display for StoneVariant {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "{}", self.as_string())
    }
}

impl StoneVariant {
    fn as_string(&self) -> &'static str {
        match *self {
            StoneVariant::Normal => "stone",
            StoneVariant::Granite => "granite",
            StoneVariant::SmoothGranite => "smooth_granite",
            StoneVariant::Diorite => "diorite",
            StoneVariant::SmoothDiorite => "smooth_diorite",
            StoneVariant::Andesite => "andesite",
            StoneVariant::SmoothAndesite => "smooth_andesite",
        }
    }
    fn data(&self) -> usize {
        match *self {
            StoneVariant::Normal => 0,
            StoneVariant::Granite => 1,
            StoneVariant::SmoothGranite => 2,
            StoneVariant::Diorite => 3,
            StoneVariant::SmoothDiorite => 4,
            StoneVariant::Andesite => 5,
            StoneVariant::SmoothAndesite => 6,
        }
    }
}
<commit_msg>Tidy up block defining<commit_after>
use std::fmt::{Display, Formatter, Error};

pub use self::Block::*;

macro_rules! consume_token { ($i:tt) => (0) }

macro_rules! offsets {
    ($first:ident, $($other:ident),*) => (
        #[allow(non_upper_case_globals)]
        pub const $first: usize = 0;
        offsets!(prev($first), $($other),*);
    );
    (prev($prev:ident), $first:ident, $($other:ident),*) => (
        #[allow(non_upper_case_globals)]
        pub const $first: usize = $prev + internal_sizes::$prev;
        offsets!(prev($first), $($other),*);
    );
    (prev($prev:ident), $first:ident) => (
        #[allow(non_upper_case_globals)]
        pub const $first: usize = $prev + internal_sizes::$prev;
    )
}

macro_rules! define_blocks {
    (
        $(
            $name:ident {
                props {
                    $(
                        $fname:ident : $ftype:ty = [$($val:expr),+],
                    )*
                },
                $(data $datafunc:expr,)*
                material $mat:expr,
                model $model:expr,
                $(variant $variant:expr,)*
                $(tint $tint:expr,)*
            }
        )+
    ) => (
        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
        pub enum Block {
            $(
                $name {
                    $(
                        $fname : $ftype,
                    )*
                },
            )+
        }
        mod internal_ids {
            create_ids!(usize, $($name),+);
        }
        mod internal_sizes {
            $(
                #[allow(non_upper_case_globals)]
                pub const $name : usize = $(($(1 + consume_token!($val) + )+ 0) *  )* 1;
            )+
        }
        mod internal_offsets {
            use super::internal_sizes;
            offsets!($($name),+);
        }
        mod internal_offset_max {
            use super::internal_sizes;
            use super::internal_offsets;
            $(
                #[allow(non_upper_case_globals)]
                pub const $name: usize = internal_offsets::$name + internal_sizes::$name - 1;
            )+
        }

        impl Block {
            #[allow(unused_variables, unused_mut, unused_assignments)]
            pub fn get_steven_id(&self) -> usize {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            let mut offset = internal_offsets::$name;
                            let mut mul = 1;
                            $(
                                offset += [$($val),+].into_iter().position(|v| *v == $fname).unwrap() * mul;
                                mul *= $(1 + consume_token!($val) + )+ 0;
                            )*
                            offset
                        },
                    )+
                }
            }

            #[allow(unused_variables, unused_assignments)]
            pub fn by_steven_id(id: usize) -> Block {
                match id {
                    $(
                        mut data @ internal_offsets::$name ... internal_offset_max::$name=> {
                            data -= internal_offsets::$name;
                            $(
                                let vals = [$($val),+];
                                let $fname = vals[data % vals.len()];
                                data /= vals.len();
                            )*
                            Block::$name {
                                $(
                                    $fname: $fname,
                                )*
                            }
                        },
                    )*
                    _ => Block::Missing {}
                }
            }

            #[allow(unused_variables, unreachable_code)]
            pub fn get_vanilla_id(&self) -> Option<usize> {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            $(
                                let data: Option<usize> = ($datafunc).map(|v| v + (internal_ids::$name << 4));
                                return data;
                            )*
                            return Some(0);
                        }
                    )+
                }
            }

            pub fn by_vanilla_id(id: usize) -> Block {
                VANILLA_ID_MAP.get(id).and_then(|v| *v).unwrap_or(Block::Missing{})
            }

            #[allow(unused_variables)]
            pub fn get_material(&self) -> Material {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            $mat
                        }
                    )+
                }
            }

            #[allow(unused_variables)]
            pub fn get_model(&self) -> (String, String) {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            let parts = $model;
                            (String::from(parts.0), String::from(parts.1))
                        }
                    )+
                }
            }

            #[allow(unused_variables, unreachable_code)]
            pub fn get_model_variant(&self) -> String {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            $(return String::from($variant);)*
                            return "normal";
                        }
                    )+
                }
            }

            #[allow(unused_variables, unreachable_code)]
            pub fn get_tint(&self) -> TintType {
                match *self {
                    $(
                        Block::$name {
                            $($fname,)*
                        } => {
                            $(return $tint;)*
                            return TintType::Default;
                        }
                    )+
                }
            }
        }

        lazy_static! {
            static ref VANILLA_ID_MAP: Vec<Option<Block>> = {
                let mut blocks = vec![];
                for i in 0 .. internal_offsets::Missing {
                    let block = Block::by_steven_id(i);
                    if let Some(id) = block.get_vanilla_id() {
                        if blocks.len() <= id {
                            blocks.resize(id + 1, None);
                        }
                        blocks[id] = Some(block);
                    }
                }
                blocks
            };
        }
    );
}

pub struct Material {
    pub renderable: bool,
    pub should_cull_against: bool,
    pub force_shade: bool,
}

pub enum TintType {
    Default,
    Color{r: u8, g: u8, b: u8},
    Grass,
    Foliage,
}

define_blocks! {
    Air {
        props {},
        material Material {
            renderable: false,
            should_cull_against: false,
            force_shade: false,
        },
        model { ("minecraft", "air" ) },
    }
    Stone {
        props {
            variant: StoneVariant = [
                StoneVariant::Normal,
                StoneVariant::Granite, StoneVariant::SmoothGranite,
                StoneVariant::Diorite, StoneVariant::SmoothDiorite,
                StoneVariant::Andesite, StoneVariant::SmoothAndesite
            ],
        },
        data { Some(variant.data()) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", variant.as_string() ) },
    }
    Grass {
        props {
            snowy: bool = [false, true],
        },
        data { if snowy { None } else { Some(0) } },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "grass" ) },
        variant format!("snowy={}", snowy),
    }
    Dirt {
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "dirt" ) },
    }
    Cobblestone {
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "cobblestone" ) },
    }
    Planks { // TODO
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "planks" ) },
    }
    Sapling { // TODO
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: false,
            force_shade: false,
        },
        model { ("minecraft", "sapling" ) },
    }
    Bedrock {
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "bedrock" ) },
    }
    FlowingWater { // TODO
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "water" ) },
    }
    Water { // TODO
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "water" ) },
    }
    FlowingLava { // TODO
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "lava" ) },
    }
    Lava {
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "lava" ) },
    }
    Sand { // TODO
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "sand" ) },
    }
    Gravel {
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "gravel" ) },
    }
    GoldOre {
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "gold_ore" ) },
    }
    IronOre {
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "iron_ore" ) },
    }
    CoalOre {
        props {
        },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", "coal_ore" ) },
    }
    Log {
        props {
            variant: TreeVariant = [
                TreeVariant::Oak, TreeVariant::Spruce,
                TreeVariant::Birch, TreeVariant::Jungle
            ],
            axis: Axis = [Axis::Y, Axis::Z, Axis::X, Axis::None],
        },
        data { Some(variant.data() | (axis.data() << 2)) },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("minecraft", format!("{}_log", variant.as_string()) ) },
        variant format!("axis={}", axis.as_string()),
    }
    Leaves {
        props {
            variant: TreeVariant = [
                TreeVariant::Oak, TreeVariant::Spruce,
                TreeVariant::Birch, TreeVariant::Jungle
            ],
            decayable: bool = [false, true],
            check_decay: bool = [false, true],
        },
        data { Some(variant.data()
                    | (if decayable { 0x4 } else { 0x0 })
                    | (if check_decay { 0x8 } else { 0x0 })
        ) },
        material Material {
            renderable: true,
            should_cull_against: false,
            force_shade: true,
        },
        model { ("minecraft", format!("{}_leaves", variant.as_string()) ) },
    }
    Missing {
        props {},
        data { None::<usize> },
        material Material {
            renderable: true,
            should_cull_against: true,
            force_shade: false,
        },
        model { ("steven", "missing_block" ) },
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Axis {
    Y,
    Z,
    X,
    None
}

impl Axis {
    pub fn as_string(&self) -> &'static str {
        match *self {
            Axis::X => "x",
            Axis::Y => "y",
            Axis::Z => "z",
            Axis::None => "none",
        }
    }
    fn data(&self) -> usize {
        match *self {
            Axis::Y => 0,
            Axis::Z => 1,
            Axis::X => 2,
            Axis::None => 3,
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum TreeVariant {
    Oak,
    Spruce,
    Birch,
    Jungle,
    Acacia,
    DarkOak
}

impl TreeVariant {
    pub fn as_string(&self) -> &'static str {
        match *self {
            TreeVariant::Oak => "oak",
            TreeVariant::Spruce => "spruce",
            TreeVariant::Birch => "birch",
            TreeVariant::Jungle => "jungle",
            TreeVariant::Acacia => "acacia",
            TreeVariant::DarkOak => "dark_oak",
        }
    }
    pub fn data(&self) -> usize {
        match *self {
            TreeVariant::Oak => 0,
            TreeVariant::Spruce => 1,
            TreeVariant::Birch => 2,
            TreeVariant::Jungle => 3,
            TreeVariant::Acacia => 0,
            TreeVariant::DarkOak => 1,
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum StoneVariant {
    Normal,
    Granite,
    SmoothGranite,
    Diorite,
    SmoothDiorite,
    Andesite,
    SmoothAndesite,
}

impl Display for StoneVariant {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "{}", self.as_string())
    }
}

impl StoneVariant {
    fn as_string(&self) -> &'static str {
        match *self {
            StoneVariant::Normal => "stone",
            StoneVariant::Granite => "granite",
            StoneVariant::SmoothGranite => "smooth_granite",
            StoneVariant::Diorite => "diorite",
            StoneVariant::SmoothDiorite => "smooth_diorite",
            StoneVariant::Andesite => "andesite",
            StoneVariant::SmoothAndesite => "smooth_andesite",
        }
    }
    fn data(&self) -> usize {
        match *self {
            StoneVariant::Normal => 0,
            StoneVariant::Granite => 1,
            StoneVariant::SmoothGranite => 2,
            StoneVariant::Diorite => 3,
            StoneVariant::SmoothDiorite => 4,
            StoneVariant::Andesite => 5,
            StoneVariant::SmoothAndesite => 6,
        }
    }
}
<|endoftext|>