<commit_before>//! Test command for testing the binary machine code emission.
//!
//! The `binemit` test command generates binary machine code for every instruction in the input
//! functions and compares the results to the expected output.

use crate::match_directive::match_directive;
use crate::subtest::{Context, SubTest, SubtestResult};
use cranelift_codegen::binemit::{self, CodeInfo, CodeSink, RegDiversions};
use cranelift_codegen::dbg::DisplayList;
use cranelift_codegen::dominator_tree::DominatorTree;
use cranelift_codegen::flowgraph::ControlFlowGraph;
use cranelift_codegen::ir;
use cranelift_codegen::ir::entities::AnyEntity;
use cranelift_codegen::isa;
use cranelift_codegen::print_errors::pretty_error;
use cranelift_codegen::settings::OptLevel;
use cranelift_reader::TestCommand;
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt::Write;

struct TestBinEmit;

pub fn subtest(parsed: &TestCommand) -> SubtestResult<Box<dyn SubTest>> {
    assert_eq!(parsed.command, "binemit");
    if !parsed.options.is_empty() {
        Err(format!("No options allowed on {}", parsed))
    } else {
        Ok(Box::new(TestBinEmit))
    }
}

/// Code sink that generates text.
struct TextSink {
    code_size: binemit::CodeOffset,
    offset: binemit::CodeOffset,
    text: String,
}

impl TextSink {
    /// Create a new empty TextSink.
    pub fn new() -> Self {
        Self {
            code_size: 0,
            offset: 0,
            text: String::new(),
        }
    }
}

impl binemit::CodeSink for TextSink {
    fn offset(&self) -> binemit::CodeOffset {
        self.offset
    }

    fn put1(&mut self, x: u8) {
        write!(self.text, "{:02x} ", x).unwrap();
        self.offset += 1;
    }

    fn put2(&mut self, x: u16) {
        write!(self.text, "{:04x} ", x).unwrap();
        self.offset += 2;
    }

    fn put4(&mut self, x: u32) {
        write!(self.text, "{:08x} ", x).unwrap();
        self.offset += 4;
    }

    fn put8(&mut self, x: u64) {
        write!(self.text, "{:016x} ", x).unwrap();
        self.offset += 8;
    }

    fn reloc_ebb(&mut self, reloc: binemit::Reloc, ebb_offset: binemit::CodeOffset) {
        write!(self.text, "{}({}) ", reloc, ebb_offset).unwrap();
    }

    fn reloc_external(
        &mut self,
        reloc: binemit::Reloc,
        name: &ir::ExternalName,
        addend: binemit::Addend,
    ) {
        write!(self.text, "{}({}", reloc, name).unwrap();
        if addend != 0 {
            write!(self.text, "{:+}", addend).unwrap();
        }
        write!(self.text, ") ").unwrap();
    }

    fn reloc_constant(&mut self, reloc: binemit::Reloc, constant: ir::ConstantOffset) {
        write!(self.text, "{}({}) ", reloc, constant).unwrap();
    }

    fn reloc_jt(&mut self, reloc: binemit::Reloc, jt: ir::JumpTable) {
        write!(self.text, "{}({}) ", reloc, jt).unwrap();
    }

    fn trap(&mut self, code: ir::TrapCode, _srcloc: ir::SourceLoc) {
        write!(self.text, "{} ", code).unwrap();
    }

    fn begin_jumptables(&mut self) {
        self.code_size = self.offset
    }
    fn begin_rodata(&mut self) {}
    fn end_codegen(&mut self) {}
    fn add_stackmap(
        &mut self,
        _: &[ir::entities::Value],
        _: &ir::Function,
        _: &dyn isa::TargetIsa,
    ) {
    }
}

impl SubTest for TestBinEmit {
    fn name(&self) -> &'static str {
        "binemit"
    }

    fn is_mutating(&self) -> bool {
        true
    }

    fn needs_isa(&self) -> bool {
        true
    }

    fn run(&self, func: Cow<ir::Function>, context: &Context) -> SubtestResult<()> {
        let isa = context.isa.expect("binemit needs an ISA");
        let encinfo = isa.encoding_info();
        // TODO: Run a verifier pass over the code first to detect any bad encodings or missing/bad
        // value locations. The current error reporting is just crashing...
        let mut func = func.into_owned();

        // Fix the stack frame layout so we can test spill/fill encodings.
        let min_offset = func
            .stack_slots
            .values()
            .map(|slot| slot.offset.unwrap())
            .min();
        func.stack_slots.frame_size = min_offset.map(|off| (-off) as u32);

        let opt_level = isa.flags().opt_level();

        // Give an encoding to any instruction that doesn't already have one.
        let mut divert = RegDiversions::new();
        for ebb in func.layout.ebbs() {
            divert.clear();
            for inst in func.layout.ebb_insts(ebb) {
                if !func.encodings[inst].is_legal() {
                    // Find an encoding that satisfies both immediate field and register
                    // constraints.
                    if let Some(enc) = {
                        let mut legal_encodings = isa
                            .legal_encodings(&func, &func.dfg[inst], func.dfg.ctrl_typevar(inst))
                            .filter(|e| {
                                let recipe_constraints = &encinfo.constraints[e.recipe()];
                                recipe_constraints.satisfied(inst, &divert, &func)
                            });

                        if opt_level == OptLevel::SpeedAndSize {
                            // Get the smallest legal encoding
                            legal_encodings
                                .min_by_key(|&e| encinfo.byte_size(e, inst, &divert, &func))
                        } else {
                            // If not optimizing, just use the first encoding.
                            legal_encodings.next()
                        }
                    } {
                        func.encodings[inst] = enc;
                    }
                }
                divert.apply(&func.dfg[inst]);
            }
        }

        // Relax branches and compute EBB offsets based on the encodings.
        let mut cfg = ControlFlowGraph::with_function(&func);
        let mut domtree = DominatorTree::with_function(&func, &cfg);
        let CodeInfo { total_size, .. } =
            binemit::relax_branches(&mut func, &mut cfg, &mut domtree, isa)
                .map_err(|e| pretty_error(&func, context.isa, e))?;

        // Collect all of the 'bin:' directives on instructions.
        let mut bins = HashMap::new();
        for comment in &context.details.comments {
            if let Some(want) = match_directive(comment.text, "bin:") {
                match comment.entity {
                    AnyEntity::Inst(inst) => {
                        if let Some(prev) = bins.insert(inst, want) {
                            return Err(format!(
                                "multiple 'bin:' directives on {}: '{}' and '{}'",
                                func.dfg.display_inst(inst, isa),
                                prev,
                                want
                            ));
                        }
                    }
                    _ => {
                        return Err(format!(
                            "'bin:' directive on non-inst {}: {}",
                            comment.entity, comment.text
                        ));
                    }
                }
            }
        }
        if bins.is_empty() {
            return Err("No 'bin:' directives found".to_string());
        }

        // Now emit all instructions.
        let mut sink = TextSink::new();
        for ebb in func.layout.ebbs() {
            divert.clear();
            // Correct header offsets should have been computed by `relax_branches()`.
            assert_eq!(
                sink.offset, func.offsets[ebb],
                "Inconsistent {} header offset",
                ebb
            );
            for (offset, inst, enc_bytes) in func.inst_offsets(ebb, &encinfo) {
                assert_eq!(sink.offset, offset);
                sink.text.clear();
                let enc = func.encodings[inst];

                // Send legal encodings into the emitter.
                if enc.is_legal() {
                    // Generate a better error message if output locations are not specified.
                    if let Some(&v) = func
                        .dfg
                        .inst_results(inst)
                        .iter()
                        .find(|&&v| !func.locations[v].is_assigned())
                    {
                        return Err(format!(
                            "Missing register/stack slot for {} in {}",
                            v,
                            func.dfg.display_inst(inst, isa)
                        ));
                    }
                    let before = sink.offset;
                    isa.emit_inst(&func, inst, &mut divert, &mut sink);
                    let emitted = sink.offset - before;
                    // Verify the encoding recipe sizes against the ISAs emit_inst implementation.
                    assert_eq!(
                        emitted,
                        enc_bytes,
                        "Inconsistent size for [{}] {}",
                        encinfo.display(enc),
                        func.dfg.display_inst(inst, isa)
                    );
                }

                // Check against bin: directives.
                if let Some(want) = bins.remove(&inst) {
                    if !enc.is_legal() {
                        // A possible cause of an unencoded instruction is a missing location for
                        // one of the input operands.
                        if let Some(&v) = func
                            .dfg
                            .inst_args(inst)
                            .iter()
                            .find(|&&v| !func.locations[v].is_assigned())
                        {
                            return Err(format!(
                                "Missing register/stack slot for {} in {}",
                                v,
                                func.dfg.display_inst(inst, isa)
                            ));
                        }

                        // Do any encodings exist?
                        let encodings = isa
                            .legal_encodings(&func, &func.dfg[inst], func.dfg.ctrl_typevar(inst))
                            .map(|e| encinfo.display(e))
                            .collect::<Vec<_>>();

                        if encodings.is_empty() {
                            return Err(format!(
                                "No encodings found for: {}",
                                func.dfg.display_inst(inst, isa)
                            ));
                        }
                        return Err(format!(
                            "No matching encodings for {} in {}",
                            func.dfg.display_inst(inst, isa),
                            DisplayList(&encodings),
                        ));
                    }
                    let have = sink.text.trim();
                    if have != want {
                        return Err(format!(
                            "Bad machine code for {}: {}\nWant: {}\nGot:  {}",
                            inst,
                            func.dfg.display_inst(inst, isa),
                            want,
                            have
                        ));
                    }
                }
            }
        }

        sink.begin_jumptables();

        for (jt, jt_data) in func.jump_tables.iter() {
            let jt_offset = func.jt_offsets[jt];
            for ebb in jt_data.iter() {
                let rel_offset: i32 = func.offsets[*ebb] as i32 - jt_offset as i32;
                sink.put4(rel_offset as u32)
            }
        }

        sink.begin_rodata();

        // output constants
        for (_, constant_data) in func.dfg.constants.iter() {
            for byte in constant_data.iter() {
                sink.put1(*byte)
            }
        }

        sink.end_codegen();

        if sink.offset != total_size {
            return Err(format!(
                "Expected code size {}, got {}",
                total_size, sink.offset
            ));
        }

        Ok(())
    }
}
<commit_msg>Report when output register annotation is missing (#1289)<commit_after>//! Test command for testing the binary machine code emission.
//!
//! The `binemit` test command generates binary machine code for every instruction in the input
//! functions and compares the results to the expected output.

use crate::match_directive::match_directive;
use crate::subtest::{Context, SubTest, SubtestResult};
use cranelift_codegen::binemit::{self, CodeInfo, CodeSink, RegDiversions};
use cranelift_codegen::dbg::DisplayList;
use cranelift_codegen::dominator_tree::DominatorTree;
use cranelift_codegen::flowgraph::ControlFlowGraph;
use cranelift_codegen::ir;
use cranelift_codegen::ir::entities::AnyEntity;
use cranelift_codegen::isa;
use cranelift_codegen::print_errors::pretty_error;
use cranelift_codegen::settings::OptLevel;
use cranelift_reader::TestCommand;
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt::Write;

struct TestBinEmit;

pub fn subtest(parsed: &TestCommand) -> SubtestResult<Box<dyn SubTest>> {
    assert_eq!(parsed.command, "binemit");
    if !parsed.options.is_empty() {
        Err(format!("No options allowed on {}", parsed))
    } else {
        Ok(Box::new(TestBinEmit))
    }
}

/// Code sink that generates text.
struct TextSink {
    code_size: binemit::CodeOffset,
    offset: binemit::CodeOffset,
    text: String,
}

impl TextSink {
    /// Create a new empty TextSink.
    pub fn new() -> Self {
        Self {
            code_size: 0,
            offset: 0,
            text: String::new(),
        }
    }
}

impl binemit::CodeSink for TextSink {
    fn offset(&self) -> binemit::CodeOffset {
        self.offset
    }

    fn put1(&mut self, x: u8) {
        write!(self.text, "{:02x} ", x).unwrap();
        self.offset += 1;
    }

    fn put2(&mut self, x: u16) {
        write!(self.text, "{:04x} ", x).unwrap();
        self.offset += 2;
    }

    fn put4(&mut self, x: u32) {
        write!(self.text, "{:08x} ", x).unwrap();
        self.offset += 4;
    }

    fn put8(&mut self, x: u64) {
        write!(self.text, "{:016x} ", x).unwrap();
        self.offset += 8;
    }

    fn reloc_ebb(&mut self, reloc: binemit::Reloc, ebb_offset: binemit::CodeOffset) {
        write!(self.text, "{}({}) ", reloc, ebb_offset).unwrap();
    }

    fn reloc_external(
        &mut self,
        reloc: binemit::Reloc,
        name: &ir::ExternalName,
        addend: binemit::Addend,
    ) {
        write!(self.text, "{}({}", reloc, name).unwrap();
        if addend != 0 {
            write!(self.text, "{:+}", addend).unwrap();
        }
        write!(self.text, ") ").unwrap();
    }

    fn reloc_constant(&mut self, reloc: binemit::Reloc, constant: ir::ConstantOffset) {
        write!(self.text, "{}({}) ", reloc, constant).unwrap();
    }

    fn reloc_jt(&mut self, reloc: binemit::Reloc, jt: ir::JumpTable) {
        write!(self.text, "{}({}) ", reloc, jt).unwrap();
    }

    fn trap(&mut self, code: ir::TrapCode, _srcloc: ir::SourceLoc) {
        write!(self.text, "{} ", code).unwrap();
    }

    fn begin_jumptables(&mut self) {
        self.code_size = self.offset
    }
    fn begin_rodata(&mut self) {}
    fn end_codegen(&mut self) {}
    fn add_stackmap(
        &mut self,
        _: &[ir::entities::Value],
        _: &ir::Function,
        _: &dyn isa::TargetIsa,
    ) {
    }
}

impl SubTest for TestBinEmit {
    fn name(&self) -> &'static str {
        "binemit"
    }

    fn is_mutating(&self) -> bool {
        true
    }

    fn needs_isa(&self) -> bool {
        true
    }

    fn run(&self, func: Cow<ir::Function>, context: &Context) -> SubtestResult<()> {
        let isa = context.isa.expect("binemit needs an ISA");
        let encinfo = isa.encoding_info();
        // TODO: Run a verifier pass over the code first to detect any bad encodings or missing/bad
        // value locations. The current error reporting is just crashing...
        let mut func = func.into_owned();

        // Fix the stack frame layout so we can test spill/fill encodings.
        let min_offset = func
            .stack_slots
            .values()
            .map(|slot| slot.offset.unwrap())
            .min();
        func.stack_slots.frame_size = min_offset.map(|off| (-off) as u32);

        let opt_level = isa.flags().opt_level();

        // Give an encoding to any instruction that doesn't already have one.
        let mut divert = RegDiversions::new();
        for ebb in func.layout.ebbs() {
            divert.clear();
            for inst in func.layout.ebb_insts(ebb) {
                if !func.encodings[inst].is_legal() {
                    // Find an encoding that satisfies both immediate field and register
                    // constraints.
                    if let Some(enc) = {
                        let mut legal_encodings = isa
                            .legal_encodings(&func, &func.dfg[inst], func.dfg.ctrl_typevar(inst))
                            .filter(|e| {
                                let recipe_constraints = &encinfo.constraints[e.recipe()];
                                recipe_constraints.satisfied(inst, &divert, &func)
                            });

                        if opt_level == OptLevel::SpeedAndSize {
                            // Get the smallest legal encoding
                            legal_encodings
                                .min_by_key(|&e| encinfo.byte_size(e, inst, &divert, &func))
                        } else {
                            // If not optimizing, just use the first encoding.
                            legal_encodings.next()
                        }
                    } {
                        func.encodings[inst] = enc;
                    }
                }
                divert.apply(&func.dfg[inst]);
            }
        }

        // Relax branches and compute EBB offsets based on the encodings.
        let mut cfg = ControlFlowGraph::with_function(&func);
        let mut domtree = DominatorTree::with_function(&func, &cfg);
        let CodeInfo { total_size, .. } =
            binemit::relax_branches(&mut func, &mut cfg, &mut domtree, isa)
                .map_err(|e| pretty_error(&func, context.isa, e))?;

        // Collect all of the 'bin:' directives on instructions.
        let mut bins = HashMap::new();
        for comment in &context.details.comments {
            if let Some(want) = match_directive(comment.text, "bin:") {
                match comment.entity {
                    AnyEntity::Inst(inst) => {
                        if let Some(prev) = bins.insert(inst, want) {
                            return Err(format!(
                                "multiple 'bin:' directives on {}: '{}' and '{}'",
                                func.dfg.display_inst(inst, isa),
                                prev,
                                want
                            ));
                        }
                    }
                    _ => {
                        return Err(format!(
                            "'bin:' directive on non-inst {}: {}",
                            comment.entity, comment.text
                        ));
                    }
                }
            }
        }
        if bins.is_empty() {
            return Err("No 'bin:' directives found".to_string());
        }

        // Now emit all instructions.
        let mut sink = TextSink::new();
        for ebb in func.layout.ebbs() {
            divert.clear();
            // Correct header offsets should have been computed by `relax_branches()`.
            assert_eq!(
                sink.offset, func.offsets[ebb],
                "Inconsistent {} header offset",
                ebb
            );
            for (offset, inst, enc_bytes) in func.inst_offsets(ebb, &encinfo) {
                assert_eq!(sink.offset, offset);
                sink.text.clear();
                let enc = func.encodings[inst];

                // Send legal encodings into the emitter.
                if enc.is_legal() {
                    // Generate a better error message if output locations are not specified.
                    validate_location_annotations(&func, inst, isa, false)?;

                    let before = sink.offset;
                    isa.emit_inst(&func, inst, &mut divert, &mut sink);
                    let emitted = sink.offset - before;
                    // Verify the encoding recipe sizes against the ISAs emit_inst implementation.
                    assert_eq!(
                        emitted,
                        enc_bytes,
                        "Inconsistent size for [{}] {}",
                        encinfo.display(enc),
                        func.dfg.display_inst(inst, isa)
                    );
                }

                // Check against bin: directives.
                if let Some(want) = bins.remove(&inst) {
                    if !enc.is_legal() {
                        // A possible cause of an unencoded instruction is a missing location for
                        // one of the input/output operands.
                        validate_location_annotations(&func, inst, isa, true)?;
                        validate_location_annotations(&func, inst, isa, false)?;

                        // Do any encodings exist?
                        let encodings = isa
                            .legal_encodings(&func, &func.dfg[inst], func.dfg.ctrl_typevar(inst))
                            .map(|e| encinfo.display(e))
                            .collect::<Vec<_>>();

                        if encodings.is_empty() {
                            return Err(format!(
                                "No encodings found for: {}",
                                func.dfg.display_inst(inst, isa)
                            ));
                        }
                        return Err(format!(
                            "No matching encodings for {} in {}",
                            func.dfg.display_inst(inst, isa),
                            DisplayList(&encodings),
                        ));
                    }
                    let have = sink.text.trim();
                    if have != want {
                        return Err(format!(
                            "Bad machine code for {}: {}\nWant: {}\nGot:  {}",
                            inst,
                            func.dfg.display_inst(inst, isa),
                            want,
                            have
                        ));
                    }
                }
            }
        }

        sink.begin_jumptables();

        for (jt, jt_data) in func.jump_tables.iter() {
            let jt_offset = func.jt_offsets[jt];
            for ebb in jt_data.iter() {
                let rel_offset: i32 = func.offsets[*ebb] as i32 - jt_offset as i32;
                sink.put4(rel_offset as u32)
            }
        }

        sink.begin_rodata();

        // output constants
        for (_, constant_data) in func.dfg.constants.iter() {
            for byte in constant_data.iter() {
                sink.put1(*byte)
            }
        }

        sink.end_codegen();

        if sink.offset != total_size {
            return Err(format!(
                "Expected code size {}, got {}",
                total_size, sink.offset
            ));
        }

        Ok(())
    }
}

/// Validate registers/stack slots are correctly annotated.
fn validate_location_annotations(
    func: &ir::Function,
    inst: ir::Inst,
    isa: &dyn isa::TargetIsa,
    validate_inputs: bool,
) -> SubtestResult<()> {
    let values = if validate_inputs {
        func.dfg.inst_args(inst)
    } else {
        func.dfg.inst_results(inst)
    };

    if let Some(&v) = values.iter().find(|&&v| !func.locations[v].is_assigned()) {
        Err(format!(
            "Need register/stack slot annotation for {} in {}",
            v,
            func.dfg.display_inst(inst, isa)
        ))
    } else {
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! `mbe` (short for Macro By Example) crate contains code for handling
//! `macro_rules` macros. It uses `TokenTree` (from `tt` package) as the
//! interface, although it contains some code to bridge `SyntaxNode`s and
//! `TokenTree`s as well!

mod parser;
mod mbe_expander;
mod syntax_bridge;
mod tt_iter;
mod subtree_source;

#[cfg(test)]
mod tests;

use std::fmt;

pub use tt::{Delimiter, DelimiterKind, Punct};

use crate::{
    parser::{parse_pattern, parse_template, Op},
    tt_iter::TtIter,
};

#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
    Expected(String),
    RepetitionEmtpyTokenTree,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExpandError {
    NoMatchingRule,
    UnexpectedToken,
    BindingError(String),
    ConversionError,
    InvalidRepeat,
    ProcMacroError(tt::ExpansionError),
    UnresolvedProcMacro,
    Other(String),
}

impl From<tt::ExpansionError> for ExpandError {
    fn from(it: tt::ExpansionError) -> Self {
        ExpandError::ProcMacroError(it)
    }
}

impl fmt::Display for ExpandError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ExpandError::NoMatchingRule => f.write_str("no rule matches input tokens"),
            ExpandError::UnexpectedToken => f.write_str("unexpected token in input"),
            ExpandError::BindingError(e) => f.write_str(e),
            ExpandError::ConversionError => f.write_str("could not convert tokens"),
            ExpandError::InvalidRepeat => f.write_str("invalid repeat expression"),
            ExpandError::ProcMacroError(e) => e.fmt(f),
            ExpandError::UnresolvedProcMacro => f.write_str("unresolved proc macro"),
            ExpandError::Other(e) => f.write_str(e),
        }
    }
}

pub use crate::syntax_bridge::{
    ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node,
    TokenMap,
};

/// This struct contains AST for a single `macro_rules` definition. What might
/// be very confusing is that AST has almost exactly the same shape as
/// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident`
/// and `$()*` have special meaning (see `Var` and `Repeat` data structures)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MacroRules {
    rules: Vec<Rule>,
    /// Highest id of the token we have in TokenMap
    shift: Shift,
}

#[derive(Clone, Debug, PartialEq, Eq)]
struct Rule {
    lhs: MetaTemplate,
    rhs: MetaTemplate,
}

#[derive(Clone, Debug, PartialEq, Eq)]
struct MetaTemplate {
    delimiter: Option<Delimiter>,
    tokens: Vec<Result<Op, ExpandError>>,
}

impl<'a> MetaTemplate {
    fn iter(&self) -> impl Iterator<Item = &Result<Op, ExpandError>> {
        self.tokens.iter()
    }

    fn delimiter_kind(&self) -> Option<DelimiterKind> {
        self.delimiter.map(|it| it.kind)
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct Shift(u32);

impl Shift {
    fn new(tt: &tt::Subtree) -> Shift {
        // Note that TokenId is started from zero,
        // We have to add 1 to prevent duplication.
        let value = max_id(tt).map_or(0, |it| it + 1);
        return Shift(value);

        // Find the max token id inside a subtree
        fn max_id(subtree: &tt::Subtree) -> Option<u32> {
            subtree
                .token_trees
                .iter()
                .filter_map(|tt| match tt {
                    tt::TokenTree::Subtree(subtree) => {
                        let tree_id = max_id(subtree);
                        match subtree.delimiter {
                            Some(it) if it.id != tt::TokenId::unspecified() => {
                                Some(tree_id.map_or(it.id.0, |t| t.max(it.id.0)))
                            }
                            _ => tree_id,
                        }
                    }
                    tt::TokenTree::Leaf(tt::Leaf::Ident(ident))
                        if ident.id != tt::TokenId::unspecified() =>
                    {
                        Some(ident.id.0)
                    }
                    _ => None,
                })
                .max()
        }
    }

    /// Shift given TokenTree token id
    fn shift_all(self, tt: &mut tt::Subtree) {
        for t in tt.token_trees.iter_mut() {
            match t {
                tt::TokenTree::Leaf(leaf) => match leaf {
                    tt::Leaf::Ident(ident) => ident.id = self.shift(ident.id),
                    tt::Leaf::Punct(punct) => punct.id = self.shift(punct.id),
                    tt::Leaf::Literal(lit) => lit.id = self.shift(lit.id),
                },
                tt::TokenTree::Subtree(tt) => {
                    if let Some(it) = tt.delimiter.as_mut() {
                        it.id = self.shift(it.id);
                    };
                    self.shift_all(tt)
                }
            }
        }
    }

    fn shift(self, id: tt::TokenId) -> tt::TokenId {
        if id == tt::TokenId::unspecified() {
            return id;
        }
        tt::TokenId(id.0 + self.0)
    }

    fn unshift(self, id: tt::TokenId) -> Option<tt::TokenId> {
        id.0.checked_sub(self.0).map(tt::TokenId)
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum Origin {
    Def,
    Call,
}

impl MacroRules {
    pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> {
        // Note: this parsing can be implemented using mbe machinery itself, by
        // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
        // manually seems easier.
        let mut src = TtIter::new(tt);
        let mut rules = Vec::new();
        while src.len() > 0 {
            let rule = Rule::parse(&mut src)?;
            rules.push(rule);
            if let Err(()) = src.expect_char(';') {
                if src.len() > 0 {
                    return Err(ParseError::Expected("expected `;`".to_string()));
                }
                break;
            }
        }

        for rule in rules.iter() {
            validate(&rule.lhs)?;
        }

        Ok(MacroRules { rules, shift: Shift::new(tt) })
    }

    pub fn expand(&self, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
        // apply shift
        let mut tt = tt.clone();
        self.shift.shift_all(&mut tt);
        mbe_expander::expand(self, &tt)
    }

    pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
        self.shift.shift(id)
    }

    pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, Origin) {
        match self.shift.unshift(id) {
            Some(id) => (id, Origin::Call),
            None => (id, Origin::Def),
        }
    }
}

impl Rule {
    fn parse(src: &mut TtIter) -> Result<Rule, ParseError> {
        let lhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?;
        src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?;
        src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?;
        let rhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?;

        let lhs = MetaTemplate { tokens: parse_pattern(&lhs), delimiter: None };
        let rhs = MetaTemplate { tokens: parse_template(&rhs), delimiter: None };

        Ok(crate::Rule { lhs, rhs })
    }
}

fn to_parse_error(e: &ExpandError) -> ParseError {
    let msg = match e {
        ExpandError::InvalidRepeat => "invalid repeat".to_string(),
        _ => "invalid macro definition".to_string(),
    };
    ParseError::Expected(msg)
}

fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> {
    for op in pattern.iter() {
        let op = op.as_ref().map_err(|e| to_parse_error(&e))?;

        match op {
            Op::Subtree(subtree) => validate(&subtree)?,
            Op::Repeat { subtree, separator, .. } => {
                // Checks that no repetition which could match an empty token
                // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558

                if separator.is_none() {
                    if subtree.iter().all(|child_op| {
                        match child_op.as_ref().map_err(to_parse_error) {
                            Ok(Op::Var { kind, .. }) => {
                                // vis is optional
                                if kind.as_ref().map_or(false, |it| it == "vis") {
                                    return true;
                                }
                            }
                            Ok(Op::Repeat { kind, .. }) => {
                                return matches!(
                                    kind,
                                    parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne
                                )
                            }
                            _ => {}
                        }
                        false
                    }) {
                        return Err(ParseError::RepetitionEmtpyTokenTree);
                    }
                }
                validate(subtree)?
            }
            _ => (),
        }
    }
    Ok(())
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ExpandResult<T> {
    pub value: T,
    pub err: Option<ExpandError>,
}

impl<T> ExpandResult<T> {
    pub fn ok(value: T) -> Self {
        Self { value, err: None }
    }

    pub fn only_err(err: ExpandError) -> Self
    where
        T: Default,
    {
        Self { value: Default::default(), err: Some(err) }
    }

    pub fn str_err(err: String) -> Self
    where
        T: Default,
    {
        Self::only_err(ExpandError::Other(err))
    }

    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ExpandResult<U> {
        ExpandResult { value: f(self.value), err: self.err }
    }

    pub fn result(self) -> Result<T, ExpandError> {
        self.err.map(Err).unwrap_or(Ok(self.value))
    }
}

impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> {
    fn from(result: Result<T, ExpandError>) -> Self {
        result.map_or_else(|e| Self::only_err(e), |it| Self::ok(it))
    }
}
<commit_msg>Fixed typos in public type names<commit_after>//! `mbe` (short for Macro By Example) crate contains code for handling
//! `macro_rules` macros. It uses `TokenTree` (from `tt` package) as the
//! interface, although it contains some code to bridge `SyntaxNode`s and
//! `TokenTree`s as well!

mod parser;
mod mbe_expander;
mod syntax_bridge;
mod tt_iter;
mod subtree_source;

#[cfg(test)]
mod tests;

use std::fmt;

pub use tt::{Delimiter, DelimiterKind, Punct};

use crate::{
    parser::{parse_pattern, parse_template, Op},
    tt_iter::TtIter,
};

#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
    Expected(String),
    RepetitionEmptyTokenTree,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExpandError {
    NoMatchingRule,
    UnexpectedToken,
    BindingError(String),
    ConversionError,
    InvalidRepeat,
    ProcMacroError(tt::ExpansionError),
    UnresolvedProcMacro,
    Other(String),
}

impl From<tt::ExpansionError> for ExpandError {
    fn from(it: tt::ExpansionError) -> Self {
        ExpandError::ProcMacroError(it)
    }
}

impl fmt::Display for ExpandError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ExpandError::NoMatchingRule => f.write_str("no rule matches input tokens"),
            ExpandError::UnexpectedToken => f.write_str("unexpected token in input"),
            ExpandError::BindingError(e) => f.write_str(e),
            ExpandError::ConversionError => f.write_str("could not convert tokens"),
            ExpandError::InvalidRepeat => f.write_str("invalid repeat expression"),
            ExpandError::ProcMacroError(e) => e.fmt(f),
            ExpandError::UnresolvedProcMacro => f.write_str("unresolved proc macro"),
            ExpandError::Other(e) => f.write_str(e),
        }
    }
}

pub use crate::syntax_bridge::{
    ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node,
    TokenMap,
};

/// This struct contains AST for a single `macro_rules` definition. What might
/// be very confusing is that AST has almost exactly the same shape as
/// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident`
/// and `$()*` have special meaning (see `Var` and `Repeat` data structures)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MacroRules {
    rules: Vec<Rule>,
    /// Highest id of the token we have in TokenMap
    shift: Shift,
}

#[derive(Clone, Debug, PartialEq, Eq)]
struct Rule {
    lhs: MetaTemplate,
    rhs: MetaTemplate,
}

#[derive(Clone, Debug, PartialEq, Eq)]
struct MetaTemplate {
    delimiter: Option<Delimiter>,
    tokens: Vec<Result<Op, ExpandError>>,
}

impl<'a> MetaTemplate {
    fn iter(&self) -> impl Iterator<Item = &Result<Op, ExpandError>> {
        self.tokens.iter()
    }

    fn delimiter_kind(&self) -> Option<DelimiterKind> {
        self.delimiter.map(|it| it.kind)
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct Shift(u32);

impl Shift {
    fn new(tt: &tt::Subtree) -> Shift {
        // Note that TokenId is started from zero,
        // We have to add 1 to prevent duplication.
        let value = max_id(tt).map_or(0, |it| it + 1);
        return Shift(value);

        // Find the max token id inside a subtree
        fn max_id(subtree: &tt::Subtree) -> Option<u32> {
            subtree
                .token_trees
                .iter()
                .filter_map(|tt| match tt {
                    tt::TokenTree::Subtree(subtree) => {
                        let tree_id = max_id(subtree);
                        match subtree.delimiter {
                            Some(it) if it.id != tt::TokenId::unspecified() => {
                                Some(tree_id.map_or(it.id.0, |t| t.max(it.id.0)))
                            }
                            _ => tree_id,
                        }
                    }
                    tt::TokenTree::Leaf(tt::Leaf::Ident(ident))
                        if ident.id != tt::TokenId::unspecified() =>
                    {
                        Some(ident.id.0)
                    }
                    _ => None,
                })
                .max()
        }
    }

    /// Shift given TokenTree token id
    fn shift_all(self, tt: &mut tt::Subtree) {
        for t in tt.token_trees.iter_mut() {
            match t {
                tt::TokenTree::Leaf(leaf) => match leaf {
                    tt::Leaf::Ident(ident) => ident.id = self.shift(ident.id),
                    tt::Leaf::Punct(punct) => punct.id = self.shift(punct.id),
                    tt::Leaf::Literal(lit) => lit.id = self.shift(lit.id),
                },
                tt::TokenTree::Subtree(tt) => {
                    if let Some(it) = tt.delimiter.as_mut() {
                        it.id = self.shift(it.id);
                    };
                    self.shift_all(tt)
                }
            }
        }
    }

    fn shift(self, id: tt::TokenId) -> tt::TokenId {
        if id == tt::TokenId::unspecified() {
            return id;
        }
        tt::TokenId(id.0 + self.0)
    }

    fn unshift(self, id: tt::TokenId) -> Option<tt::TokenId> {
        id.0.checked_sub(self.0).map(tt::TokenId)
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum Origin {
    Def,
    Call,
}

impl MacroRules {
    pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> {
        // Note: this parsing can be implemented using mbe machinery itself, by
        // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
        // manually seems easier.
        let mut src = TtIter::new(tt);
        let mut rules = Vec::new();
        while src.len() > 0 {
            let rule = Rule::parse(&mut src)?;
            rules.push(rule);
            if let Err(()) = src.expect_char(';') {
                if src.len() > 0 {
                    return Err(ParseError::Expected("expected `;`".to_string()));
                }
                break;
            }
        }

        for rule in rules.iter() {
            validate(&rule.lhs)?;
        }

        Ok(MacroRules { rules, shift: Shift::new(tt) })
    }

    pub fn expand(&self, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
        // apply shift
        let mut tt = tt.clone();
        self.shift.shift_all(&mut tt);
        mbe_expander::expand(self, &tt)
    }

    pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
        self.shift.shift(id)
    }

    pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, Origin) {
        match self.shift.unshift(id) {
            Some(id) => (id, Origin::Call),
            None => (id, Origin::Def),
        }
    }
}

impl Rule {
    fn parse(src: &mut TtIter) -> Result<Rule, ParseError> {
        let lhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?;
        src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?;
        src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?;
        let rhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?;

        let lhs = MetaTemplate { tokens: parse_pattern(&lhs), delimiter: None };
        let rhs = MetaTemplate { tokens: parse_template(&rhs), delimiter: None };

        Ok(crate::Rule { lhs, rhs })
    }
}

fn to_parse_error(e: &ExpandError) -> ParseError {
    let msg = match e {
        ExpandError::InvalidRepeat => "invalid repeat".to_string(),
        _ => "invalid macro definition".to_string(),
    };
    ParseError::Expected(msg)
}

fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> {
    for op in pattern.iter() {
        let op = op.as_ref().map_err(|e| to_parse_error(&e))?;

        match op {
            Op::Subtree(subtree) => validate(&subtree)?,
            Op::Repeat { subtree, separator, .. } => {
                // Checks that no repetition which could match an empty token
                // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558

                if separator.is_none() {
                    if subtree.iter().all(|child_op| {
                        match child_op.as_ref().map_err(to_parse_error) {
                            Ok(Op::Var { kind, .. }) => {
                                // vis is optional
                                if kind.as_ref().map_or(false, |it| it == "vis") {
                                    return true;
                                }
                            }
                            Ok(Op::Repeat { kind, .. }) => {
                                return matches!(
                                    kind,
                                    parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne
                                )
                            }
                            _ => {}
                        }
                        false
                    }) {
                        return Err(ParseError::RepetitionEmptyTokenTree);
                    }
                }
                validate(subtree)?
            }
            _ => (),
        }
    }
    Ok(())
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ExpandResult<T> {
    pub value: T,
    pub err: Option<ExpandError>,
}

impl<T> ExpandResult<T> {
    pub fn ok(value: T) -> Self {
        Self { value, err: None }
    }

    pub fn only_err(err: ExpandError) -> Self
    where
        T: Default,
    {
        Self { value: Default::default(), err: Some(err) }
    }

    pub fn str_err(err: String) -> Self
    where
        T: Default,
    {
        Self::only_err(ExpandError::Other(err))
    }

    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ExpandResult<U> {
        ExpandResult { value: f(self.value), err: self.err }
    }

    pub fn result(self) -> Result<T, ExpandError> {
        self.err.map(Err).unwrap_or(Ok(self.value))
    }
}

impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> {
    fn from(result: Result<T, ExpandError>) -> Self {
        result.map_or_else(|e| Self::only_err(e), |it| Self::ok(it))
    }
}
<|endoftext|>


<commit_before>/// `encoding_struct!` implement structure that could be saved in blockchain.
///
/// Storage value unlike message, could be mapped on buffers without any checks.
/// For now it's required to set `encoding_struct` fixed part size as `const SIZE`.
///
/// For each field, it's required to set exact position in `encoding_struct`.
/// # Usage Example:
/// ```
/// #[macro_use] extern crate exonum;
/// # extern crate serde;
/// # extern crate serde_json;
///
/// encoding_struct! {
///     struct SaveTwoInteger {
///         const SIZE = 16;
///
///         field first: u64 [0 => 8]
///         field second: u64 [8 => 16]
///     }
/// }
/// # fn main() {
///     let first = 1u64;
///     let second = 2u64;
///     let s = SaveTwoInteger::new(first, second);
///     println!("Debug structure = {:?}", s);
/// # }
/// ```
///
/// For additional reference about data layout see also
/// *[ `encoding` documentation](./encoding/index.html).*
///
/// `encoding_struct!` internaly use `ident_count!`, be sure to add this macro to namespace.
#[macro_export]
macro_rules! encoding_struct {
    (
    $(#[$attr:meta])*
    struct $name:ident {
        const SIZE = $body:expr;

        $(
        $(#[$field_attr:meta])*
        field $field_name:ident : $field_type:ty [$from:expr => $to:expr]
        )*
    }) => (
        #[derive(Clone, PartialEq)]
        $(#[$attr])*
        pub struct $name {
            raw: Vec<u8>
        }

        // Reimplement `Field` for `encoding_struct!`
        // to write fields in place of another structure
        impl<'a> $crate::encoding::Field<'a> for $name {
            unsafe fn read(buffer: &'a [u8],
                            from: $crate::encoding::Offset,
                            to: $crate::encoding::Offset) -> Self {
                let vec: Vec<u8> = $crate::encoding::Field::read(buffer, from, to);
                $crate::storage::StorageValue::deserialize(vec)
            }

            fn write(&self,
                            buffer: &mut Vec<u8>,
                            from: $crate::encoding::Offset,
                            to: $crate::encoding::Offset) {
                $crate::encoding::Field::write(&self.raw, buffer, from, to);
            }

            #[allow(unused_variables)]
            fn check(buffer: &'a [u8],
                        from_st_val: $crate::encoding::CheckedOffset,
                        to_st_val: $crate::encoding::CheckedOffset,
                        latest_segment: $crate::encoding::CheckedOffset)
                -> $crate::encoding::Result
            {
                let latest_segment_origin = <&[u8] as $crate::encoding::Field>::check(buffer, from_st_val, to_st_val, latest_segment)?;
                let vec: &[u8] = unsafe{ $crate::encoding::Field::read(buffer,
                                                                        from_st_val.unchecked_offset(),
                                                                        to_st_val.unchecked_offset())};
                let latest_segment = ($body as $crate::encoding::Offset).into();
                $(
                let latest_segment = <$field_type as $crate::encoding::Field>::check(&vec,
                                                                        $from.into(),
                                                                        $to.into(),
                                                                        latest_segment)?;
                )*
                Ok(latest_segment_origin)
            }

            fn field_size() -> $crate::encoding::Offset {
                // We write `encoding_struct` as regular buffer,
                // so real `field_size` is 8.
                // TODO: maybe we should write it as sub structure in place?
                // We could get benefit from it: we limit indirection
                // in deserializing sub fields, by only one calculation.

                // $body as $crate::encoding::Offset

                8 as $crate::encoding::Offset
            }
        }

        impl $crate::storage::StorageValue for $name {
            fn serialize(self) -> Vec<u8> {
                self.raw
            }

            fn deserialize(v: Vec<u8>) -> Self {
                $name {
                    raw: v
                }
            }

            fn hash(&self) -> $crate::crypto::Hash {
                $name::hash(self)
            }
        }

        // TODO extract some fields like hash and from_raw into trait
        impl $name {
            #[cfg_attr(feature="cargo-clippy", allow(too_many_arguments))]
            /// Create `$name`.
            pub fn new($($field_name: $field_type,)*) -> $name {
                use $crate::encoding::{Field};
                let mut buf = vec![0; $body];
                $($field_name.write(&mut buf, $from, $to);)*
                $name { raw: buf }
            }

            pub fn hash(&self) -> $crate::crypto::Hash {
                $crate::crypto::hash(self.raw.as_ref())
            }

            $(
            $(#[$field_attr])*
            pub fn $field_name(&self) -> $field_type {
                use $crate::encoding::Field;
                unsafe {
                    Field::read(&self.raw, $from, $to)
                }
            })*
        }

        impl ::std::fmt::Debug for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                -> Result<(), ::std::fmt::Error> {
                fmt.debug_struct(stringify!($name))
                 $(.field(stringify!($field_name), &self.$field_name()))*
                   .finish()
            }
        }

        impl $crate::encoding::serialize::json::ExonumJson for $name {
            fn deserialize_field<B> (value: &$crate::encoding::serialize::json::reexport::Value,
                                        buffer: & mut B,
                                        from: $crate::encoding::Offset,
                                        _to: $crate::encoding::Offset )
                -> Result<(), Box<::std::error::Error>>
                where B: $crate::encoding::serialize::WriteBufferWrapper
            {
                use $crate::encoding::serialize::json::ExonumJson;
                let obj = value.as_object().ok_or("Can't cast json as object.")?;
                $(
                let val = obj.get(stringify!($field_name)).ok_or("Can't get object from json.")?;

                <$field_type as ExonumJson>::deserialize_field(val, buffer,
                                                                from + $from, from + $to )?;

                )*
                Ok(())
            }

            fn serialize_field(&self)
                -> Result<$crate::encoding::serialize::json::reexport::Value,
                            Box<::std::error::Error>>
            {
                use $crate::encoding::serialize::json::reexport::Value;
                let mut map = $crate::encoding::serialize::json::reexport::Map::new();
                $(
                    map.insert(stringify!($field_name).to_string(),
                        self.$field_name().serialize_field()?);
                )*
                Ok(Value::Object(map))
            }
        }
        impl $crate::encoding::serialize::json::ExonumJsonDeserialize for $name {
            fn deserialize(value: &::serde_json::Value) -> Result<Self, Box<::std::error::Error>> {
                let to = $body as $crate::encoding::Offset;
                let from = 0;
                use $crate::encoding::serialize::json::ExonumJson;

                let mut buf = vec![0; $body];
                <Self as ExonumJson>::deserialize_field(value, &mut buf, from, to)?;
                Ok($name { raw: buf })
            }
        }

        // TODO: Rewrite Deserialize and Serialize implementation
        impl<'de> $crate::encoding::serialize::reexport::Deserialize<'de> for $name {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
                where D: $crate::encoding::serialize::reexport::Deserializer<'de>
            {
                use $crate::encoding::serialize::json::reexport::Value;
                use $crate::encoding::serialize::reexport::{DeError, Deserialize};
                let value = <Value as Deserialize>::deserialize(deserializer)?;
                <Self as $crate::encoding::serialize::json::ExonumJsonDeserialize>::deserialize(&value)
                .map_err(|_| D::Error::custom("Can not deserialize value."))
            }
        }

        impl $crate::encoding::serialize::reexport::Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: $crate::encoding::serialize::reexport::Serializer
            {
                use $crate::encoding::serialize::reexport::SerError;
                use $crate::encoding::serialize::json::ExonumJson;
                self.serialize_field()
                    .map_err(|_| S::Error::custom(
                                concat!("Can not serialize structure: ", stringify!($name))))?
                    .serialize(serializer)
            }
        }
    )
}
<commit_msg>Use reexport of serde_json crate for encoding_struct macro<commit_after>/// `encoding_struct!` implement structure that could be saved in blockchain.
///
/// Storage value unlike message, could be mapped on buffers without any checks.
/// For now it's required to set `encoding_struct` fixed part size as `const SIZE`.
///
/// For each field, it's required to set exact position in `encoding_struct`.
/// # Usage Example:
/// ```
/// #[macro_use] extern crate exonum;
/// # extern crate serde;
/// # extern crate serde_json;
///
/// encoding_struct! {
///     struct SaveTwoInteger {
///         const SIZE = 16;
///
///         field first: u64 [0 => 8]
///         field second: u64 [8 => 16]
///     }
/// }
/// # fn main() {
///     let first = 1u64;
///     let second = 2u64;
///     let s = SaveTwoInteger::new(first, second);
///     println!("Debug structure = {:?}", s);
/// # }
/// ```
///
/// For additional reference about data layout see also
/// *[ `encoding` documentation](./encoding/index.html).*
///
/// `encoding_struct!` internaly use `ident_count!`, be sure to add this macro to namespace.
#[macro_export]
macro_rules! encoding_struct {
    (
    $(#[$attr:meta])*
    struct $name:ident {
        const SIZE = $body:expr;

        $(
        $(#[$field_attr:meta])*
        field $field_name:ident : $field_type:ty [$from:expr => $to:expr]
        )*
    }) => (
        #[derive(Clone, PartialEq)]
        $(#[$attr])*
        pub struct $name {
            raw: Vec<u8>
        }

        // Reimplement `Field` for `encoding_struct!`
        // to write fields in place of another structure
        impl<'a> $crate::encoding::Field<'a> for $name {
            unsafe fn read(buffer: &'a [u8],
                            from: $crate::encoding::Offset,
                            to: $crate::encoding::Offset) -> Self {
                let vec: Vec<u8> = $crate::encoding::Field::read(buffer, from, to);
                $crate::storage::StorageValue::deserialize(vec)
            }

            fn write(&self,
                            buffer: &mut Vec<u8>,
                            from: $crate::encoding::Offset,
                            to: $crate::encoding::Offset) {
                $crate::encoding::Field::write(&self.raw, buffer, from, to);
            }

            #[allow(unused_variables)]
            fn check(buffer: &'a [u8],
                        from_st_val: $crate::encoding::CheckedOffset,
                        to_st_val: $crate::encoding::CheckedOffset,
                        latest_segment: $crate::encoding::CheckedOffset)
                -> $crate::encoding::Result
            {
                let latest_segment_origin = <&[u8] as $crate::encoding::Field>::check(buffer, from_st_val, to_st_val, latest_segment)?;
                let vec: &[u8] = unsafe{ $crate::encoding::Field::read(buffer,
                                                                        from_st_val.unchecked_offset(),
                                                                        to_st_val.unchecked_offset())};
                let latest_segment = ($body as $crate::encoding::Offset).into();
                $(
                let latest_segment = <$field_type as $crate::encoding::Field>::check(&vec,
                                                                        $from.into(),
                                                                        $to.into(),
                                                                        latest_segment)?;
                )*
                Ok(latest_segment_origin)
            }

            fn field_size() -> $crate::encoding::Offset {
                // We write `encoding_struct` as regular buffer,
                // so real `field_size` is 8.
                // TODO: maybe we should write it as sub structure in place?
                // We could get benefit from it: we limit indirection
                // in deserializing sub fields, by only one calculation.

                // $body as $crate::encoding::Offset

                8 as $crate::encoding::Offset
            }
        }

        impl $crate::storage::StorageValue for $name {
            fn serialize(self) -> Vec<u8> {
                self.raw
            }

            fn deserialize(v: Vec<u8>) -> Self {
                $name {
                    raw: v
                }
            }

            fn hash(&self) -> $crate::crypto::Hash {
                $name::hash(self)
            }
        }

        // TODO extract some fields like hash and from_raw into trait
        impl $name {
            #[cfg_attr(feature="cargo-clippy", allow(too_many_arguments))]
            /// Create `$name`.
            pub fn new($($field_name: $field_type,)*) -> $name {
                use $crate::encoding::{Field};
                let mut buf = vec![0; $body];
                $($field_name.write(&mut buf, $from, $to);)*
                $name { raw: buf }
            }

            pub fn hash(&self) -> $crate::crypto::Hash {
                $crate::crypto::hash(self.raw.as_ref())
            }

            $(
            $(#[$field_attr])*
            pub fn $field_name(&self) -> $field_type {
                use $crate::encoding::Field;
                unsafe {
                    Field::read(&self.raw, $from, $to)
                }
            })*
        }

        impl ::std::fmt::Debug for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                -> Result<(), ::std::fmt::Error> {
                fmt.debug_struct(stringify!($name))
                 $(.field(stringify!($field_name), &self.$field_name()))*
                   .finish()
            }
        }

        impl $crate::encoding::serialize::json::ExonumJson for $name {
            fn deserialize_field<B> (value: &$crate::encoding::serialize::json::reexport::Value,
                                        buffer: & mut B,
                                        from: $crate::encoding::Offset,
                                        _to: $crate::encoding::Offset )
                -> Result<(), Box<::std::error::Error>>
                where B: $crate::encoding::serialize::WriteBufferWrapper
            {
                use $crate::encoding::serialize::json::ExonumJson;
                let obj = value.as_object().ok_or("Can't cast json as object.")?;
                $(
                let val = obj.get(stringify!($field_name)).ok_or("Can't get object from json.")?;

                <$field_type as ExonumJson>::deserialize_field(val, buffer,
                                                                from + $from, from + $to )?;

                )*
                Ok(())
            }

            fn serialize_field(&self)
                -> Result<$crate::encoding::serialize::json::reexport::Value,
                            Box<::std::error::Error>>
            {
                use $crate::encoding::serialize::json::reexport::Value;
                let mut map = $crate::encoding::serialize::json::reexport::Map::new();
                $(
                    map.insert(stringify!($field_name).to_string(),
                        self.$field_name().serialize_field()?);
                )*
                Ok(Value::Object(map))
            }
        }
        impl $crate::encoding::serialize::json::ExonumJsonDeserialize for $name {
            fn deserialize(value: &$crate::encoding::serialize::json::reexport::Value) -> Result<Self, Box<::std::error::Error>> {
                let to = $body as $crate::encoding::Offset;
                let from = 0;
                use $crate::encoding::serialize::json::ExonumJson;

                let mut buf = vec![0; $body];
                <Self as ExonumJson>::deserialize_field(value, &mut buf, from, to)?;
                Ok($name { raw: buf })
            }
        }

        // TODO: Rewrite Deserialize and Serialize implementation
        impl<'de> $crate::encoding::serialize::reexport::Deserialize<'de> for $name {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
                where D: $crate::encoding::serialize::reexport::Deserializer<'de>
            {
                use $crate::encoding::serialize::json::reexport::Value;
                use $crate::encoding::serialize::reexport::{DeError, Deserialize};
                let value = <Value as Deserialize>::deserialize(deserializer)?;
                <Self as $crate::encoding::serialize::json::ExonumJsonDeserialize>::deserialize(&value)
                .map_err(|_| D::Error::custom("Can not deserialize value."))
            }
        }

        impl $crate::encoding::serialize::reexport::Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: $crate::encoding::serialize::reexport::Serializer
            {
                use $crate::encoding::serialize::reexport::SerError;
                use $crate::encoding::serialize::json::ExonumJson;
                self.serialize_field()
                    .map_err(|_| S::Error::custom(
                                concat!("Can not serialize structure: ", stringify!($name))))?
                    .serialize(serializer)
            }
        }
    )
}
<|endoftext|>


<commit_before>#![macro_escape]

use std::str::Chars;
use std::vec::Vec;
use std::io::IoResult;

#[deriving(Clone)]
pub struct ParseBranch {
    matches: Vec<u8>,
    result: Option<String>,
    children: Vec<ParseBranch>,
}

impl ParseBranch {
    fn new() -> ParseBranch {
        ParseBranch {
            matches: Vec::new(),
            result: None,
            children: Vec::new()
        }
    }
}

pub fn branchify(options: &[(&str, &str)], case_sensitive: bool) -> Vec<ParseBranch> {
    let mut root = ParseBranch::new();

    fn go_down_moses(branch: &mut ParseBranch, mut chariter: Chars, result: &str, case_sensitive: bool) {
        match chariter.next() {
            Some(c) => {
                let first_case = if case_sensitive { c as u8 } else { c.to_ascii().to_uppercase().to_byte() };
                for next_branch in branch.children.iter_mut() {
                    if next_branch.matches[0] == first_case {
                        go_down_moses(next_branch, chariter, result, case_sensitive);
                        return;
                    }
                }
                let mut subbranch = ParseBranch::new();
                subbranch.matches.push(first_case);
                if !case_sensitive {
                    let second_case = c.to_ascii().to_lowercase().to_byte();
                    if first_case != second_case {
                        subbranch.matches.push(second_case);
                    }
                }
                branch.children.push(subbranch);
                let i = branch.children.len() - 1;
                go_down_moses(&mut branch.children[i], chariter, result, case_sensitive);
            },
            None => {
                assert!(branch.result.is_none());
                branch.result = Some(String::from_str(result));
            },
        }
    };

    for &(key, result) in options.iter() {
        go_down_moses(&mut root, key.chars(), result, case_sensitive);
    }

    root.children
}

macro_rules! branchify(
    (case sensitive, $($key:expr => $value:ident),*) => (
        ::branchify::branchify([$(($key, stringify!($value))),*], true)
    );
    (case insensitive, $($key:expr => $value:ident),*) => (
        ::branchify::branchify([$(($key, stringify!($value))),*], false)
    );
)

/// Prints the contents to stdout.
///
/// :param branches: the branches to search through
/// :param indent: the level of indentation (each level representing four leading spaces)
/// :param read_call: the function call to read a byte
/// :param end: the byte which marks the end of the sequence
/// :param max_len: the maximum length a value may be before giving up and returning ``None``
/// :param valid: the function call to if a byte ``b`` is valid
/// :param unknown: the expression to call for an unknown value; in this string, ``{}`` will be
///         replaced with an expression (literal or non-literal) evaluating to a ``String`` (it is
///         ``{}`` only, not arbitrary format strings)
pub fn generate_branchified_method(
        writer: &mut Writer,
        branches: Vec<ParseBranch>,
        indent: uint,
        read_call: &str,
        end: &str,
        max_len: &str,
        valid: &str,
        unknown: &str) -> IoResult<()> {

    fn r(writer: &mut Writer, branch: &ParseBranch, prefix: &str, indent: uint, read_call: &str,
            end: &str, max_len: &str, valid: &str, unknown: &str) -> IoResult<()> {
        let indentstr = " ".repeat(indent * 4);
        macro_rules! w (
            ($s:expr) => {
                try!(write!(writer, "{}{}\n", indentstr, $s))
            }
        )
        for &c in branch.matches.iter() {
            let next_prefix = format!("{}{}", prefix, c as char);
            w!(format!("Ok(b'{}') => match {} {{", c as char, read_call));
            for b in branch.children.iter() {
                try!(r(writer, b, next_prefix[], indent + 1, read_call, end, max_len, valid, unknown));
            }
            match branch.result {
                Some(ref result) =>
                    w!(format!("    Ok(b' ') => return Ok({}),", *result)),
                None => w!(format!("    Ok(b' ') => return Ok({}),",
                                  unknown.replace("{}", format!("String::from_str(\"{}\")", next_prefix)[]))),
            }
            w!(format!("    Ok(b) if {} => (\"{}\", b),", valid, next_prefix));
            w!("    Ok(_) => return Err(::std::io::IoError { kind: ::std::io::OtherIoError, desc: \"bad value\", detail: None }),");
            w!("    Err(err) => return Err(err),");
            w!("},");
        }
        Ok(())
    }
    let indentstr = " ".repeat(indent * 4);
    macro_rules! w (
        ($s:expr) => {
            try!(write!(writer, "{}{}\n", indentstr, $s))
        }
    )

    w!(format!("let (s, next_byte) = match {} {{", read_call));
    for b in branches.iter() {
        try!(r(writer, b, "", indent + 1, read_call, end, max_len, valid, unknown));
    }
    w!(format!("    Ok(b) if {} => (\"\", b),", valid));
    w!(       ("    Ok(_) => return Err(::std::io::IoError { kind: ::std::io::OtherIoError, desc: \"bad value\", detail: None }),"));
    w!(       ("    Err(err) => return Err(err),"));
    w!(       ("};"));
    w!(       ("// OK, that didn't pan out. Let's read the rest and see what we get."));
    w!(       ("let mut s = String::from_str(s);"));
    w!(       ("s.push(next_byte as char);"));
    w!(       ("loop {"));
    w!(format!("    match {} {{", read_call));
    w!(format!("        Ok(b) if b == {} => return Ok({}),", end, unknown.replace("{}", "s")));
    w!(format!("        Ok(b) if {} => {{", valid));
    w!(format!("            if s.len() == {} {{", max_len));
    w!(       ("                // Too long; bad request"));
    w!(       ("                return Err(::std::io::IoError { kind: ::std::io::OtherIoError, desc: \"too long, bad request\", detail: None });"));
    w!(       ("            }"));
    w!(       ("            s.push(b as char);"));
    w!(       ("        },"));
    w!(       ("        Ok(_) => return Err(::std::io::IoError { kind: ::std::io::OtherIoError, desc: \"bad value\", detail: None }),"));
    w!(       ("        Err(err) => return Err(err),"));
    w!(       ("    }"));
    w!(       ("}"));
    Ok(())
}
<commit_msg>Rust update: no more `[T, ..n]` -> `&[T]` coercion<commit_after>#![macro_escape]

use std::str::Chars;
use std::vec::Vec;
use std::io::IoResult;

#[deriving(Clone)]
pub struct ParseBranch {
    matches: Vec<u8>,
    result: Option<String>,
    children: Vec<ParseBranch>,
}

impl ParseBranch {
    fn new() -> ParseBranch {
        ParseBranch {
            matches: Vec::new(),
            result: None,
            children: Vec::new()
        }
    }
}

pub fn branchify(options: &[(&str, &str)], case_sensitive: bool) -> Vec<ParseBranch> {
    let mut root = ParseBranch::new();

    fn go_down_moses(branch: &mut ParseBranch, mut chariter: Chars, result: &str, case_sensitive: bool) {
        match chariter.next() {
            Some(c) => {
                let first_case = if case_sensitive { c as u8 } else { c.to_ascii().to_uppercase().to_byte() };
                for next_branch in branch.children.iter_mut() {
                    if next_branch.matches[0] == first_case {
                        go_down_moses(next_branch, chariter, result, case_sensitive);
                        return;
                    }
                }
                let mut subbranch = ParseBranch::new();
                subbranch.matches.push(first_case);
                if !case_sensitive {
                    let second_case = c.to_ascii().to_lowercase().to_byte();
                    if first_case != second_case {
                        subbranch.matches.push(second_case);
                    }
                }
                branch.children.push(subbranch);
                let i = branch.children.len() - 1;
                go_down_moses(&mut branch.children[i], chariter, result, case_sensitive);
            },
            None => {
                assert!(branch.result.is_none());
                branch.result = Some(String::from_str(result));
            },
        }
    };

    for &(key, result) in options.iter() {
        go_down_moses(&mut root, key.chars(), result, case_sensitive);
    }

    root.children
}

macro_rules! branchify(
    (case sensitive, $($key:expr => $value:ident),*) => (
        ::branchify::branchify(&[$(($key, stringify!($value))),*], true)
    );
    (case insensitive, $($key:expr => $value:ident),*) => (
        ::branchify::branchify(&[$(($key, stringify!($value))),*], false)
    );
)

/// Prints the contents to stdout.
///
/// :param branches: the branches to search through
/// :param indent: the level of indentation (each level representing four leading spaces)
/// :param read_call: the function call to read a byte
/// :param end: the byte which marks the end of the sequence
/// :param max_len: the maximum length a value may be before giving up and returning ``None``
/// :param valid: the function call to if a byte ``b`` is valid
/// :param unknown: the expression to call for an unknown value; in this string, ``{}`` will be
///         replaced with an expression (literal or non-literal) evaluating to a ``String`` (it is
///         ``{}`` only, not arbitrary format strings)
pub fn generate_branchified_method(
        writer: &mut Writer,
        branches: Vec<ParseBranch>,
        indent: uint,
        read_call: &str,
        end: &str,
        max_len: &str,
        valid: &str,
        unknown: &str) -> IoResult<()> {

    fn r(writer: &mut Writer, branch: &ParseBranch, prefix: &str, indent: uint, read_call: &str,
            end: &str, max_len: &str, valid: &str, unknown: &str) -> IoResult<()> {
        let indentstr = " ".repeat(indent * 4);
        macro_rules! w (
            ($s:expr) => {
                try!(write!(writer, "{}{}\n", indentstr, $s))
            }
        )
        for &c in branch.matches.iter() {
            let next_prefix = format!("{}{}", prefix, c as char);
            w!(format!("Ok(b'{}') => match {} {{", c as char, read_call));
            for b in branch.children.iter() {
                try!(r(writer, b, next_prefix[], indent + 1, read_call, end, max_len, valid, unknown));
            }
            match branch.result {
                Some(ref result) =>
                    w!(format!("    Ok(b' ') => return Ok({}),", *result)),
                None => w!(format!("    Ok(b' ') => return Ok({}),",
                                  unknown.replace("{}", format!("String::from_str(\"{}\")", next_prefix)[]))),
            }
            w!(format!("    Ok(b) if {} => (\"{}\", b),", valid, next_prefix));
            w!("    Ok(_) => return Err(::std::io::IoError { kind: ::std::io::OtherIoError, desc: \"bad value\", detail: None }),");
            w!("    Err(err) => return Err(err),");
            w!("},");
        }
        Ok(())
    }
    let indentstr = " ".repeat(indent * 4);
    macro_rules! w (
        ($s:expr) => {
            try!(write!(writer, "{}{}\n", indentstr, $s))
        }
    )

    w!(format!("let (s, next_byte) = match {} {{", read_call));
    for b in branches.iter() {
        try!(r(writer, b, "", indent + 1, read_call, end, max_len, valid, unknown));
    }
    w!(format!("    Ok(b) if {} => (\"\", b),", valid));
    w!(       ("    Ok(_) => return Err(::std::io::IoError { kind: ::std::io::OtherIoError, desc: \"bad value\", detail: None }),"));
    w!(       ("    Err(err) => return Err(err),"));
    w!(       ("};"));
    w!(       ("// OK, that didn't pan out. Let's read the rest and see what we get."));
    w!(       ("let mut s = String::from_str(s);"));
    w!(       ("s.push(next_byte as char);"));
    w!(       ("loop {"));
    w!(format!("    match {} {{", read_call));
    w!(format!("        Ok(b) if b == {} => return Ok({}),", end, unknown.replace("{}", "s")));
    w!(format!("        Ok(b) if {} => {{", valid));
    w!(format!("            if s.len() == {} {{", max_len));
    w!(       ("                // Too long; bad request"));
    w!(       ("                return Err(::std::io::IoError { kind: ::std::io::OtherIoError, desc: \"too long, bad request\", detail: None });"));
    w!(       ("            }"));
    w!(       ("            s.push(b as char);"));
    w!(       ("        },"));
    w!(       ("        Ok(_) => return Err(::std::io::IoError { kind: ::std::io::OtherIoError, desc: \"bad value\", detail: None }),"));
    w!(       ("        Err(err) => return Err(err),"));
    w!(       ("    }"));
    w!(       ("}"));
    Ok(())
}
<|endoftext|>


<commit_before>mod events;

use winit::{WindowBuilder, get_available_monitors, get_primary_monitor, Event, ElementState};
use vulkano_win::{Window, VkSurfaceBuild, required_extensions};
use vulkano::instance::{Instance, PhysicalDevice};
use vulkano::device::{Queue, Device, DeviceExtensions};
use vulkano::swapchain::{Swapchain, SurfaceTransform, PresentMode};
use vulkano::image::SwapchainImage;
use vulkano::image::attachment::AttachmentImage;
use vulkano::framebuffer::Framebuffer;
use vulkano::command_buffer::{PrimaryCommandBufferBuilder, Submission, submit};
use vulkano::format;

use config::Config;
use config::WindowConfig;

use std::sync::Arc;
use std::time::Duration;
use std::collections::HashMap;

mod render_pass {

    use vulkano::format;
    use vulkano::format::Format;

    single_pass_renderpass!{
    attachments: {
        color: {
            load: Clear,
            store: Store,
            format: Format,
        },
        depth: {
            load: Clear,
            store: DontCare,
            format: format::D16Unorm,
            }
        },
        pass: {
            color: [color],
            depth_stencil: {depth}
        }
    }
}

pub struct Engine {
    window: Window,
    instance: Arc<Instance>,
    physical_device: usize,
    device: Arc<Device>,
    swapchain: Arc<Swapchain>,
    images: Vec<Arc<SwapchainImage>>,
    depth_buffer: Arc<AttachmentImage<format::D16Unorm>>,
    render_pass: Arc<render_pass::CustomRenderPass>,
    framebuffers: Vec<Arc<Framebuffer<render_pass::CustomRenderPass>>>,
    submissions: Vec<Arc<Submission>>,
    queue: Arc<Queue>,
    config: Config,
    inputs: HashMap<String, f32>,
}

impl Engine {
    pub fn new(config: Config) -> Engine {

        let window_builder = create_window(&config.window);

        let instance = {
            let extensions = required_extensions();
            Instance::new(None, &extensions, None).expect("Failed to create Vulkan instance.")
        };

        let ins = &instance.clone();

        let physical = PhysicalDevice::enumerate(&ins)
            .next()
            .expect("No vulkan device is available.");

        let physical_device = physical.index();

        let window = window_builder.build_vk_surface(&instance).unwrap();

        let queue = physical
            .queue_families()
            .find(|q| q.supports_graphics() && window.surface().is_supported(q).unwrap_or(false))
            .expect("Couldn't find a graphical queue family.");

        // Logical Device, Queues
        let (device, mut queues) = {
            let device_ext = DeviceExtensions {
                khr_swapchain: true,
                ..DeviceExtensions::none()
            };

            Device::new(&physical,
                        physical.supported_features(),
                        &device_ext,
                        [(queue, 0.5)].iter().cloned())
                    .expect("failed to create device")
        };

        // Device Queue
        let queue = queues.next().unwrap();

        // Swapchain, Swapchain Images
        let (swapchain, images) =
            create_swapchain(&window, &physical, &device, &queue, None, &config);

        let depth_buffer =
            AttachmentImage::transient(&device, images[0].dimensions(), format::D16Unorm).unwrap();

        // Render Pass
        let render_pass =
            render_pass::CustomRenderPass::new(&device,
                                               &render_pass::Formats {
                                                    // Use the format of the images and one sample.
                                                    color: (images[0].format(), 1),
                                                    depth: (format::D16Unorm, 1),
                                                })
                    .unwrap();

        let framebuffers = images
            .iter()
            .map(|image| {
                let attachments = render_pass::AList {
                    color: &image,
                    depth: &depth_buffer,
                };

                Framebuffer::new(&render_pass,
                                 [image.dimensions()[0], image.dimensions()[1], 1],
                                 attachments)
                        .unwrap()
            })
            .collect::<Vec<_>>();

        // Queue Submissions
        let submissions = Vec::new();

        // Input System
        let mut inputs: HashMap<String, f32> = config
            .input
            .keys()
            .map(|k| (k.clone(), 0.0f32))
            .collect();

        Engine {
            window: window,
            instance,
            physical_device,
            device,
            swapchain,
            images,
            depth_buffer,
            framebuffers,
            render_pass,
            submissions,
            queue,
            config,
            inputs,
        }
    }

    /// Handles input/output events from the window and any input middleware.
    pub fn io(&mut self) -> bool {

        for ev in self.window.window().poll_events() {

            // Axis Map
            for (string_key, axis) in self.config.input.iter() {
                for axis_value in axis {

                    let out = events::string_to_wevent(&axis_value.key, &ev);

                    // Check axis_value.meta for additional checks.

                    // Write to axis map
                    match out {
                        Some(x) => *self.inputs.get_mut(string_key).unwrap() = x,
                        None => (),
                    };

                }
            }

            // Core Events
            match &ev {
                &Event::Resized(w, h) => {
                    self.config.window.resolution = [w, h];
                    let (swapchain, images) =
                        create_swapchain(&self.window,
                                         &PhysicalDevice::from_index(&self.instance,
                                                                     self.physical_device)
                                                  .unwrap(),
                                         &self.device,
                                         &self.queue,
                                         Some(&self.swapchain),
                                         &self.config);
                    self.swapchain = swapchain;
                    self.images = images;
                    self.depth_buffer = AttachmentImage::transient(&self.device,
                                                                   self.images[0].dimensions(),
                                                                   format::D16Unorm)
                            .unwrap();
                    self.framebuffers = self.images
                        .iter()
                        .map(|image| {
                            let attachments = render_pass::AList {
                                color: &image,
                                depth: &self.depth_buffer,
                            };

                            Framebuffer::new(&self.render_pass,
                                             [image.dimensions()[0], image.dimensions()[1], 1],
                                             attachments)
                                    .unwrap()
                        })
                        .collect::<Vec<_>>();
                }
                &Event::Closed => return false,
                _ => (),
            };
        }

        true
    }

    /// Recursively updates application tree.
    pub fn update(&self) {

        //@TODO recursively map each update function from each node.
        //node.children.map(update)

    }

    /// Updates the display surface with a new image.
    pub fn render(&mut self) {
        let command_buffers = self.framebuffers
            .iter()
            .map(|framebuffer| {
                PrimaryCommandBufferBuilder::new(&self.device, self.queue.family())
                    .draw_inline(&self.render_pass,
                                 &framebuffer,
                                 render_pass::ClearValues {
                                     color: [0.2, 0.4, 0.8, 1.0],
                                     depth: 1.0,
                                 })
                    .draw_end()
                    .build()
            })
            .collect::<Vec<_>>();
        let image_num = self.swapchain
            .acquire_next_image(Duration::new(1, 0))
            .unwrap();

        // @TODO build command buffers with threads and submit the changes in main thread (here)
        self.submissions
            .push(submit(&command_buffers[image_num], &self.queue).unwrap());

        self.swapchain.present(&self.queue, image_num).unwrap();
    }
}

/// Sets up and creates a swapchain
fn create_swapchain(window: &Window,
                    physical_device: &PhysicalDevice,
                    device: &Arc<Device>,
                    queue: &Arc<Queue>,
                    old: Option<&Arc<Swapchain>>,
                    config: &Config)
                    -> (Arc<Swapchain>, Vec<Arc<SwapchainImage>>) {
    {
        let caps = window
            .surface()
            .get_capabilities(&physical_device)
            .expect("failed to get surface capabilities");

        let dimensions = if config.window.resolution[0] <= 240 ||
                            config.window.resolution[1] <= 240 {
            caps.current_extent.unwrap_or([800, 600])
        } else {
            config.window.resolution
        };

        let present = if config.graphics.vsync &&
                         caps.present_modes.supports(PresentMode::Mailbox) {
            PresentMode::Mailbox
        } else {
            caps.present_modes.iter().next().unwrap()
        };

        let alpha = caps.supported_composite_alpha.iter().next().unwrap();

        let format = caps.supported_formats[0].0;

        Swapchain::new(&device,
                       &window.surface(),
                       caps.min_image_count,
                       format,
                       dimensions,
                       1,
                       &caps.supported_usage_flags,
                       queue,
                       SurfaceTransform::Identity,
                       alpha,
                       present,
                       true,
                       old)
                .expect("failed to create swapchain")
    }
}

/// Creates a window builder with a given window configuration.
fn create_window(config: &WindowConfig) -> WindowBuilder {

    let mut w = get_primary_monitor();
    let dimensions = w.get_dimensions();

    // Set resolution
    let resolution = if config.resolution[0] <= 240 || config.resolution[1] <= 240 {
        [dimensions.0, dimensions.1]
    } else {
        config.resolution.clone()
    };

    // Set fullscreen
    if config.fullscreen {
        for (i, monitor) in get_available_monitors().enumerate() {
            if i == config.display as usize {
                w = monitor;
            }
        }
    }

    // Create manager
    let window_manager = WindowBuilder::new()
        .with_title("CodeVR")
        .with_dimensions(resolution[0], resolution[1]);

    if config.fullscreen {
        return window_manager.with_fullscreen(w);
    }

    window_manager
}
<commit_msg>Fixed minimizing bug<commit_after>mod events;

use winit::{WindowBuilder, get_available_monitors, get_primary_monitor, Event, ElementState};
use vulkano_win::{Window, VkSurfaceBuild, required_extensions};
use vulkano::instance::{Instance, PhysicalDevice};
use vulkano::device::{Queue, Device, DeviceExtensions};
use vulkano::swapchain::{Swapchain, SurfaceTransform, PresentMode};
use vulkano::image::SwapchainImage;
use vulkano::image::attachment::AttachmentImage;
use vulkano::framebuffer::Framebuffer;
use vulkano::command_buffer::{PrimaryCommandBufferBuilder, Submission, submit};
use vulkano::format;

use config::Config;
use config::WindowConfig;

use std::sync::Arc;
use std::time::Duration;
use std::collections::HashMap;

mod render_pass {

    use vulkano::format;
    use vulkano::format::Format;

    single_pass_renderpass!{
    attachments: {
        color: {
            load: Clear,
            store: Store,
            format: Format,
        },
        depth: {
            load: Clear,
            store: DontCare,
            format: format::D16Unorm,
            }
        },
        pass: {
            color: [color],
            depth_stencil: {depth}
        }
    }
}

pub struct Engine {
    window: Window,
    instance: Arc<Instance>,
    physical_device: usize,
    device: Arc<Device>,
    swapchain: Arc<Swapchain>,
    images: Vec<Arc<SwapchainImage>>,
    depth_buffer: Arc<AttachmentImage<format::D16Unorm>>,
    render_pass: Arc<render_pass::CustomRenderPass>,
    framebuffers: Vec<Arc<Framebuffer<render_pass::CustomRenderPass>>>,
    submissions: Vec<Arc<Submission>>,
    queue: Arc<Queue>,
    config: Config,
    inputs: HashMap<String, f32>,
}

impl Engine {
    pub fn new(config: Config) -> Engine {

        let window_builder = create_window(&config.window);

        let instance = {
            let extensions = required_extensions();
            Instance::new(None, &extensions, None).expect("Failed to create Vulkan instance.")
        };

        let ins = &instance.clone();

        let physical = PhysicalDevice::enumerate(&ins)
            .next()
            .expect("No vulkan device is available.");

        let physical_device = physical.index();

        let window = window_builder.build_vk_surface(&instance).unwrap();

        let queue = physical
            .queue_families()
            .find(|q| q.supports_graphics() && window.surface().is_supported(q).unwrap_or(false))
            .expect("Couldn't find a graphical queue family.");

        // Logical Device, Queues
        let (device, mut queues) = {
            let device_ext = DeviceExtensions {
                khr_swapchain: true,
                ..DeviceExtensions::none()
            };

            Device::new(&physical,
                        physical.supported_features(),
                        &device_ext,
                        [(queue, 0.5)].iter().cloned())
                    .expect("failed to create device")
        };

        // Device Queue
        let queue = queues.next().unwrap();

        // Swapchain, Swapchain Images
        let (swapchain, images) =
            create_swapchain(&window, &physical, &device, &queue, None, &config);

        let depth_buffer =
            AttachmentImage::transient(&device, images[0].dimensions(), format::D16Unorm).unwrap();

        // Render Pass
        let render_pass =
            render_pass::CustomRenderPass::new(&device,
                                               &render_pass::Formats {
                                                    // Use the format of the images and one sample.
                                                    color: (images[0].format(), 1),
                                                    depth: (format::D16Unorm, 1),
                                                })
                    .unwrap();

        let framebuffers = images
            .iter()
            .map(|image| {
                let attachments = render_pass::AList {
                    color: &image,
                    depth: &depth_buffer,
                };

                Framebuffer::new(&render_pass,
                                 [image.dimensions()[0], image.dimensions()[1], 1],
                                 attachments)
                        .unwrap()
            })
            .collect::<Vec<_>>();

        // Queue Submissions
        let submissions = Vec::new();

        // Input System
        let mut inputs: HashMap<String, f32> = config
            .input
            .keys()
            .map(|k| (k.clone(), 0.0f32))
            .collect();

        Engine {
            window: window,
            instance,
            physical_device,
            device,
            swapchain,
            images,
            depth_buffer,
            framebuffers,
            render_pass,
            submissions,
            queue,
            config,
            inputs,
        }
    }

    /// Handles input/output events from the window and any input middleware.
    pub fn io(&mut self) -> bool {

        for ev in self.window.window().poll_events() {

            // Axis Map
            for (string_key, axis) in self.config.input.iter() {
                for axis_value in axis {

                    let out = events::string_to_wevent(&axis_value.key, &ev);

                    // Check axis_value.meta for additional checks.

                    // Write to axis map
                    match out {
                        Some(x) => *self.inputs.get_mut(string_key).unwrap() = x,
                        None => (),
                    };

                }
            }

            // Core Events
            match &ev {
                &Event::Resized(w, h) => {
                    self.config.window.resolution = [w, h];
                    let (swapchain, images) =
                        create_swapchain(&self.window,
                                         &PhysicalDevice::from_index(&self.instance,
                                                                     self.physical_device)
                                                  .unwrap(),
                                         &self.device,
                                         &self.queue,
                                         Some(&self.swapchain),
                                         &self.config);
                    self.swapchain = swapchain;
                    self.images = images;
                    self.depth_buffer = AttachmentImage::transient(&self.device,
                                                                   self.images[0].dimensions(),
                                                                   format::D16Unorm)
                            .unwrap();
                    self.framebuffers = self.images
                        .iter()
                        .map(|image| {
                            let attachments = render_pass::AList {
                                color: &image,
                                depth: &self.depth_buffer,
                            };

                            Framebuffer::new(&self.render_pass,
                                             [image.dimensions()[0], image.dimensions()[1], 1],
                                             attachments)
                                    .unwrap()
                        })
                        .collect::<Vec<_>>();
                }
                &Event::Closed => return false,
                _ => (),
            };
        }

        true
    }

    /// Recursively updates application tree.
    pub fn update(&self) {

        //@TODO recursively map each update function from each node.
        //node.children.map(update)

    }

    /// Updates the display surface with a new image.
    pub fn render(&mut self) {
        let command_buffers = self.framebuffers
            .iter()
            .map(|framebuffer| {
                PrimaryCommandBufferBuilder::new(&self.device, self.queue.family())
                    .draw_inline(&self.render_pass,
                                 &framebuffer,
                                 render_pass::ClearValues {
                                     color: [0.2, 0.4, 0.8, 1.0],
                                     depth: 1.0,
                                 })
                    .draw_end()
                    .build()
            })
            .collect::<Vec<_>>();
        let image_num = self.swapchain
            .acquire_next_image(Duration::new(1, 0))
            .unwrap();

        // @TODO build command buffers with threads and submit the changes in main thread (here)
        self.submissions
            .push(submit(&command_buffers[image_num], &self.queue).unwrap());

        self.swapchain.present(&self.queue, image_num).unwrap();
    }
}

/// Sets up and creates a swapchain
fn create_swapchain(window: &Window,
                    physical_device: &PhysicalDevice,
                    device: &Arc<Device>,
                    queue: &Arc<Queue>,
                    old: Option<&Arc<Swapchain>>,
                    config: &Config)
                    -> (Arc<Swapchain>, Vec<Arc<SwapchainImage>>) {
    {
        let caps = window
            .surface()
            .get_capabilities(&physical_device)
            .expect("failed to get surface capabilities");

        let dimensions = if config.window.resolution[0] <= 240 ||
                            config.window.resolution[1] <= 240 {

            let min = caps.min_image_extent;

            let extent = caps.current_extent.unwrap_or([800, 600]);

            if extent[0] < min[0] || extent[1] < min[1] {
                min
            }
            else {
                extent
            }
        } else {
            config.window.resolution
        };

        let present = if config.graphics.vsync &&
                         caps.present_modes.supports(PresentMode::Mailbox) {
            PresentMode::Mailbox
        } else {
            caps.present_modes.iter().next().unwrap()
        };

        let alpha = caps.supported_composite_alpha.iter().next().unwrap();

        let format = caps.supported_formats[0].0;

        Swapchain::new(&device,
                       &window.surface(),
                       caps.min_image_count,
                       format,
                       dimensions,
                       1,
                       &caps.supported_usage_flags,
                       queue,
                       SurfaceTransform::Identity,
                       alpha,
                       present,
                       true,
                       old)
                .expect("failed to create swapchain")
    }
}

/// Creates a window builder with a given window configuration.
fn create_window(config: &WindowConfig) -> WindowBuilder {

    let mut w = get_primary_monitor();
    let dimensions = w.get_dimensions();

    // Set resolution
    let resolution = if config.resolution[0] <= 240 || config.resolution[1] <= 240 {
        [dimensions.0, dimensions.1]
    } else {
        config.resolution.clone()
    };

    // Set fullscreen
    if config.fullscreen {
        for (i, monitor) in get_available_monitors().enumerate() {
            if i == config.display as usize {
                w = monitor;
            }
        }
    }

    // Create manager
    let window_manager = WindowBuilder::new()
        .with_title("CodeVR")
        .with_dimensions(resolution[0], resolution[1]);

    if config.fullscreen {
        return window_manager.with_fullscreen(w);
    }

    window_manager
}
<|endoftext|>