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

//! Liveness analysis which computes liveness of MIR local variables at the boundary of basic blocks
//!
//! This analysis considers references as being used only at the point of the
//! borrow. This means that this does not track uses because of references that
//! already exist:
//!
//! ```Rust
//!     fn foo() {
//!         x = 0;
//!         // `x` is live here
//!         GLOBAL = &x: *const u32;
//!         // but not here, even while it can be accessed through `GLOBAL`.
//!         foo();
//!         x = 1;
//!         // `x` is live again here, because it is assigned to `OTHER_GLOBAL`
//!         OTHER_GLOBAL = &x: *const u32;
//!         // ...
//!     }
//! ```
//!
//! This means that users of this analysis still have to check whether
//! pre-existing references can be used to access the value (e.g. at movable
//! generator yield points, all pre-existing references are invalidated, so this
//! doesn't matter).

use rustc::mir::*;
use rustc::mir::visit::{LvalueContext, Visitor};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::indexed_set::IdxSetBuf;
use util::pretty::{write_basic_block, dump_enabled, write_mir_intro};
use rustc::mir::transform::MirSource;
use rustc::ty::item_path;
use std::path::{PathBuf, Path};
use std::fs;
use rustc::ty::TyCtxt;
use std::io::{self, Write};

pub type LocalSet = IdxSetBuf<Local>;

#[derive(Eq, PartialEq, Clone)]
struct DefsUses {
    defs: LocalSet,
    uses: LocalSet,
}

impl DefsUses {
    fn apply(&self, bits: &mut LocalSet) -> bool {
        bits.subtract(&self.defs) | bits.union(&self.uses)
    }

    fn add_def(&mut self, index: Local) {
        // If it was used already in the block, remove that use
        // now that we found a definition.
        //
        // Example:
        //
        //     // Defs = {X}, Uses = {}
        //     X = 5
        //     // Defs = {}, Uses = {X}
        //     use(X)
        self.uses.remove(&index);
        self.defs.add(&index);
    }

    fn add_use(&mut self, index: Local) {
        // Inverse of above.
        //
        // Example:
        //
        //     // Defs = {}, Uses = {X}
        //     use(X)
        //     // Defs = {X}, Uses = {}
        //     X = 5
        //     // Defs = {}, Uses = {X}
        //     use(X)
        self.defs.remove(&index);
        self.uses.add(&index);
    }
}

impl<'tcx> Visitor<'tcx> for DefsUses {
    fn visit_local(&mut self,
                   &local: &Local,
                   context: LvalueContext<'tcx>,
                   _: Location) {
        match context {
            ///////////////////////////////////////////////////////////////////////////
            // DEFS

            LvalueContext::Store |

            // We let Call defined the result in both the success and
            // unwind cases. This is not really correct, however it
            // does not seem to be observable due to the way that we
            // generate MIR. See the test case
            // `mir-opt/nll/liveness-call-subtlety.rs`. To do things
            // properly, we would apply the def in call only to the
            // input from the success path and not the unwind
            // path. -nmatsakis
            LvalueContext::Call |

            // Storage live and storage dead aren't proper defines, but we can ignore
            // values that come before them.
            LvalueContext::StorageLive |
            LvalueContext::StorageDead => {
                self.add_def(local);
            }

            ///////////////////////////////////////////////////////////////////////////
            // USES

            LvalueContext::Projection(..) |

            // Borrows only consider their local used at the point of the borrow.
            // This won't affect the results since we use this analysis for generators
            // and we only care about the result at suspension points. Borrows cannot
            // cross suspension points so this behavior is unproblematic.
            LvalueContext::Borrow { .. } |

            LvalueContext::Inspect |
            LvalueContext::Consume |
            LvalueContext::Validate |

            // We consider drops to always be uses of locals.
            // Drop eloboration should be run before this analysis otherwise
            // the results might be too pessimistic.
            LvalueContext::Drop => {
                self.add_use(local);
            }
        }
    }
}

fn block<'tcx>(b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses {
    let mut visitor = DefsUses {
        defs: LocalSet::new_empty(locals),
        uses: LocalSet::new_empty(locals),
    };

    let dummy_location = Location { block: BasicBlock::new(0), statement_index: 0 };

    // Visit the various parts of the basic block in reverse. If we go
    // forward, the logic in `add_def` and `add_use` would be wrong.
    visitor.visit_terminator(BasicBlock::new(0), b.terminator(), dummy_location);
    for statement in b.statements.iter().rev() {
        visitor.visit_statement(BasicBlock::new(0), statement, dummy_location);
    }

    visitor
}

// This gives the result of the liveness analysis at the boundary of basic blocks
pub struct LivenessResult {
    pub ins: IndexVec<BasicBlock, LocalSet>,
    pub outs: IndexVec<BasicBlock, LocalSet>,
}

pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>) -> LivenessResult {
    let locals = mir.local_decls.len();
    let def_use: IndexVec<_, _> = mir.basic_blocks().iter().map(|b| {
        block(b, locals)
    }).collect();

    let copy = |from: &IndexVec<BasicBlock, LocalSet>, to: &mut IndexVec<BasicBlock, LocalSet>| {
        for (i, set) in to.iter_enumerated_mut() {
            set.clone_from(&from[i]);
        }
    };

    let mut ins: IndexVec<_, _> = mir.basic_blocks()
        .indices()
        .map(|_| LocalSet::new_empty(locals)).collect();
    let mut outs = ins.clone();

    let mut ins_ = ins.clone();
    let mut outs_ = outs.clone();

    loop {
        copy(&ins, &mut ins_);
        copy(&outs, &mut outs_);

        for b in mir.basic_blocks().indices().rev() {
            // out = ∪ {ins of successors}
            outs[b].clear();
            for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() {
                outs[b].union(&ins[successor]);
            }

            // in = use ∪ (out - def)
            ins[b].clone_from(&outs[b]);

            // FIXME use the return value to detect if we have changed things
            def_use[b].apply(&mut ins[b]);
        }

        if ins_ == ins && outs_ == outs {
            break;
        }
    }

    LivenessResult {
        ins,
        outs,
    }
}

impl LivenessResult {
    /// Walks backwards through the statements/terminator in the given
    /// basic block `block`.  At each point within `block`, invokes
    /// the callback `op` with the current location and the set of
    /// variables that are live on entry to that location.
    pub fn simulate_block<'tcx, OP>(&self,
                                    mir: &Mir<'tcx>,
                                    block: BasicBlock,
                                    mut callback: OP)
        where OP: FnMut(Location, &LocalSet)
    {
        let data = &mir[block];

        // Get a copy of the bits on exit from the block.
        let mut bits = self.outs[block].clone();

        // Start with the maximal statement index -- i.e., right before
        // the terminator executes.
        let mut statement_index = data.statements.len();

        // Compute liveness right before terminator and invoke callback.
        let terminator_location = Location { block, statement_index };
        let terminator_defs_uses = self.defs_uses(mir, terminator_location, &data.terminator);
        terminator_defs_uses.apply(&mut bits);
        callback(terminator_location, &bits);

        // Compute liveness before each statement (in rev order) and invoke callback.
        for statement in data.statements.iter().rev() {
            statement_index -= 1;
            let statement_location = Location { block, statement_index };
            let statement_defs_uses = self.defs_uses(mir, statement_location, statement);
            statement_defs_uses.apply(&mut bits);
            callback(statement_location, &bits);
        }

        assert_eq!(bits, self.ins[block]);
    }

    fn defs_uses<'tcx, V>(&self,
                          mir: &Mir<'tcx>,
                          location: Location,
                          thing: &V)
                          -> DefsUses
        where V: MirVisitable<'tcx>,
    {
        let locals = mir.local_decls.len();
        let mut visitor = DefsUses {
            defs: LocalSet::new_empty(locals),
            uses: LocalSet::new_empty(locals),
        };

        // Visit the various parts of the basic block in reverse. If we go
        // forward, the logic in `add_def` and `add_use` would be wrong.
        thing.apply(location, &mut visitor);

        visitor
    }
}

trait MirVisitable<'tcx> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>;
}

impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>
    {
        visitor.visit_statement(location.block,
                                self,
                                location)
    }
}

impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>
    {
        visitor.visit_terminator(location.block,
                                 self.as_ref().unwrap(),
                                 location)
    }
}

pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          pass_name: &str,
                          source: MirSource,
                          mir: &Mir<'tcx>,
                          result: &LivenessResult) {
    if !dump_enabled(tcx, pass_name, source) {
        return;
    }
    let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below
        tcx.item_path_str(tcx.hir.local_def_id(source.item_id()))
    });
    dump_matched_mir_node(tcx, pass_name, &node_path,
                          source, mir, result);
}

fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   pass_name: &str,
                                   node_path: &str,
                                   source: MirSource,
                                   mir: &Mir<'tcx>,
                                   result: &LivenessResult) {
    let mut file_path = PathBuf::new();
    if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
        let p = Path::new(file_dir);
        file_path.push(p);
    };
    let file_name = format!("rustc.node{}{}-liveness.mir",
                            source.item_id(), pass_name);
    file_path.push(&file_name);
    let _ = fs::File::create(&file_path).and_then(|mut file| {
        writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?;
        writeln!(file, "// source = {:?}", source)?;
        writeln!(file, "// pass_name = {}", pass_name)?;
        writeln!(file, "")?;
        write_mir_fn(tcx, source, mir, &mut file, result)?;
        Ok(())
    });
}

pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              src: MirSource,
                              mir: &Mir<'tcx>,
                              w: &mut Write,
                              result: &LivenessResult)
                              -> io::Result<()> {
    write_mir_intro(tcx, src, mir, w)?;
    for block in mir.basic_blocks().indices() {
        let print = |w: &mut Write, prefix, result: &IndexVec<BasicBlock, LocalSet>| {
            let live: Vec<String> = mir.local_decls.indices()
                .filter(|i| result[block].contains(i))
                .map(|i| format!("{:?}", i))
                .collect();
            writeln!(w, "{} {{{}}}", prefix, live.join(", "))
        };
        print(w, "   ", &result.ins)?;
        write_basic_block(tcx, block, mir, &mut |_, _| Ok(()), w)?;
        print(w, "   ", &result.outs)?;
        if block.index() + 1 != mir.basic_blocks().len() {
            writeln!(w, "")?;
        }
    }

    writeln!(w, "}}")?;
    Ok(())
}

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

//! Liveness analysis which computes liveness of MIR local variables at the boundary of basic blocks
//!
//! This analysis considers references as being used only at the point of the
//! borrow. This means that this does not track uses because of references that
//! already exist:
//!
//! ```Rust
//!     fn foo() {
//!         x = 0;
//!         // `x` is live here
//!         GLOBAL = &x: *const u32;
//!         // but not here, even while it can be accessed through `GLOBAL`.
//!         foo();
//!         x = 1;
//!         // `x` is live again here, because it is assigned to `OTHER_GLOBAL`
//!         OTHER_GLOBAL = &x: *const u32;
//!         // ...
//!     }
//! ```
//!
//! This means that users of this analysis still have to check whether
//! pre-existing references can be used to access the value (e.g. at movable
//! generator yield points, all pre-existing references are invalidated, so this
//! doesn't matter).

use rustc::mir::*;
use rustc::mir::visit::{LvalueContext, Visitor};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::indexed_set::IdxSetBuf;
use util::pretty::{write_basic_block, dump_enabled, write_mir_intro};
use rustc::mir::transform::MirSource;
use rustc::ty::item_path;
use std::path::{PathBuf, Path};
use std::fs;
use rustc::ty::TyCtxt;
use std::io::{self, Write};

pub type LocalSet = IdxSetBuf<Local>;

#[derive(Eq, PartialEq, Clone)]
struct DefsUses {
    defs: LocalSet,
    uses: LocalSet,
}

impl DefsUses {
    fn apply(&self, bits: &mut LocalSet) -> bool {
        bits.subtract(&self.defs) | bits.union(&self.uses)
    }

    fn add_def(&mut self, index: Local) {
        // If it was used already in the block, remove that use
        // now that we found a definition.
        //
        // Example:
        //
        //     // Defs = {X}, Uses = {}
        //     X = 5
        //     // Defs = {}, Uses = {X}
        //     use(X)
        self.uses.remove(&index);
        self.defs.add(&index);
    }

    fn add_use(&mut self, index: Local) {
        // Inverse of above.
        //
        // Example:
        //
        //     // Defs = {}, Uses = {X}
        //     use(X)
        //     // Defs = {X}, Uses = {}
        //     X = 5
        //     // Defs = {}, Uses = {X}
        //     use(X)
        self.defs.remove(&index);
        self.uses.add(&index);
    }
}

impl<'tcx> Visitor<'tcx> for DefsUses {
    fn visit_local(&mut self,
                   &local: &Local,
                   context: LvalueContext<'tcx>,
                   _: Location) {
        match context {
            ///////////////////////////////////////////////////////////////////////////
            // DEFS

            LvalueContext::Store |

            // We let Call defined the result in both the success and
            // unwind cases. This is not really correct, however it
            // does not seem to be observable due to the way that we
            // generate MIR. See the test case
            // `mir-opt/nll/liveness-call-subtlety.rs`. To do things
            // properly, we would apply the def in call only to the
            // input from the success path and not the unwind
            // path. -nmatsakis
            LvalueContext::Call |

            // Storage live and storage dead aren't proper defines, but we can ignore
            // values that come before them.
            LvalueContext::StorageLive |
            LvalueContext::StorageDead => {
                self.add_def(local);
            }

            ///////////////////////////////////////////////////////////////////////////
            // USES

            LvalueContext::Projection(..) |

            // Borrows only consider their local used at the point of the borrow.
            // This won't affect the results since we use this analysis for generators
            // and we only care about the result at suspension points. Borrows cannot
            // cross suspension points so this behavior is unproblematic.
            LvalueContext::Borrow { .. } |

            LvalueContext::Inspect |
            LvalueContext::Consume |
            LvalueContext::Validate |

            // We consider drops to always be uses of locals.
            // Drop eloboration should be run before this analysis otherwise
            // the results might be too pessimistic.
            LvalueContext::Drop => {
                self.add_use(local);
            }
        }
    }
}

fn block<'tcx>(b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses {
    let mut visitor = DefsUses {
        defs: LocalSet::new_empty(locals),
        uses: LocalSet::new_empty(locals),
    };

    let dummy_location = Location { block: BasicBlock::new(0), statement_index: 0 };

    // Visit the various parts of the basic block in reverse. If we go
    // forward, the logic in `add_def` and `add_use` would be wrong.
    visitor.visit_terminator(BasicBlock::new(0), b.terminator(), dummy_location);
    for statement in b.statements.iter().rev() {
        visitor.visit_statement(BasicBlock::new(0), statement, dummy_location);
    }

    visitor
}

// This gives the result of the liveness analysis at the boundary of basic blocks
pub struct LivenessResult {
    pub ins: IndexVec<BasicBlock, LocalSet>,
    pub outs: IndexVec<BasicBlock, LocalSet>,
}

pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>) -> LivenessResult {
    let locals = mir.local_decls.len();
    let def_use: IndexVec<_, _> = mir.basic_blocks().iter().map(|b| {
        block(b, locals)
    }).collect();

    let mut ins: IndexVec<_, _> = mir.basic_blocks()
        .indices()
        .map(|_| LocalSet::new_empty(locals))
        .collect();
    let mut outs = ins.clone();

    let mut changed = true;
    let mut bits = LocalSet::new_empty(locals);
    while changed {
        changed = false;

        for b in mir.basic_blocks().indices().rev() {
            // outs[b] = ∪ {ins of successors}
            bits.clear();
            for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() {
                bits.union(&ins[successor]);
            }
            outs[b].clone_from(&bits);

            // bits = use ∪ (bits - def)
            def_use[b].apply(&mut bits);

            // update bits on entry and flag if they have changed
            if ins[b] != bits {
                ins[b].clone_from(&bits);
                changed = true;
            }
        }
    }

    LivenessResult {
        ins,
        outs,
    }
}

impl LivenessResult {
    /// Walks backwards through the statements/terminator in the given
    /// basic block `block`.  At each point within `block`, invokes
    /// the callback `op` with the current location and the set of
    /// variables that are live on entry to that location.
    pub fn simulate_block<'tcx, OP>(&self,
                                    mir: &Mir<'tcx>,
                                    block: BasicBlock,
                                    mut callback: OP)
        where OP: FnMut(Location, &LocalSet)
    {
        let data = &mir[block];

        // Get a copy of the bits on exit from the block.
        let mut bits = self.outs[block].clone();

        // Start with the maximal statement index -- i.e., right before
        // the terminator executes.
        let mut statement_index = data.statements.len();

        // Compute liveness right before terminator and invoke callback.
        let terminator_location = Location { block, statement_index };
        let terminator_defs_uses = self.defs_uses(mir, terminator_location, &data.terminator);
        terminator_defs_uses.apply(&mut bits);
        callback(terminator_location, &bits);

        // Compute liveness before each statement (in rev order) and invoke callback.
        for statement in data.statements.iter().rev() {
            statement_index -= 1;
            let statement_location = Location { block, statement_index };
            let statement_defs_uses = self.defs_uses(mir, statement_location, statement);
            statement_defs_uses.apply(&mut bits);
            callback(statement_location, &bits);
        }

        assert_eq!(bits, self.ins[block]);
    }

    fn defs_uses<'tcx, V>(&self,
                          mir: &Mir<'tcx>,
                          location: Location,
                          thing: &V)
                          -> DefsUses
        where V: MirVisitable<'tcx>,
    {
        let locals = mir.local_decls.len();
        let mut visitor = DefsUses {
            defs: LocalSet::new_empty(locals),
            uses: LocalSet::new_empty(locals),
        };

        // Visit the various parts of the basic block in reverse. If we go
        // forward, the logic in `add_def` and `add_use` would be wrong.
        thing.apply(location, &mut visitor);

        visitor
    }
}

trait MirVisitable<'tcx> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>;
}

impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>
    {
        visitor.visit_statement(location.block,
                                self,
                                location)
    }
}

impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
    fn apply<V>(&self, location: Location, visitor: &mut V)
        where V: Visitor<'tcx>
    {
        visitor.visit_terminator(location.block,
                                 self.as_ref().unwrap(),
                                 location)
    }
}

pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          pass_name: &str,
                          source: MirSource,
                          mir: &Mir<'tcx>,
                          result: &LivenessResult) {
    if !dump_enabled(tcx, pass_name, source) {
        return;
    }
    let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below
        tcx.item_path_str(tcx.hir.local_def_id(source.item_id()))
    });
    dump_matched_mir_node(tcx, pass_name, &node_path,
                          source, mir, result);
}

fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   pass_name: &str,
                                   node_path: &str,
                                   source: MirSource,
                                   mir: &Mir<'tcx>,
                                   result: &LivenessResult) {
    let mut file_path = PathBuf::new();
    if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
        let p = Path::new(file_dir);
        file_path.push(p);
    };
    let file_name = format!("rustc.node{}{}-liveness.mir",
                            source.item_id(), pass_name);
    file_path.push(&file_name);
    let _ = fs::File::create(&file_path).and_then(|mut file| {
        writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?;
        writeln!(file, "// source = {:?}", source)?;
        writeln!(file, "// pass_name = {}", pass_name)?;
        writeln!(file, "")?;
        write_mir_fn(tcx, source, mir, &mut file, result)?;
        Ok(())
    });
}

pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              src: MirSource,
                              mir: &Mir<'tcx>,
                              w: &mut Write,
                              result: &LivenessResult)
                              -> io::Result<()> {
    write_mir_intro(tcx, src, mir, w)?;
    for block in mir.basic_blocks().indices() {
        let print = |w: &mut Write, prefix, result: &IndexVec<BasicBlock, LocalSet>| {
            let live: Vec<String> = mir.local_decls.indices()
                .filter(|i| result[block].contains(i))
                .map(|i| format!("{:?}", i))
                .collect();
            writeln!(w, "{} {{{}}}", prefix, live.join(", "))
        };
        print(w, "   ", &result.ins)?;
        write_basic_block(tcx, block, mir, &mut |_, _| Ok(()), w)?;
        print(w, "   ", &result.outs)?;
        if block.index() + 1 != mir.basic_blocks().len() {
            writeln!(w, "")?;
        }
    }

    writeln!(w, "}}")?;
    Ok(())
}

<|endoftext|>


<commit_before><commit_msg>Implement obj group reg's<commit_after><|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use text::glyph::CharIndex;

#[deriving(PartialEq)]
pub enum CompressionMode {
    CompressNone,
    CompressWhitespace,
    CompressWhitespaceNewline,
    DiscardNewline
}

// ported from Gecko's nsTextFrameUtils::TransformText.
//
// High level TODOs:
//
// * Issue #113: consider incoming text state (arabic, etc)
//               and propagate outgoing text state (dual of above)
//
// * Issue #114: record skipped and kept chars for mapping original to new text
//
// * Untracked: various edge cases for bidi, CJK, etc.
pub fn transform_text(text: &str,
                      mode: CompressionMode,
                      incoming_whitespace: bool,
                      output_text: &mut String,
                      new_line_pos: &mut Vec<CharIndex>)
                      -> bool {
    let out_whitespace = match mode {
        CompressionMode::CompressNone | CompressionMode::DiscardNewline => {
            let mut new_line_index = CharIndex(0);
            for ch in text.chars() {
                if is_discardable_char(ch, mode) {
                    // TODO: record skipped char
                } else {
                    // TODO: record kept char
                    if ch == '\t' {
                        // TODO: set "has tab" flag
                    } else if ch == '\n' {
                        // Save new-line's position for line-break
                        // This value is relative(not absolute)
                        new_line_pos.push(new_line_index);
                        new_line_index = CharIndex(0);
                    }

                    if ch != '\n' {
                        new_line_index = new_line_index + CharIndex(1);
                    }
                    output_text.push(ch);
                }
            }
            text.len() > 0 && is_in_whitespace(text.char_at_reverse(0), mode)
        },

        CompressionMode::CompressWhitespace | CompressionMode::CompressWhitespaceNewline => {
            let mut in_whitespace: bool = incoming_whitespace;
            for ch in text.chars() {
                // TODO: discard newlines between CJK chars
                let mut next_in_whitespace: bool = is_in_whitespace(ch, mode);

                if !next_in_whitespace {
                    if is_always_discardable_char(ch) {
                        // revert whitespace setting, since this char was discarded
                        next_in_whitespace = in_whitespace;
                        // TODO: record skipped char
                    } else {
                        // TODO: record kept char
                        output_text.push(ch);
                    }
                } else { /* next_in_whitespace; possibly add a space char */
                    if in_whitespace {
                        // TODO: record skipped char
                    } else {
                        // TODO: record kept char
                        output_text.push(' ');
                    }
                }
                // save whitespace context for next char
                in_whitespace = next_in_whitespace;
            } /* /for str::each_char */
            in_whitespace
        }
    };

    return out_whitespace;

    fn is_in_whitespace(ch: char, mode: CompressionMode) -> bool {
        match (ch, mode) {
            (' ', _)  => true,
            ('\t', _) => true,
            ('\n', CompressionMode::CompressWhitespaceNewline) => true,
            (_, _)    => false
        }
    }

    fn is_discardable_char(ch: char, mode: CompressionMode) -> bool {
        if is_always_discardable_char(ch) {
            return true;
        }
        match mode {
            CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => ch == '\n',
            _ => false
        }
    }

    fn is_always_discardable_char(_ch: char) -> bool {
        // TODO: check for bidi control chars, soft hyphens.
        false
    }
}

pub fn float_to_fixed(before: int, f: f64) -> i32 {
    ((1i32 << before as uint) as f64 * f) as i32
}

pub fn fixed_to_float(before: int, f: i32) -> f64 {
    f as f64 * 1.0f64 / ((1i32 << before as uint) as f64)
}

pub fn fixed_to_rounded_int(before: int, f: i32) -> int {
    let half = 1i32 << (before-1) as uint;
    if f > 0i32 {
        ((half + f) >> before as uint) as int
    } else {
       -((half - f) >> before as uint) as int
    }
}

/* Generate a 32-bit TrueType tag from its 4 characters */
pub fn true_type_tag(a: char, b: char, c: char, d: char) -> u32 {
    let a = a as u32;
    let b = b as u32;
    let c = c as u32;
    let d = d as u32;
    (a << 24 | b << 16 | c << 8 | d) as u32
}

#[test]
fn test_true_type_tag() {
    assert_eq!(true_type_tag('c', 'm', 'a', 'p'), 0x_63_6D_61_70_u32);
}

#[test]
fn test_transform_compress_none() {
    let test_strs = [
        "  foo bar",
        "foo bar  ",
        "foo\n bar",
        "foo \nbar",
        "  foo  bar  \nbaz",
        "foo bar baz",
        "foobarbaz\n\n",
    ];

    let mode = CompressionMode::CompressNone;
    for &test in test_strs.iter() {
        let mut new_line_pos = vec![];
        let mut trimmed_str = String::new();
        transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
        assert_eq!(trimmed_str.as_slice(), test)
    }
}

#[test]
fn test_transform_discard_newline() {
    let test_strs = [
        ("  foo bar",         "  foo bar"),
        ("foo bar  ",         "foo bar  "),
        ("foo\n bar",         "foo bar"),
        ("foo \nbar",         "foo bar"),
        ("  foo  bar  \nbaz", "  foo  bar  baz"),
        ("foo bar baz",       "foo bar baz"),
        ("foobarbaz\n\n",     "foobarbaz"),
    ];

    let mode = CompressionMode::DiscardNewline;
    for &(test, oracle) in test_strs.iter() {
        let mut new_line_pos = vec![];
        let mut trimmed_str = String::new();
        transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
        assert_eq!(trimmed_str.as_slice(), oracle)
    }
}

#[test]
fn test_transform_compress_whitespace() {
    let test_strs = [
        ("  foo bar",          "foo bar"),
        ("foo bar  ",          "foo bar "),
        ("foo\n bar",          "foo\n bar"),
        ("foo \nbar",          "foo \nbar"),
        ("  foo  bar  \nbaz",  "foo bar \nbaz"),
        ("foo bar baz",        "foo bar baz"),
        ("foobarbaz\n\n",      "foobarbaz\n\n"),
    ];

    let mode = CompressionMode::CompressWhitespace;
    for &(test, oracle) in test_strs.iter() {
        let mut new_line_pos = vec![];
        let mut trimmed_str = String::new();
        transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
        assert_eq!(&*trimmed_str, oracle)
    }
}

#[test]
fn test_transform_compress_whitespace_newline() {
    let test_strs = vec![
        ("  foo bar",         "foo bar"),
        ("foo bar  ",         "foo bar "),
        ("foo\n bar",         "foo bar"),
        ("foo \nbar",         "foo bar"),
        ("  foo  bar  \nbaz", "foo bar baz"),
        ("foo bar baz",       "foo bar baz"),
        ("foobarbaz\n\n",     "foobarbaz "),
    ];

    let mode = CompressionMode::CompressWhitespaceNewline;
    for &(test, oracle) in test_strs.iter() {
        let mut new_line_pos = vec![];
        let mut trimmed_str = String::new();
        transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
        assert_eq!(&*trimmed_str, oracle)
    }
}

#[test]
fn test_transform_compress_whitespace_newline_no_incoming() {
    let test_strs = [
        ("  foo bar",         " foo bar"),
        ("\nfoo bar",         " foo bar"),
        ("foo bar  ",         "foo bar "),
        ("foo\n bar",         "foo bar"),
        ("foo \nbar",         "foo bar"),
        ("  foo  bar  \nbaz", " foo bar baz"),
        ("foo bar baz",       "foo bar baz"),
        ("foobarbaz\n\n",     "foobarbaz "),
    ];

    let mode = CompressionMode::CompressWhitespaceNewline;
    for &(test, oracle) in test_strs.iter() {
        let mut new_line_pos = vec![];
        let mut trimmed_str = String::new();
        transform_text(test, mode, false, &mut trimmed_str, &mut new_line_pos);
        assert_eq!(trimmed_str.as_slice(), oracle)
    }
}
<commit_msg>Reformat the transform_text tests.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use text::glyph::CharIndex;

#[deriving(PartialEq)]
pub enum CompressionMode {
    CompressNone,
    CompressWhitespace,
    CompressWhitespaceNewline,
    DiscardNewline
}

// ported from Gecko's nsTextFrameUtils::TransformText.
//
// High level TODOs:
//
// * Issue #113: consider incoming text state (arabic, etc)
//               and propagate outgoing text state (dual of above)
//
// * Issue #114: record skipped and kept chars for mapping original to new text
//
// * Untracked: various edge cases for bidi, CJK, etc.
pub fn transform_text(text: &str,
                      mode: CompressionMode,
                      incoming_whitespace: bool,
                      output_text: &mut String,
                      new_line_pos: &mut Vec<CharIndex>)
                      -> bool {
    let out_whitespace = match mode {
        CompressionMode::CompressNone | CompressionMode::DiscardNewline => {
            let mut new_line_index = CharIndex(0);
            for ch in text.chars() {
                if is_discardable_char(ch, mode) {
                    // TODO: record skipped char
                } else {
                    // TODO: record kept char
                    if ch == '\t' {
                        // TODO: set "has tab" flag
                    } else if ch == '\n' {
                        // Save new-line's position for line-break
                        // This value is relative(not absolute)
                        new_line_pos.push(new_line_index);
                        new_line_index = CharIndex(0);
                    }

                    if ch != '\n' {
                        new_line_index = new_line_index + CharIndex(1);
                    }
                    output_text.push(ch);
                }
            }
            text.len() > 0 && is_in_whitespace(text.char_at_reverse(0), mode)
        },

        CompressionMode::CompressWhitespace | CompressionMode::CompressWhitespaceNewline => {
            let mut in_whitespace: bool = incoming_whitespace;
            for ch in text.chars() {
                // TODO: discard newlines between CJK chars
                let mut next_in_whitespace: bool = is_in_whitespace(ch, mode);

                if !next_in_whitespace {
                    if is_always_discardable_char(ch) {
                        // revert whitespace setting, since this char was discarded
                        next_in_whitespace = in_whitespace;
                        // TODO: record skipped char
                    } else {
                        // TODO: record kept char
                        output_text.push(ch);
                    }
                } else { /* next_in_whitespace; possibly add a space char */
                    if in_whitespace {
                        // TODO: record skipped char
                    } else {
                        // TODO: record kept char
                        output_text.push(' ');
                    }
                }
                // save whitespace context for next char
                in_whitespace = next_in_whitespace;
            } /* /for str::each_char */
            in_whitespace
        }
    };

    return out_whitespace;

    fn is_in_whitespace(ch: char, mode: CompressionMode) -> bool {
        match (ch, mode) {
            (' ', _)  => true,
            ('\t', _) => true,
            ('\n', CompressionMode::CompressWhitespaceNewline) => true,
            (_, _)    => false
        }
    }

    fn is_discardable_char(ch: char, mode: CompressionMode) -> bool {
        if is_always_discardable_char(ch) {
            return true;
        }
        match mode {
            CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => ch == '\n',
            _ => false
        }
    }

    fn is_always_discardable_char(_ch: char) -> bool {
        // TODO: check for bidi control chars, soft hyphens.
        false
    }
}

pub fn float_to_fixed(before: int, f: f64) -> i32 {
    ((1i32 << before as uint) as f64 * f) as i32
}

pub fn fixed_to_float(before: int, f: i32) -> f64 {
    f as f64 * 1.0f64 / ((1i32 << before as uint) as f64)
}

pub fn fixed_to_rounded_int(before: int, f: i32) -> int {
    let half = 1i32 << (before-1) as uint;
    if f > 0i32 {
        ((half + f) >> before as uint) as int
    } else {
       -((half - f) >> before as uint) as int
    }
}

/* Generate a 32-bit TrueType tag from its 4 characters */
pub fn true_type_tag(a: char, b: char, c: char, d: char) -> u32 {
    let a = a as u32;
    let b = b as u32;
    let c = c as u32;
    let d = d as u32;
    (a << 24 | b << 16 | c << 8 | d) as u32
}

#[test]
fn test_true_type_tag() {
    assert_eq!(true_type_tag('c', 'm', 'a', 'p'), 0x_63_6D_61_70_u32);
}

#[test]
fn test_transform_compress_none() {
    let test_strs = [
        "  foo bar",
        "foo bar  ",
        "foo\n bar",
        "foo \nbar",
        "  foo  bar  \nbaz",
        "foo bar baz",
        "foobarbaz\n\n",
    ];

    let mode = CompressionMode::CompressNone;
    for &test in test_strs.iter() {
        let mut new_line_pos = vec![];
        let mut trimmed_str = String::new();
        transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
        assert_eq!(trimmed_str.as_slice(), test)
    }
}

#[test]
fn test_transform_discard_newline() {
    let test_strs = [
        ("  foo bar",
         "  foo bar"),

        ("foo bar  ",
         "foo bar  "),

        ("foo\n bar",
         "foo bar"),

        ("foo \nbar",
         "foo bar"),

        ("  foo  bar  \nbaz",
         "  foo  bar  baz"),

        ("foo bar baz",
         "foo bar baz"),

        ("foobarbaz\n\n",
         "foobarbaz"),
    ];

    let mode = CompressionMode::DiscardNewline;
    for &(test, oracle) in test_strs.iter() {
        let mut new_line_pos = vec![];
        let mut trimmed_str = String::new();
        transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
        assert_eq!(trimmed_str.as_slice(), oracle)
    }
}

#[test]
fn test_transform_compress_whitespace() {
    let test_strs = [
        ("  foo bar",
         "foo bar"),

        ("foo bar  ",
         "foo bar "),

        ("foo\n bar",
         "foo\n bar"),

        ("foo \nbar",
         "foo \nbar"),

        ("  foo  bar  \nbaz",
         "foo bar \nbaz"),

        ("foo bar baz",
         "foo bar baz"),

        ("foobarbaz\n\n",
         "foobarbaz\n\n"),
    ];

    let mode = CompressionMode::CompressWhitespace;
    for &(test, oracle) in test_strs.iter() {
        let mut new_line_pos = vec![];
        let mut trimmed_str = String::new();
        transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
        assert_eq!(&*trimmed_str, oracle)
    }
}

#[test]
fn test_transform_compress_whitespace_newline() {
    let test_strs = vec![
        ("  foo bar",
         "foo bar"),

        ("foo bar  ",
         "foo bar "),

        ("foo\n bar",
         "foo bar"),

        ("foo \nbar",
         "foo bar"),

        ("  foo  bar  \nbaz",
         "foo bar baz"),

        ("foo bar baz",
         "foo bar baz"),

        ("foobarbaz\n\n",
         "foobarbaz "),
    ];

    let mode = CompressionMode::CompressWhitespaceNewline;
    for &(test, oracle) in test_strs.iter() {
        let mut new_line_pos = vec![];
        let mut trimmed_str = String::new();
        transform_text(test, mode, true, &mut trimmed_str, &mut new_line_pos);
        assert_eq!(&*trimmed_str, oracle)
    }
}

#[test]
fn test_transform_compress_whitespace_newline_no_incoming() {
    let test_strs = [
        ("  foo bar",
         " foo bar"),

        ("\nfoo bar",
         " foo bar"),

        ("foo bar  ",
         "foo bar "),

        ("foo\n bar",
         "foo bar"),

        ("foo \nbar",
         "foo bar"),

        ("  foo  bar  \nbaz",
         " foo bar baz"),

        ("foo bar baz",
         "foo bar baz"),

        ("foobarbaz\n\n",
         "foobarbaz "),
    ];

    let mode = CompressionMode::CompressWhitespaceNewline;
    for &(test, oracle) in test_strs.iter() {
        let mut new_line_pos = vec![];
        let mut trimmed_str = String::new();
        transform_text(test, mode, false, &mut trimmed_str, &mut new_line_pos);
        assert_eq!(trimmed_str.as_slice(), oracle)
    }
}
<|endoftext|>


<commit_before><commit_msg>clean up util<commit_after><|endoftext|>


<commit_before><commit_msg>turn several chacha functions into  macros<commit_after><|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::MessageEventBinding;
use dom::bindings::codegen::InheritTypes::{EventCast, MessageEventDerived};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, EventMethods, MessageEventTypeId};

use servo_util::str::DOMString;

use js::jsapi::JSContext;
use js::jsval::JSVal;

#[deriving(Encodable)]
pub struct MessageEvent {
    event: Event,
    data: Traceable<JSVal>,
    origin: DOMString,
    lastEventId: DOMString,
}

impl MessageEventDerived for Event {
    fn is_messageevent(&self) -> bool {
        self.type_id == MessageEventTypeId
    }
}

impl MessageEvent {
    pub fn new_inherited(data: JSVal, origin: DOMString, lastEventId: DOMString)
                         -> MessageEvent {
        MessageEvent {
            event: Event::new_inherited(MessageEventTypeId),
            data: Traceable::new(data),
            origin: origin,
            lastEventId: lastEventId,
        }
    }

    pub fn new(global: &GlobalRef, type_: DOMString,
               bubbles: bool, cancelable: bool,
               data: JSVal, origin: DOMString, lastEventId: DOMString)
               -> Temporary<MessageEvent> {
        let ev = reflect_dom_object(box MessageEvent::new_inherited(data, origin, lastEventId),
                                    global,
                                    MessageEventBinding::Wrap).root();
        let event: &JSRef<Event> = EventCast::from_ref(&*ev);
        event.InitEvent(type_, bubbles, cancelable);
        Temporary::from_rooted(&*ev)
    }

    pub fn Constructor(global: &GlobalRef,
                       type_: DOMString,
                       init: &MessageEventBinding::MessageEventInit)
                       -> Fallible<Temporary<MessageEvent>> {
        let ev = MessageEvent::new(global, type_, init.parent.bubbles, init.parent.cancelable,
                                   init.data, init.origin.clone(), init.lastEventId.clone());
        Ok(ev)
    }
}

pub trait MessageEventMethods {
    fn Data(&self, cx: *mut JSContext) -> JSVal;
    fn Origin(&self) -> DOMString;
    fn LastEventId(&self) -> DOMString;
}

impl<'a> MessageEventMethods for JSRef<'a, MessageEvent> {
    fn Data(&self, _cx: *mut JSContext) -> JSVal {
        *self.data
    }

    fn Origin(&self) -> DOMString {
        self.origin.clone()
    }

    fn LastEventId(&self) -> DOMString {
        self.lastEventId.clone()
    }
}

impl Reflectable for MessageEvent {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.event.reflector()
    }
}
<commit_msg>Implement MessageEvent::dispatch.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::MessageEventBinding;
use dom::bindings::codegen::InheritTypes::{EventCast, MessageEventDerived};
use dom::bindings::conversions::ToJSValConvertible;
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, EventMethods, MessageEventTypeId};
use dom::eventtarget::{EventTarget, EventTargetHelpers};

use servo_util::str::DOMString;

use js::jsapi::JSContext;
use js::jsval::JSVal;

#[deriving(Encodable)]
pub struct MessageEvent {
    event: Event,
    data: Traceable<JSVal>,
    origin: DOMString,
    lastEventId: DOMString,
}

impl MessageEventDerived for Event {
    fn is_messageevent(&self) -> bool {
        self.type_id == MessageEventTypeId
    }
}

impl MessageEvent {
    pub fn new_inherited(data: JSVal, origin: DOMString, lastEventId: DOMString)
                         -> MessageEvent {
        MessageEvent {
            event: Event::new_inherited(MessageEventTypeId),
            data: Traceable::new(data),
            origin: origin,
            lastEventId: lastEventId,
        }
    }

    pub fn new(global: &GlobalRef, type_: DOMString,
               bubbles: bool, cancelable: bool,
               data: JSVal, origin: DOMString, lastEventId: DOMString)
               -> Temporary<MessageEvent> {
        let ev = reflect_dom_object(box MessageEvent::new_inherited(data, origin, lastEventId),
                                    global,
                                    MessageEventBinding::Wrap).root();
        let event: &JSRef<Event> = EventCast::from_ref(&*ev);
        event.InitEvent(type_, bubbles, cancelable);
        Temporary::from_rooted(&*ev)
    }

    pub fn Constructor(global: &GlobalRef,
                       type_: DOMString,
                       init: &MessageEventBinding::MessageEventInit)
                       -> Fallible<Temporary<MessageEvent>> {
        let ev = MessageEvent::new(global, type_, init.parent.bubbles, init.parent.cancelable,
                                   init.data, init.origin.clone(), init.lastEventId.clone());
        Ok(ev)
    }
}

impl MessageEvent {
    pub fn dispatch(target: &JSRef<EventTarget>,
                    scope: &GlobalRef,
                    message: DOMString) {
        let messageevent = MessageEvent::new(
            scope, "message".to_string(), false, false,
            message.to_jsval(scope.get_cx()),
            "".to_string(), "".to_string()).root();
        let event: &JSRef<Event> = EventCast::from_ref(&*messageevent);
        target.dispatch_event_with_target(None, &*event).unwrap();
    }
}

pub trait MessageEventMethods {
    fn Data(&self, cx: *mut JSContext) -> JSVal;
    fn Origin(&self) -> DOMString;
    fn LastEventId(&self) -> DOMString;
}

impl<'a> MessageEventMethods for JSRef<'a, MessageEvent> {
    fn Data(&self, _cx: *mut JSContext) -> JSVal {
        *self.data
    }

    fn Origin(&self) -> DOMString {
        self.origin.clone()
    }

    fn LastEventId(&self) -> DOMString {
        self.lastEventId.clone()
    }
}

impl Reflectable for MessageEvent {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.event.reflector()
    }
}
<|endoftext|>


<commit_before><commit_msg>Auto merge of #782 - RalfJung:generator, r=RalfJung<commit_after>#![feature(generators, generator_trait)]

use std::{
    ops::{Generator, GeneratorState},
    pin::Pin,
};

fn firstn() -> impl Generator<Yield = u64, Return = ()> {
    static move || {
        let mut num = 0;
        let num = &mut num;

        yield *num;
        *num += 1; //~ ERROR dangling pointer was dereferenced
    }
}

struct GeneratorIteratorAdapter<G>(G);

impl<G> Iterator for GeneratorIteratorAdapter<G>
where
    G: Generator<Return = ()>,
{
    type Item = G::Yield;

    fn next(&mut self) -> Option<Self::Item> {
        let me = unsafe { Pin::new_unchecked(&mut self.0) };
        match me.resume() {
            GeneratorState::Yielded(x) => Some(x),
            GeneratorState::Complete(_) => None,
        }
    }
}

fn main() {
    let mut generator_iterator_2 = {
        let mut generator_iterator = GeneratorIteratorAdapter(firstn());
        generator_iterator.next(); // pin it

        generator_iterator // move it
    }; // *deallocate* generator_iterator

    generator_iterator_2.next(); // and use moved value
}
<|endoftext|>


<commit_before><commit_msg>Added test for reference fields in structs<commit_after><|endoftext|>


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

// This test case tests the incremental compilation hash (ICH) implementation
// for inline asm.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph

#![allow(warnings)]
#![feature(rustc_attrs)]
#![feature(asm)]
#![crate_type="rlib"]

// Change template -------------------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_template(a: i32) -> i32 {
    let c: i32;
    unsafe {
        asm!("add 1, $0"
             : "=r"(c)
             : "0"(a)
             :
             :
             );
    }
    c
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_template(a: i32) -> i32 {
    let c: i32;
    unsafe {
        asm!("add 2, $0"
             : "=r"(c)
             : "0"(a)
             :
             :
             );
    }
    c
}

// Change output -------------------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_output(a: i32) -> i32 {
    let mut _out1: i32 = 0;
    let mut _out2: i32 = 0;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out1)
             : "0"(a)
             :
             :
             );
    }
    _out1
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_output(a: i32) -> i32 {
    let mut _out1: i32 = 0;
    let mut _out2: i32 = 0;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out2)
             : "0"(a)
             :
             :
             );
    }
    _out1
}

// Change input -------------------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_input(_a: i32, _b: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a)
             :
             :
             );
    }
    _out
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_input(_a: i32, _b: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_b)
             :
             :
             );
    }
    _out
}

// Change input constraint -----------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_input_constraint(_a: i32, _b: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a), "r"(_b)
             :
             :
             );
    }
    _out
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_input_constraint(_a: i32, _b: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "r"(_a), "0"(_b)
             :
             :
             );
    }
    _out
}

// Change clobber --------------------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_clobber(_a: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a)
             :
             :
             );
    }
    _out
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_clobber(_a: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a)
             : "eax"
             :
             );
    }
    _out
}

// Change options --------------------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_options(_a: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a)
             :
             :
             );
    }
    _out
}

#[cfg(not(cfail1))]
#[rustc_clean(label="Hir", cfg="cfail2")]
#[rustc_clean(label="Hir", cfg="cfail3")]
#[rustc_dirty(label="HirBody", cfg="cfail2")]
#[rustc_clean(label="HirBody", cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn change_options(_a: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a)
             :
             : "volatile"
             );
    }
    _out
}

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

// This test case tests the incremental compilation hash (ICH) implementation
// for inline asm.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph

#![allow(warnings)]
#![feature(rustc_attrs)]
#![feature(asm)]
#![crate_type="rlib"]

// Change template -------------------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_template(a: i32) -> i32 {
    let c: i32;
    unsafe {
        asm!("add 1, $0"
             : "=r"(c)
             : "0"(a)
             :
             :
             );
    }
    c
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_template(a: i32) -> i32 {
    let c: i32;
    unsafe {
        asm!("add 2, $0"
             : "=r"(c)
             : "0"(a)
             :
             :
             );
    }
    c
}

// Change output -------------------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_output(a: i32) -> i32 {
    let mut _out1: i32 = 0;
    let mut _out2: i32 = 0;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out1)
             : "0"(a)
             :
             :
             );
    }
    _out1
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_output(a: i32) -> i32 {
    let mut _out1: i32 = 0;
    let mut _out2: i32 = 0;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out2)
             : "0"(a)
             :
             :
             );
    }
    _out1
}

// Change input -------------------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_input(_a: i32, _b: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a)
             :
             :
             );
    }
    _out
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_input(_a: i32, _b: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_b)
             :
             :
             );
    }
    _out
}

// Change input constraint -----------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a), "r"(_b)
             :
             :
             );
    }
    _out
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "r"(_a), "0"(_b)
             :
             :
             );
    }
    _out
}

// Change clobber --------------------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_clobber(_a: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a)
             :
             :
             );
    }
    _out
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_clobber(_a: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a)
             : "eax"
             :
             );
    }
    _out
}

// Change options --------------------------------------------------------------
#[cfg(cfail1)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_options(_a: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a)
             :
             :
             );
    }
    _out
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn change_options(_a: i32) -> i32 {
    let _out;
    unsafe {
        asm!("add 1, $0"
             : "=r"(_out)
             : "0"(_a)
             :
             : "volatile"
             );
    }
    _out
}

<|endoftext|>


<commit_before><commit_msg>Rollup merge of #63394 - jackh726:issue-36804, r=jonas-schievink<commit_after>// check-pass
#![feature(specialization)]

pub struct Cloned<I>(I);

impl<'a, I, T: 'a> Iterator for Cloned<I>
where
    I: Iterator<Item = &'a T>,
    T: Clone,
{
    type Item = T;

    fn next(&mut self) -> Option<T> {
        unimplemented!()
    }
}

impl<'a, I, T: 'a> Iterator for Cloned<I>
where
    I: Iterator<Item = &'a T>,
    T: Copy,
{
    fn count(self) -> usize {
        unimplemented!()
    }
}

fn main() {
    let a = [1,2,3,4];
    Cloned(a.iter()).count();
}
<|endoftext|>


<commit_before><commit_msg>added some impl macros<commit_after><|endoftext|>


<commit_before><commit_msg>Second-order benchmark<commit_after>//! FRP benchmarks from https://github.com/tsurucapital/frp-benchmarks
#![feature(test)]

extern crate test;
extern crate rand;
extern crate carboxyl;

use test::Bencher;
use rand::{XorShiftRng, sample};
use carboxyl::Sink;

/// Second-order benchmark.
///
/// Generate `n_sinks` `Stream<()>`, then for each stream create a `Cell<i32>`
/// that counts the number of firings. Create a `Stream<Cell<i32>>` that every
/// 10 network steps sequentially moves to the next cell. Create a `Cell<i32>`
/// from this stream. At each network step, fire 10 `Stream<()>` at random,
/// then print the current value of the `Cell<i32>`.
///
/// Benchmark the time required for `n_steps` steps.
fn second_order(n_sinks: usize, n_steps: usize, b: &mut Bencher) {
    // Setup network
    let stepper = Sink::<usize>::new();
    let sinks = (0..n_sinks)
        .map(|_| Sink::<()>::new())
        .collect::<Vec<_>>();
    let counters = sinks.iter()
        .map(|sink| sink.stream().scan(0, |n, _| n + 1))
        .collect::<Vec<_>>();
    let walker = {
        let counters = counters.clone();
        stepper.stream().map(move |k| counters[k / 10].clone())
    };
    let cell = walker.hold(counters[0].clone()).switch();

    // Feed events
    let mut rng = XorShiftRng::new_unseeded();
    b.iter(|| for i in 0..n_steps {
        stepper.send(i);
        for sink in sample(&mut rng, sinks.iter(), 10) {
            sink.send(());
        }
        format!("{}", cell.sample());
    });
}

#[bench]
fn second_order_100(b: &mut Bencher) {
    second_order(1_000, 100, b);
}

#[bench]
fn second_order_1k(b: &mut Bencher) {
    second_order(1_000, 1_000, b);
}

#[bench]
fn second_order_10k(b: &mut Bencher) {
    second_order(1_000, 10_000, b);
}
<|endoftext|>


<commit_before><commit_msg>fix: add missing swap<commit_after><|endoftext|>


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

// compile-flags: -Z identify_regions -Z span_free_formats
// ignore-tidy-linelength

// Regression test for #43457: an `EndRegion` was missing from output
// because compiler was using a faulty means for region map lookup.

use std::cell::RefCell;

fn rc_refcell_test(r: RefCell<i32>) {
    r.borrow_mut();
}

fn main() { }

// END RUST SOURCE
// START rustc.node5.SimplifyCfg-qualify-consts.after.mir
//
// fn rc_refcell_test(_1: std::cell::RefCell<i32>) -> () {
//     let mut _0: ();
//     scope 1 {
//         let _2: std::cell::RefCell<i32>;
//     }
//     let mut _3: std::cell::RefMut<'17ds, i32>;
//     let mut _4: &'17ds std::cell::RefCell<i32>;
//
//     bb0: {
//         StorageLive(_2);
//         _2 = _1;
//         StorageLive(_4);
//         _4 = &'17ds _2;
//         _3 = const <std::cell::RefCell<T>>::borrow_mut(_4) -> bb1;
//     }
//
//     bb1: {
//         drop(_3) -> bb2;
//     }
//
//     bb2: {
//         StorageDead(_4);
//         EndRegion('17ds);
//         _0 = ();
//         StorageDead(_2);
//         return;
//     }
// }
<commit_msg>Update regression test to explicit enable `EndRegion` emission.<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
// ignore-tidy-linelength

// Regression test for #43457: an `EndRegion` was missing from output
// because compiler was using a faulty means for region map lookup.

use std::cell::RefCell;

fn rc_refcell_test(r: RefCell<i32>) {
    r.borrow_mut();
}

fn main() { }

// END RUST SOURCE
// START rustc.node5.SimplifyCfg-qualify-consts.after.mir
//
// fn rc_refcell_test(_1: std::cell::RefCell<i32>) -> () {
//     let mut _0: ();
//     scope 1 {
//         let _2: std::cell::RefCell<i32>;
//     }
//     let mut _3: std::cell::RefMut<'17ds, i32>;
//     let mut _4: &'17ds std::cell::RefCell<i32>;
//
//     bb0: {
//         StorageLive(_2);
//         _2 = _1;
//         StorageLive(_4);
//         _4 = &'17ds _2;
//         _3 = const <std::cell::RefCell<T>>::borrow_mut(_4) -> bb1;
//     }
//
//     bb1: {
//         drop(_3) -> bb2;
//     }
//
//     bb2: {
//         StorageDead(_4);
//         EndRegion('17ds);
//         _0 = ();
//         StorageDead(_2);
//         return;
//     }
// }
<|endoftext|>


<commit_before><commit_msg>Use window ratio when constructing projection matrix.<commit_after><|endoftext|>


<commit_before><commit_msg>Add udp echo server example<commit_after>use mio::net::UdpSocket;
use mio::{Events, Interests, Poll, Token};
use std::io;

const IN: Token = Token(0);

fn main() {
    // Set up a new socket on port 9000 to listen on.
    let socket = UdpSocket::bind("0.0.0.0:9000".parse().unwrap()).unwrap();
    // Initialize poller.
    let mut poll = Poll::new().unwrap();
    // Register our socket with the token IN (defined above) and an interest
    // in being `READABLE`.
    poll.registry()
        .register(&socket, IN, Interests::READABLE)
        .unwrap();

    // Prepare a buffer for the number of events we can handle at a time.
    // Someone might wat to echo really fast so lets give it some size.
    let mut events = Events::with_capacity(1024);
    // Initialize a buffer for the UDP datagram
    let mut buf = [0; 65535];
    // Main loop
    loop {
        // Poll if we have events waiting for us on the socket.
        poll.poll(&mut events, None).unwrap();
        // If we do iterate throuigh them
        for event in events.iter() {
            // Validate the token we registered our socket with,
            // in this example it will only ever be one but we
            // make sure it's valid non the less.
            match event.token() {
                IN => loop {
                    // In this loop we receive from the socket as long as we
                    // can read data
                    match socket.recv_from(&mut buf) {
                        Ok((n, from_addr)) => {
                            // Send the data right back from where it came from.
                            let _r = socket.send_to(&buf[..n], from_addr);
                        }
                        Err(e) => {
                            // If we failed to receive data we have two cases
                            if e.kind() == io::ErrorKind::WouldBlock {
                                // If the reason was `WouldBlock` we know
                                // our socket has no more data to give so
                                // we can return to the poll to wait politely.
                                break;
                            } else {
                                // If it was any other kind of error, something
                                // went wrong and we panic.
                                panic!("error: {:?}", e)
                            }
                        }
                    }
                },
                // We only have IN as a token, so this should never ever be hit
                _ => unreachable!(),
            }
        }
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use toml::Value;

use libimagstore::store::Entry;

use builtin::header::field_path::FieldPath;
use filter::Filter;

/// Check whether certain header field in a entry is equal to a value
pub struct FieldGrep {
    header_field_path: FieldPath,
    grep: Regex,
}

impl FieldGrep {

    pub fn new(path: FieldPath, grep: Regex) -> FieldGrep {
        FieldGrep {
            header_field_path: path,
            grep: grep,
        }
    }

}

impl Filter for FieldGrep {

    fn filter(&self, e: &Entry) -> bool {
        e.get_header()
            .read(&self.header_field_path[..])
            .map(|v| {
                match v {
                    Some(Value::String(s)) => self.grep.captures(&s[..]).is_some(),
                    _                      => false,
                }
            })
            .unwrap_or(false)
    }

}

<commit_msg>Add field_grep filter<commit_after>use regex::Regex;
use toml::Value;

use libimagstore::store::Entry;

use builtin::header::field_path::FieldPath;
use builtin::header::field_predicate::FieldPredicate;
use builtin::header::field_predicate::Predicate;
use filter::Filter;

struct EqGrep{
    regex: Regex
}

impl Predicate for EqGrep {

    fn evaluate(&self, v: Value) -> bool {
        match v {
            Value::String(s) => self.regex.captures(&s[..]).is_some(),
            _                 => false,
        }
    }

}

/// Check whether certain header field in a entry is equal to a value
pub struct FieldGrep {
    filter: FieldPredicate<EqGrep>,
}

impl FieldGrep {

    pub fn new(path: FieldPath, grep: Regex) -> FieldGrep {
        FieldGrep {
            filter: FieldPredicate::new(path, Box::new(EqGrep { regex: grep})),
        }
    }

}

impl Filter for FieldGrep {

    fn filter(&self, e: &Entry) -> bool {
        self.filter.filter(e)
    }

}

<|endoftext|>


<commit_before><commit_msg>Initial commit<commit_after>use std::env;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::Path;

// Lookup table
// We can generate this but it's small enough to hardcode
const TABLE : [u32; 256] = [
        0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
        0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
        0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
        0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
        0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
        0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
        0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
        0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
        0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
        0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
        0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
        0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
        0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
        0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
        0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
        0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
        0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
        0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
        0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
        0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
        0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
        0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
        0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
        0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
        0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
        0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
        0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
        0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
        0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
        0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
        0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
        0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
        0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
        0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
        0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
        0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
        0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
        0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
        0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
        0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
        0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
        0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
        0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
    ];

fn main() {

	let args : Vec<_> = env::args().collect();

	if args.len() < 2 {
		print_usage();
		return;
	}

	// Get the file name from the commandline
	// arguments
	let filename = &args[1];

	// Open the file
	let mut file = match File::open(filename) {
	    Ok(file) => file,
	    Err(why) => panic!("Couldn't open {}: {}", filename,
                     Error::description(&why)),
	};

 	// Read the contents of the file into a byte vector
	let mut contents : Vec<u8> = Vec::new();
	file.read_to_end(&mut contents).unwrap();

	// Compute the check sum
	let crc = compute_checksum(&contents);

	// Print it
	println!("{0:x}", crc);
}

fn compute_checksum(input : &[u8]) -> u32 {

	// Start an initial value of 0xFFFFFFFF - all bits are set
    input.iter().fold(0xFFFFFFFFu32,
    	| acc, &item | {
    		// Generate an index based on the low bits of our current
    		// CRC XOR'd with current item in our array
			let index = (acc & 0xFF) ^ (item as u32);

			// Right shift the crc by 8 bits and XOR it with the value
			// in the look up table
			(acc >> 8) ^ (TABLE[index as usize] as u32)
	}) ^ 0xFFFFFFFFu32 // XOR the final CRC with -1

}

fn print_usage() {
	let app_path = env::args().next().unwrap().clone();

	let path = Path::new(&app_path);
	println!("usage: {} <filename>",
		// Display the file name only, not the full path
		path.file_name().unwrap().to_str().unwrap());
}<|endoftext|>


<commit_before><commit_msg>Added triangle gradient example<commit_after>extern crate tetrahedrane;

use tetrahedrane::vid::*;
use tetrahedrane::start;
use tetrahedrane::shaders;

fn main() {
    // Make a new window
    let mut window = start::Window::new(640, 480, "Hello World!", 1 as usize);

    let mut shaders: Vec<Shader> = Vec::new();

    // Create a triangle
    let mut triangle = Triangle::new(DepthPoint::new(0.0, -0.5, 3.0),
                                 DepthPoint::new(0.5, 0.5, 3.0),
                                 DepthPoint::new(-0.5, 0.5, 3.0),
                                 0.0, 0.0, 0.0,
                                 Color::new(200, 200, 200));

    // Add a shader
    shaders.push(shaders::filled_triangle_gradient(1));

    // Apply shader to the triangle
    triangle.shader_ids[0] = 1;

    loop {
        window.window.set(Color::new(20, 40, 60).orb_color());
        window.window.set(Color::new(20, 40, 60).orb_color());

        triangle.coord_rotate_x_y(0.0, 0.0, 0.01);
        triangle.coord_rotate_x_z(0.0, 3.0, 0.02);
        triangle.coord_rotate_y_z(0.0, 3.0, 0.05);

        // Render the triangle with shaders.
        window.render(triangle, &shaders);

        window.window.sync();

        std::thread::sleep(std::time::Duration::from_millis(16));
    }
}<|endoftext|>


<commit_before><commit_msg>Implement CacheMiddleware<commit_after>use moka::future::Cache;
use std::time::Duration;
use tide::{
    http::{
        content::{AcceptEncoding, ContentEncoding, Encoding},
        headers::{HeaderName, HeaderValues},
        Method, Mime,
    },
    Body, Middleware, Next, Request, Response, StatusCode,
};
use wildmatch::WildMatch;

#[derive(Clone)]
pub struct CacheMiddleware {
    cache: Cache<String, (StatusCode, Mime, Vec<u8>, Vec<(HeaderName, HeaderValues)>)>,
    skip_cache_wildmatch: Option<Vec<WildMatch>>,
}

impl CacheMiddleware {
    pub fn new(
        prefix: String,
        cache_ttl_sec: u64,
        cache_tti_sec: u64,
        skip_cache_path: Option<Vec<String>>,
    ) -> Self {
        log::info!(
            "Setting up response cache for path {} with time-to-live: {}s and time-to-idle: {}s",
            &prefix,
            &cache_ttl_sec,
            &cache_tti_sec,
        );
        let cache = Cache::builder()
            .time_to_live(Duration::from_secs(cache_ttl_sec))
            .time_to_idle(Duration::from_secs(cache_tti_sec))
            .build();
        let skip_cache_wildmatch = match skip_cache_path {
            Some(skip_cache_path) => Some(
                skip_cache_path
                    .iter()
                    .map(|path| WildMatch::new(path))
                    .collect(),
            ),
            None => None,
        };

        Self {
            cache,
            skip_cache_wildmatch,
        }
    }
}

#[tide::utils::async_trait]
impl<State: Clone + Send + Sync + 'static> Middleware<State> for CacheMiddleware {
    async fn handle(&self, req: Request<State>, next: Next<'_, State>) -> tide::Result {
        let url_path: String = req.url().path().to_string();
        let skip_cache: bool = {
            if req.method() != Method::Get {
                true
            } else {
                match &self.skip_cache_wildmatch {
                    Some(skip_cache_wildmatch) => skip_cache_wildmatch
                        .iter()
                        .find(|wildmatch_path| wildmatch_path.matches(&url_path))
                        .is_some(),
                    None => false,
                }
            }
        };

        let cache_key: Option<String> = if skip_cache {
            None
        } else {
            let accepts = AcceptEncoding::from_headers(&req)?;
            let encoding: String = if let Some(mut accepts) = accepts {
                let encoding =
                    accepts.negotiate(&[Encoding::Brotli, Encoding::Gzip, Encoding::Deflate])?;
                encoding.to_string()
            } else {
                "".to_string()
            };

            Some(get_cache_key(&url_path, &encoding))
        };

        if let Some(cache_key) = &cache_key {
            // Try to find this request from the cache
            let cached_response = &self.cache.get(&cache_key.clone());
            if let Some((status, mime, body_as_bytes, headers)) = cached_response {
                log::debug!("Cache hit: {}", cache_key);
                let mut body = Body::from_bytes(body_as_bytes.to_vec());
                body.set_mime(mime.clone());
                let mut res_builder = Response::builder(status.clone()).body(body);
                for (header_name, header_values) in headers {
                    res_builder = res_builder.header(header_name, header_values);
                }
                return Ok(res_builder.build());
            }
        }

        let mut res: Response = next.run(req).await;
        if let Some(cache_key) = cache_key {
            let status = res.status();
            if !status.is_success() {
                return Ok(res);
            }
            let response_encoding =
                if let Some(response_encoding) = ContentEncoding::from_headers(&res).unwrap() {
                    response_encoding.to_string()
                } else {
                    "".to_string()
                };
            let response_cache_key = get_cache_key(&url_path, &response_encoding);
            if response_cache_key != cache_key {
                // For some reason tide_compress didn't encode the way we thought it would
                log::error!(
                    "Encoding mismatch with cache, expected: '{}' but was '{}'",
                    &cache_key,
                    response_cache_key
                );
                return Ok(res);
            }

            log::debug!("Cache_miss: {}", cache_key);
            let cache_headers: Vec<(HeaderName, HeaderValues)> = res
                .iter()
                .map(|(header_name, header_values)| (header_name.clone(), header_values.clone()))
                .collect();
            let body = res.take_body();
            let mime = body.mime().clone();
            let body_as_bytes = body.into_bytes().await.unwrap();

            self.cache
                .insert(
                    cache_key,
                    (status, mime.clone(), body_as_bytes.clone(), cache_headers),
                )
                .await;
            let mut body = Body::from_bytes(body_as_bytes);
            body.set_mime(mime.clone());
            res.set_body(body);
            Ok(res)
        } else {
            // There is no caching for this request, just return the response we got
            log::debug!("Skip cache: {}", url_path);
            Ok(res)
        }
    }
}

fn get_cache_key(url_path: &str, encoding: &str) -> String {
    format!("{} {}", url_path, encoding)
}
<|endoftext|>


<commit_before><commit_msg>Fix cursor movement<commit_after><|endoftext|>


<commit_before>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate serde_json;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate task_hookrs;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;
extern crate libimagtodo;

use std::process::exit;
use std::process::{Command, Stdio};
use std::io::stdin;

use toml::Value;

use task_hookrs::import::import_tasks;
use task_hookrs::status::TaskStatus;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagtodo::task::Task;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;
fn main() {
    let rt = generate_runtime_setup("imag-todo",
                                    &version!()[..],
                                    "Interface with taskwarrior",
                                    build_ui);

    match rt.cli().subcommand_name() {
        Some("tw-hook") => tw_hook(&rt),
        Some("list") => list(&rt),
        _ => unreachable!(),
    } // end match scmd
} // end main

fn tw_hook(rt: &Runtime) {
    let subcmd = rt.cli().subcommand_matches("tw-hook").unwrap();
    if subcmd.is_present("add") {
        let stdin = stdin();
        let stdin = stdin.lock(); // implements BufRead which is required for `Task::import()`

        match Task::import(rt.store(), stdin) {
            Ok((_, line, uuid)) => info!("{}\nTask {} stored in imag", line, uuid),
            Err(e) => {
                trace_error(&e);
                exit(1);
            }
        }
    } else if subcmd.is_present("delete") {
        // The used hook is "on-modify". This hook gives two json-objects
        // per usage und wants one (the second one) back.
        let stdin         = stdin();
        let stdin         = stdin.lock();

        match import_tasks(stdin) {
            Ok(ttasks) => for (counter, ttask) in ttasks.iter().enumerate() {
                if counter % 2 == 1 {
                    // Only every second task is needed, the first one is the
                    // task before the change, and the second one after
                    // the change. The (maybe modified) second one is
                    // expected by taskwarrior.
                    match serde_json::ser::to_string(&ttask) {
                        Ok(val) => println!("{}", val),
                        Err(e) => {
                            trace_error(&e);
                            exit(1);
                        }
                    }

                    // Taskwarrior does not have the concept of deleted tasks, but only modified
                    // ones.
                    //
                    // Here we check if the status of a task is deleted and if yes, we delete it
                    // from the store.
                    if *ttask.status() == TaskStatus::Deleted {
                        match Task::delete_by_uuid(rt.store(), *ttask.uuid()) {
                            Ok(_) => println!("Deleted task {}", *ttask.uuid()),
                            Err(e) => {
                                trace_error(&e);
                                exit(1);
                            }
                        }
                    }
                } // end if c % 2
            },
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
        }
    } else {
        // Should not be possible, as one argument is required via
        // ArgGroup
        unreachable!();
    }
}

fn list(rt: &Runtime) {
    let subcmd  = rt.cli().subcommand_matches("list").unwrap();
    let verbose = subcmd.is_present("verbose");

    let res = Task::all(rt.store()) // get all tasks
        .map(|iter| { // and if this succeeded
            // filter out the ones were we can read the uuid
            let uuids : Vec<_> = iter.filter_map(|t| match t {
                Ok(v) => match v.get_header().read("todo.uuid") {
                    Ok(Some(Value::String(ref u))) => Some(u.clone()),
                    Ok(Some(_)) => {
                        warn!("Header type error");
                        None
                    },
                    Ok(None) => None,
                    Err(e) => {
                        trace_error(&e);
                        None
                    }
                },
                Err(e) => {
                    trace_error(&e);
                    None
                }
            })
            .collect();

            // compose a `task` call with them, ...
            let outstring = if verbose { // ... if verbose
                let output = Command::new("task")
                    .stdin(Stdio::null())
                    .args(&uuids)
                    .spawn()
                    .unwrap_or_else(|e| {
                        trace_error(&e);
                        panic!("Failed to execute `task` on the commandline. I'm dying now.");
                    })
                    .wait_with_output()
                    .unwrap_or_else(|e| panic!("failed to unwrap output: {}", e));

                String::from_utf8(output.stdout)
                    .unwrap_or_else(|e| panic!("failed to execute: {}", e))
            } else { // ... else just join them
                uuids.join("\n")
            };

            // and then print that
            println!("{}", outstring);
        });

    if let Err(e) = res {
        trace_error(&e);
    }
}

<commit_msg>We must actually use println!() here<commit_after>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate serde_json;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate task_hookrs;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;
extern crate libimagtodo;

use std::process::exit;
use std::process::{Command, Stdio};
use std::io::stdin;

use toml::Value;

use task_hookrs::import::import_tasks;
use task_hookrs::status::TaskStatus;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagtodo::task::Task;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;
fn main() {
    let rt = generate_runtime_setup("imag-todo",
                                    &version!()[..],
                                    "Interface with taskwarrior",
                                    build_ui);

    match rt.cli().subcommand_name() {
        Some("tw-hook") => tw_hook(&rt),
        Some("list") => list(&rt),
        _ => unreachable!(),
    } // end match scmd
} // end main

fn tw_hook(rt: &Runtime) {
    let subcmd = rt.cli().subcommand_matches("tw-hook").unwrap();
    if subcmd.is_present("add") {
        let stdin = stdin();
        let stdin = stdin.lock(); // implements BufRead which is required for `Task::import()`

        match Task::import(rt.store(), stdin) {
            Ok((_, line, uuid)) => println!("{}\nTask {} stored in imag", line, uuid),
            Err(e) => {
                trace_error(&e);
                exit(1);
            }
        }
    } else if subcmd.is_present("delete") {
        // The used hook is "on-modify". This hook gives two json-objects
        // per usage und wants one (the second one) back.
        let stdin         = stdin();
        let stdin         = stdin.lock();

        match import_tasks(stdin) {
            Ok(ttasks) => for (counter, ttask) in ttasks.iter().enumerate() {
                if counter % 2 == 1 {
                    // Only every second task is needed, the first one is the
                    // task before the change, and the second one after
                    // the change. The (maybe modified) second one is
                    // expected by taskwarrior.
                    match serde_json::ser::to_string(&ttask) {
                        Ok(val) => println!("{}", val),
                        Err(e) => {
                            trace_error(&e);
                            exit(1);
                        }
                    }

                    // Taskwarrior does not have the concept of deleted tasks, but only modified
                    // ones.
                    //
                    // Here we check if the status of a task is deleted and if yes, we delete it
                    // from the store.
                    if *ttask.status() == TaskStatus::Deleted {
                        match Task::delete_by_uuid(rt.store(), *ttask.uuid()) {
                            Ok(_) => println!("Deleted task {}", *ttask.uuid()),
                            Err(e) => {
                                trace_error(&e);
                                exit(1);
                            }
                        }
                    }
                } // end if c % 2
            },
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
        }
    } else {
        // Should not be possible, as one argument is required via
        // ArgGroup
        unreachable!();
    }
}

fn list(rt: &Runtime) {
    let subcmd  = rt.cli().subcommand_matches("list").unwrap();
    let verbose = subcmd.is_present("verbose");

    let res = Task::all(rt.store()) // get all tasks
        .map(|iter| { // and if this succeeded
            // filter out the ones were we can read the uuid
            let uuids : Vec<_> = iter.filter_map(|t| match t {
                Ok(v) => match v.get_header().read("todo.uuid") {
                    Ok(Some(Value::String(ref u))) => Some(u.clone()),
                    Ok(Some(_)) => {
                        warn!("Header type error");
                        None
                    },
                    Ok(None) => None,
                    Err(e) => {
                        trace_error(&e);
                        None
                    }
                },
                Err(e) => {
                    trace_error(&e);
                    None
                }
            })
            .collect();

            // compose a `task` call with them, ...
            let outstring = if verbose { // ... if verbose
                let output = Command::new("task")
                    .stdin(Stdio::null())
                    .args(&uuids)
                    .spawn()
                    .unwrap_or_else(|e| {
                        trace_error(&e);
                        panic!("Failed to execute `task` on the commandline. I'm dying now.");
                    })
                    .wait_with_output()
                    .unwrap_or_else(|e| panic!("failed to unwrap output: {}", e));

                String::from_utf8(output.stdout)
                    .unwrap_or_else(|e| panic!("failed to execute: {}", e))
            } else { // ... else just join them
                uuids.join("\n")
            };

            // and then print that
            println!("{}", outstring);
        });

    if let Err(e) = res {
        trace_error(&e);
    }
}

<|endoftext|>


<commit_before><commit_msg>Remove unnecessary mut on variable.<commit_after><|endoftext|>


<commit_before>use super::geometry::*;

fn rotate(x: f32, y: f32, around_x: f32, around_y: f32, angle: f32) -> (f32, f32) {
    use std::f32;

    let s = f32::sin(angle);
    let c = f32::cos(angle);

    let x = x - around_x;
    let y = y - around_y;

    let x = x * c - y * s;
    let y = x * s + y * c;

    (x + around_x, y + around_y)
}

pub trait Rotation {
    fn rotate_x_y(&mut self, x: f32, y: f32, angle: f32);
    fn rotate_x_z(&mut self, x: f32, y: f32, angle: f32);
    fn rotate_y_z(&mut self, x: f32, y: f32, angle: f32);
}

impl Rotation for Point {
    fn rotate_x_y(&mut self, x: f32, y: f32, angle: f32) {
        let (x, y) = rotate(self.x, self.y, x, y, angle);
        self.x = x;
        self.y = y;
    }

    fn rotate_x_z(&mut self, x: f32, z: f32, angle: f32) {
        let (x, z) = rotate(self.x, self.z, x, z, angle);
        self.x = x;
        self.z = z;
    }

    fn rotate_y_z(&mut self, y: f32, z: f32, angle: f32) {
        let (y, z) = rotate(self.y, self.z, y, z, angle);
        self.y = y;
        self.z = z;
    }
}

impl Rotation for Triangle {
    fn rotate_x_y(&mut self, x: f32, y: f32, angle: f32) {
        self.p1.rotate_x_y(x, y, angle);
        self.p2.rotate_x_y(x, y, angle);
        self.p3.rotate_x_y(x, y, angle);
    }

    fn rotate_x_z(&mut self, x: f32, z: f32, angle: f32) {
        self.p1.rotate_x_z(x, z, angle);
        self.p2.rotate_x_z(x, z, angle);
        self.p3.rotate_x_z(x, z, angle);
    }

    fn rotate_y_z(&mut self, y: f32, z: f32, angle: f32) {
        self.p1.rotate_y_z(y, z, angle);
        self.p2.rotate_y_z(y, z, angle);
        self.p3.rotate_y_z(y, z, angle);
    }
}<commit_msg>Add some docstrings<commit_after>use super::geometry::*;

fn rotate(x: f32, y: f32, around_x: f32, around_y: f32, angle: f32) -> (f32, f32) {
    use std::f32;

    let s = f32::sin(angle);
    let c = f32::cos(angle);

    let x = x - around_x;
    let y = y - around_y;

    let x = x * c - y * s;
    let y = x * s + y * c;

    (x + around_x, y + around_y)
}

pub trait Rotation {
    fn rotate_x_y(&mut self, x: f32, y: f32, angle: f32);
    fn rotate_x_z(&mut self, x: f32, y: f32, angle: f32);
    fn rotate_y_z(&mut self, x: f32, y: f32, angle: f32);
}

impl Rotation for Point {
    /// Rotates on x and y axes. You shouldn't rotate a point you rotated
    /// earlier, instead keep rotating the initial one.
    /// For some reason, it breaks for some reason if you keep rotating too much
    fn rotate_x_y(&mut self, x: f32, y: f32, angle: f32) -> Point {
        let (x, y) = rotate(self.x, self.y, x, y, angle);
        Point {
            x: x,
            y: y,
            z: self.z,
        }
    }

    /// Rotate on x and z axes. Same error as with rotate_x_y
    fn rotate_x_z(&mut self, x: f32, z: f32, angle: f32) {
        let (x, z) = rotate(self.x, self.z, x, z, angle);
        self.x = x;
        self.z = z;
    }

    /// Rotate on y and z axes. Same error as with rotate_x_y
    fn rotate_y_z(&mut self, y: f32, z: f32, angle: f32) {
        let (y, z) = rotate(self.y, self.z, y, z, angle);
        self.y = y;
        self.z = z;
    }
}

impl Rotation for Triangle {
    fn rotate_x_y(&mut self, x: f32, y: f32, angle: f32) {
        self.p1.rotate_x_y(x, y, angle);
        self.p2.rotate_x_y(x, y, angle);
        self.p3.rotate_x_y(x, y, angle);
    }

    fn rotate_x_z(&mut self, x: f32, z: f32, angle: f32) {
        self.p1.rotate_x_z(x, z, angle);
        self.p2.rotate_x_z(x, z, angle);
        self.p3.rotate_x_z(x, z, angle);
    }

    fn rotate_y_z(&mut self, y: f32, z: f32, angle: f32) {
        self.p1.rotate_y_z(y, z, angle);
        self.p2.rotate_y_z(y, z, angle);
        self.p3.rotate_y_z(y, z, angle);
    }
}<|endoftext|>