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

//! Miscellaneous `embedded-hal` trait implementations.
//!
//! The `hal` module consists of a collection of `embedded-hal` trait
//! implementations for traits that aren't tied to a specific peripheral.
//!
//! This module is only included when either the `hal` or `hal-unproven` feature
//! flag is enabled.

use std::thread;
use std::time::{Duration, Instant};

use embedded_hal::blocking::delay::{DelayMs, DelayUs};
use embedded_hal::timer::CountDown;
use void::Void;

/// Implements the `embedded-hal` `DelayMs` and `DelayUs` traits.
#[derive(Debug, Default)]
pub struct Delay {}

impl Delay {
    /// Constructs a new `Delay`.
    pub fn new() -> Delay {
        Delay {}
    }
}

impl DelayMs<u8> for Delay {
    fn delay_ms(&mut self, ms: u8) {
        thread::sleep(Duration::from_millis(u64::from(ms)));
    }
}

impl DelayMs<u16> for Delay {
    fn delay_ms(&mut self, ms: u16) {
        thread::sleep(Duration::from_millis(u64::from(ms)));
    }
}

impl DelayMs<u32> for Delay {
    fn delay_ms(&mut self, ms: u32) {
        thread::sleep(Duration::from_millis(u64::from(ms)));
    }
}

impl DelayMs<u64> for Delay {
    fn delay_ms(&mut self, ms: u64) {
        thread::sleep(Duration::from_millis(ms));
    }
}

impl DelayUs<u8> for Delay {
    fn delay_us(&mut self, us: u8) {
        thread::sleep(Duration::from_micros(u64::from(us)));
    }
}

impl DelayUs<u16> for Delay {
    fn delay_us(&mut self, us: u16) {
        thread::sleep(Duration::from_micros(u64::from(us)));
    }
}

impl DelayUs<u32> for Delay {
    fn delay_us(&mut self, us: u32) {
        thread::sleep(Duration::from_micros(u64::from(us)));
    }
}

impl DelayUs<u64> for Delay {
    fn delay_us(&mut self, us: u64) {
        thread::sleep(Duration::from_micros(us));
    }
}

/// Implements the `embedded-hal` `CountDown` trait.
#[derive(Debug, Default, Copy, Clone)]
pub struct Timer {
    now: Instant,
    duration: Duration,
}

impl Timer {
    /// Constructs a new `Timer`.
    pub fn new() -> Self {
        Self {
            now: Instant::now(),
            duration: Duration::from_micros(0),
        }
    }
}

pub struct Millisecond(pub u64);
pub struct Microsecond(pub u64);
pub struct Second(pub u64);

impl From<Millisecond> for Microsecond {
    fn from(item: Millisecond) -> Self {
        Microsecond(item.0 * 1_000)
    }
}

impl From<Second> for Microsecond {
    fn from(item: Second) -> Self {
        Microsecond(item.0 * 1_000_000)
    }
}

impl Microsecond {
    fn as_u64(&self) -> u64 {
        let &Microsecond(t) = self;
        t
    }
}

impl CountDown for Timer {
    type Time = Microsecond;

    /// Start the timer with a `timeout`
    fn start<T>(&mut self, timeout: T)
    where
        T: Into<Microsecond>,
    {
        self.duration = Duration::from_micros(timeout.into().as_u64());
        self.now = Instant::now();
    }

    /// Return `Ok` if the timer has wrapped
    /// Automatically clears the flag and restarts the time
    fn wait(&mut self) -> nb::Result<(), Void> {
        if self.now.elapsed() >= self.duration {
            Ok(())
        } else {
            Err(nb::Error::WouldBlock)
        }
    }
}
<commit_msg>Manually implement Default for Timer<commit_after>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Miscellaneous `embedded-hal` trait implementations.
//!
//! The `hal` module consists of a collection of `embedded-hal` trait
//! implementations for traits that aren't tied to a specific peripheral.
//!
//! This module is only included when either the `hal` or `hal-unproven` feature
//! flag is enabled.

use std::thread;
use std::time::{Duration, Instant};

use embedded_hal::blocking::delay::{DelayMs, DelayUs};
use embedded_hal::timer::CountDown;
use void::Void;

/// Implements the `embedded-hal` `DelayMs` and `DelayUs` traits.
#[derive(Debug, Default)]
pub struct Delay {}

impl Delay {
    /// Constructs a new `Delay`.
    pub fn new() -> Delay {
        Delay {}
    }
}

impl DelayMs<u8> for Delay {
    fn delay_ms(&mut self, ms: u8) {
        thread::sleep(Duration::from_millis(u64::from(ms)));
    }
}

impl DelayMs<u16> for Delay {
    fn delay_ms(&mut self, ms: u16) {
        thread::sleep(Duration::from_millis(u64::from(ms)));
    }
}

impl DelayMs<u32> for Delay {
    fn delay_ms(&mut self, ms: u32) {
        thread::sleep(Duration::from_millis(u64::from(ms)));
    }
}

impl DelayMs<u64> for Delay {
    fn delay_ms(&mut self, ms: u64) {
        thread::sleep(Duration::from_millis(ms));
    }
}

impl DelayUs<u8> for Delay {
    fn delay_us(&mut self, us: u8) {
        thread::sleep(Duration::from_micros(u64::from(us)));
    }
}

impl DelayUs<u16> for Delay {
    fn delay_us(&mut self, us: u16) {
        thread::sleep(Duration::from_micros(u64::from(us)));
    }
}

impl DelayUs<u32> for Delay {
    fn delay_us(&mut self, us: u32) {
        thread::sleep(Duration::from_micros(u64::from(us)));
    }
}

impl DelayUs<u64> for Delay {
    fn delay_us(&mut self, us: u64) {
        thread::sleep(Duration::from_micros(us));
    }
}

/// Implements the `embedded-hal` `CountDown` trait.
#[derive(Debug, Copy, Clone)]
pub struct Timer {
    now: Instant,
    duration: Duration,
}

impl Timer {
    /// Constructs a new `Timer`.
    pub fn new() -> Self {
        Self {
            now: Instant::now(),
            duration: Duration::from_micros(0),
        }
    }
}

impl Default for Timer {
    fn default() -> Self {
        Timer::new()
    }
}

pub struct Millisecond(pub u64);
pub struct Microsecond(pub u64);
pub struct Second(pub u64);

impl From<Millisecond> for Microsecond {
    fn from(item: Millisecond) -> Self {
        Microsecond(item.0 * 1_000)
    }
}

impl From<Second> for Microsecond {
    fn from(item: Second) -> Self {
        Microsecond(item.0 * 1_000_000)
    }
}

impl Microsecond {
    fn as_u64(&self) -> u64 {
        let &Microsecond(t) = self;
        t
    }
}

impl CountDown for Timer {
    type Time = Microsecond;

    /// Start the timer with a `timeout`
    fn start<T>(&mut self, timeout: T)
    where
        T: Into<Microsecond>,
    {
        self.duration = Duration::from_micros(timeout.into().as_u64());
        self.now = Instant::now();
    }

    /// Return `Ok` if the timer has wrapped
    /// Automatically clears the flag and restarts the time
    fn wait(&mut self) -> nb::Result<(), Void> {
        if self.now.elapsed() >= self.duration {
            Ok(())
        } else {
            Err(nb::Error::WouldBlock)
        }
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use address::Address;
use basicblock::{BasicBlock, BasicBlockEdge, EdgeType};
use instruction::Instruction;
use petgraph::graph::{Graph, NodeIndex};
use std::collections::BTreeMap;

/// A [control flow graph].
///
/// [control flow graph]: https://en.wikipedia.org/wiki/Control_flow_graph
pub struct ControlFlowGraph<'f, I: 'f + Instruction> {
    /// The [`Graph`] that stores the actual ControlFlowGraph
    ///
    /// [`Graph`]: ../petgraph/graph/struct.Graph.html
    pub graph: Graph<BasicBlock<'f, I>, BasicBlockEdge>,
    /// The [`NodeIndex`] for the entry [`BasicBlock`] for this function.
    ///
    /// [`BasicBlock`]: struct.BasicBlock.html
    /// [`NodeIndex`]: ../petgraph/graph/struct.NodeIndex.html
    pub entry_block: Option<NodeIndex>,
    /// Map an [address] to the corresponding [basic block].
    ///
    /// [address]: struct.Address.html
    /// [basic block]: struct.BasicBlock.html
    pub block_finder: BTreeMap<Address, NodeIndex>,
}

impl<'f, I: Instruction> ControlFlowGraph<'f, I> {
    /// Build the ControlFlowGraph from the [`instructions`].
    ///
    /// This is conducted in a 2 step process:
    ///
    /// * First, each instruction is examined to identify block boundaries.
    /// * Then, we go through each instruction again, looking for the
    ///   previously identified block boundaries and build the edges.
    ///
    /// This two step process prevents us from having to construct and then
    /// subsequently split blocks as we find backward edges.
    ///
    /// [`instructions`]: trait.Instruction.html
    pub fn new(instructions: &'f [I]) -> Self {
        let mut cfg = ControlFlowGraph {
            graph: Graph::new(),
            entry_block: None,
            block_finder: BTreeMap::new(),
        };
        if !instructions.is_empty() {
            cfg.identify_blocks(instructions);
            cfg.build_edges(instructions);
        }
        cfg
    }

    /// Identify basic blocks by their boundaries.
    ///
    /// Inspect each instruction to see if it is a 'leader' or the start of
    /// a new basic block. An instruction is a leader if:
    ///
    /// * It is the first instruction in the basic block.
    /// * It comes after a branch of any sort. We identify these as things
    ///   for which `Instruction::is_block_terminator` returns `true`.
    /// * It is the target of a jump (conditional or unconditional) within
    ///   the function.
    fn identify_blocks(&mut self, instructions: &[I]) {
        let start_addr = instructions[0].address();
        let end_addr = instructions.last().map(|i| i.address()).unwrap();
        let mut next_is_leader: bool = true;
        for inst in instructions {
            if next_is_leader {
                let idx = self.graph.add_node(BasicBlock::new(inst.address()));
                self.block_finder.insert(inst.address(), idx);
                next_is_leader = false;
            }
            if inst.is_block_terminator() {
                if let Some(target_addr) = inst.target_address() {
                    if !self.block_finder.contains_key(&target_addr) &&
                       target_addr >= start_addr && target_addr <= end_addr {
                        let idx = self.graph.add_node(BasicBlock::new(target_addr));
                        self.block_finder.insert(target_addr, idx);
                    }
                }
                // The next instruction, if any, will be the start of a new block.
                next_is_leader = true;
            }
        }
        self.entry_block = Some(*self.block_finder.get(&instructions[0].address()).unwrap());
    }

    /// Build an edge between 2 basic blocks.
    fn build_edge(&mut self,
                  current_block_idx: NodeIndex,
                  next_block_idx: NodeIndex,
                  current_inst: &I) {
        if current_inst.is_local_conditional_jump() {
            // We have one edge for the jump target and one for the fallthrough.
            // We jump through some hoops here to keep the borrow checker happy.
            if let Some(target_addr) = current_inst.target_address() {
                if let Some(target_block_idx) = self.block_finder.get(&target_addr) {
                    let edge = BasicBlockEdge { edge_type: EdgeType::ConditionalTaken };
                    self.graph.add_edge(current_block_idx, *target_block_idx, edge);
                }
                let edge = BasicBlockEdge { edge_type: EdgeType::ConditionalFallthrough };
                self.graph.add_edge(current_block_idx, next_block_idx, edge);
            }
        } else if current_inst.is_local_jump() || current_inst.is_call() {
            let edge = BasicBlockEdge { edge_type: EdgeType::Unconditional };
            self.graph.add_edge(current_block_idx, next_block_idx, edge);
        } else if current_inst.is_return() {
            // Do we want to record this exit anywhere?
        }
    }

    /// Build edges after having identified the basic blocks.
    ///
    /// After the basic blocks have been identified, we can go back and
    /// connect the basic blocks with their appropriate edges.
    ///
    /// We do this by iterating through the instructions looking for
    /// boundaries between the basic blocks and then setting up the
    /// new edges.
    fn build_edges(&mut self, instructions: &'f [I]) {
        // Here, we're going to walk through the instructions again,
        // looking at the current instruction, while also maintaining
        // a separate iterator giving us the next instruction (if there
        // is one.
        let current_inst_iter = instructions.iter();
        let mut next_inst_iter = current_inst_iter.clone();
        // Skip the first one so that we're actually working with the next one.
        next_inst_iter.next();
        let mut current_block_idx = self.entry_block.unwrap();
        for current_inst in current_inst_iter {
            // Add this instruction to the current block
            if let Some(current_block) = self.graph.node_weight_mut(current_block_idx) {
                current_block.instructions.push(current_inst);
            }
            if let Some(next_inst) = next_inst_iter.next() {
                // Does the next instruction begin a basic block?
                let next_block_idx =
                    *self.block_finder.get(&next_inst.address()).unwrap_or(&current_block_idx);
                // If we're at a block boundary, create an edge between the
                // current and next blocks. The type of the edge is determined
                // by looking at the current instruction.
                if next_block_idx != current_block_idx {
                    self.build_edge(current_block_idx, next_block_idx, current_inst);
                    current_block_idx = next_block_idx;
                }
            } else {
                // No next instruction, so we're at the end.
                // Do we want to record this exit anywhere?
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use instruction::Instruction;
    use petgraph::EdgeDirection;
    use super::ControlFlowGraph;
    use tests::*;

    #[test]
    fn construct() {
        let insts: Vec<TestInstruction> = vec![];
        let cfg = ControlFlowGraph::new(&insts);
        assert!(cfg.entry_block.is_none());
        assert_eq!(cfg.graph.node_count(), 0);
    }

    #[test]
    fn build_one_basic_block() {
        let insts: Vec<Instruction> = vec![TestInstruction::new(0, Opcode::Add),
                                           TestInstruction::new(1, Opcode::Add),
                                           TestInstruction::new(2, Opcode::Ret)];
        let cfg = ControlFlowGraph::new(&insts);
        assert!(cfg.entry_block.is_some());
        assert_eq!(cfg.graph.node_count(), 1);

        let inbound = cfg.graph.externals(EdgeDirection::Incoming);
        assert_eq!(inbound.count(), 1);

        let outbound = cfg.graph.externals(EdgeDirection::Outgoing);
        assert_eq!(outbound.count(), 1);
    }
}
<commit_msg>Fix tests from last change.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use address::Address;
use basicblock::{BasicBlock, BasicBlockEdge, EdgeType};
use instruction::Instruction;
use petgraph::graph::{Graph, NodeIndex};
use std::collections::BTreeMap;

/// A [control flow graph].
///
/// [control flow graph]: https://en.wikipedia.org/wiki/Control_flow_graph
pub struct ControlFlowGraph<'f, I: 'f + Instruction> {
    /// The [`Graph`] that stores the actual ControlFlowGraph
    ///
    /// [`Graph`]: ../petgraph/graph/struct.Graph.html
    pub graph: Graph<BasicBlock<'f, I>, BasicBlockEdge>,
    /// The [`NodeIndex`] for the entry [`BasicBlock`] for this function.
    ///
    /// [`BasicBlock`]: struct.BasicBlock.html
    /// [`NodeIndex`]: ../petgraph/graph/struct.NodeIndex.html
    pub entry_block: Option<NodeIndex>,
    /// Map an [address] to the corresponding [basic block].
    ///
    /// [address]: struct.Address.html
    /// [basic block]: struct.BasicBlock.html
    pub block_finder: BTreeMap<Address, NodeIndex>,
}

impl<'f, I: Instruction> ControlFlowGraph<'f, I> {
    /// Build the ControlFlowGraph from the [`instructions`].
    ///
    /// This is conducted in a 2 step process:
    ///
    /// * First, each instruction is examined to identify block boundaries.
    /// * Then, we go through each instruction again, looking for the
    ///   previously identified block boundaries and build the edges.
    ///
    /// This two step process prevents us from having to construct and then
    /// subsequently split blocks as we find backward edges.
    ///
    /// [`instructions`]: trait.Instruction.html
    pub fn new(instructions: &'f [I]) -> Self {
        let mut cfg = ControlFlowGraph {
            graph: Graph::new(),
            entry_block: None,
            block_finder: BTreeMap::new(),
        };
        if !instructions.is_empty() {
            cfg.identify_blocks(instructions);
            cfg.build_edges(instructions);
        }
        cfg
    }

    /// Identify basic blocks by their boundaries.
    ///
    /// Inspect each instruction to see if it is a 'leader' or the start of
    /// a new basic block. An instruction is a leader if:
    ///
    /// * It is the first instruction in the basic block.
    /// * It comes after a branch of any sort. We identify these as things
    ///   for which `Instruction::is_block_terminator` returns `true`.
    /// * It is the target of a jump (conditional or unconditional) within
    ///   the function.
    fn identify_blocks(&mut self, instructions: &[I]) {
        let start_addr = instructions[0].address();
        let end_addr = instructions.last().map(|i| i.address()).unwrap();
        let mut next_is_leader: bool = true;
        for inst in instructions {
            if next_is_leader {
                let idx = self.graph.add_node(BasicBlock::new(inst.address()));
                self.block_finder.insert(inst.address(), idx);
                next_is_leader = false;
            }
            if inst.is_block_terminator() {
                if let Some(target_addr) = inst.target_address() {
                    if !self.block_finder.contains_key(&target_addr) &&
                       target_addr >= start_addr && target_addr <= end_addr {
                        let idx = self.graph.add_node(BasicBlock::new(target_addr));
                        self.block_finder.insert(target_addr, idx);
                    }
                }
                // The next instruction, if any, will be the start of a new block.
                next_is_leader = true;
            }
        }
        self.entry_block = Some(*self.block_finder.get(&instructions[0].address()).unwrap());
    }

    /// Build an edge between 2 basic blocks.
    fn build_edge(&mut self,
                  current_block_idx: NodeIndex,
                  next_block_idx: NodeIndex,
                  current_inst: &I) {
        if current_inst.is_local_conditional_jump() {
            // We have one edge for the jump target and one for the fallthrough.
            // We jump through some hoops here to keep the borrow checker happy.
            if let Some(target_addr) = current_inst.target_address() {
                if let Some(target_block_idx) = self.block_finder.get(&target_addr) {
                    let edge = BasicBlockEdge { edge_type: EdgeType::ConditionalTaken };
                    self.graph.add_edge(current_block_idx, *target_block_idx, edge);
                }
                let edge = BasicBlockEdge { edge_type: EdgeType::ConditionalFallthrough };
                self.graph.add_edge(current_block_idx, next_block_idx, edge);
            }
        } else if current_inst.is_local_jump() || current_inst.is_call() {
            let edge = BasicBlockEdge { edge_type: EdgeType::Unconditional };
            self.graph.add_edge(current_block_idx, next_block_idx, edge);
        } else if current_inst.is_return() {
            // Do we want to record this exit anywhere?
        }
    }

    /// Build edges after having identified the basic blocks.
    ///
    /// After the basic blocks have been identified, we can go back and
    /// connect the basic blocks with their appropriate edges.
    ///
    /// We do this by iterating through the instructions looking for
    /// boundaries between the basic blocks and then setting up the
    /// new edges.
    fn build_edges(&mut self, instructions: &'f [I]) {
        // Here, we're going to walk through the instructions again,
        // looking at the current instruction, while also maintaining
        // a separate iterator giving us the next instruction (if there
        // is one.
        let current_inst_iter = instructions.iter();
        let mut next_inst_iter = current_inst_iter.clone();
        // Skip the first one so that we're actually working with the next one.
        next_inst_iter.next();
        let mut current_block_idx = self.entry_block.unwrap();
        for current_inst in current_inst_iter {
            // Add this instruction to the current block
            if let Some(current_block) = self.graph.node_weight_mut(current_block_idx) {
                current_block.instructions.push(current_inst);
            }
            if let Some(next_inst) = next_inst_iter.next() {
                // Does the next instruction begin a basic block?
                let next_block_idx =
                    *self.block_finder.get(&next_inst.address()).unwrap_or(&current_block_idx);
                // If we're at a block boundary, create an edge between the
                // current and next blocks. The type of the edge is determined
                // by looking at the current instruction.
                if next_block_idx != current_block_idx {
                    self.build_edge(current_block_idx, next_block_idx, current_inst);
                    current_block_idx = next_block_idx;
                }
            } else {
                // No next instruction, so we're at the end.
                // Do we want to record this exit anywhere?
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use petgraph::EdgeDirection;
    use super::ControlFlowGraph;
    use tests::*;

    #[test]
    fn construct() {
        let insts: Vec<TestInstruction> = vec![];
        let cfg = ControlFlowGraph::new(&insts);
        assert!(cfg.entry_block.is_none());
        assert_eq!(cfg.graph.node_count(), 0);
    }

    #[test]
    fn build_one_basic_block() {
        let insts = vec![TestInstruction::new(0, Opcode::Add),
                         TestInstruction::new(1, Opcode::Add),
                         TestInstruction::new(2, Opcode::Ret)];
        let cfg = ControlFlowGraph::new(&insts);
        assert!(cfg.entry_block.is_some());
        assert_eq!(cfg.graph.node_count(), 1);

        let inbound = cfg.graph.externals(EdgeDirection::Incoming);
        assert_eq!(inbound.count(), 1);

        let outbound = cfg.graph.externals(EdgeDirection::Outgoing);
        assert_eq!(outbound.count(), 1);
    }
}
<|endoftext|>


<commit_before>//! Generic array are commonly used as a return value for hash digests, so
//! it's a good idea to allow to hexlify them easily. This module implements
//! `std::fmt::LowerHex` and `std::fmt::UpperHex` traits.
//!
//! Example:
//!
//! ```rust
//! # #[macro_use]
//! # extern crate generic_array;
//! # extern crate typenum;
//! # fn main() {
//! let array = arr![u8; 10, 20, 30];
//! assert_eq!(format!("{:x}", array), "0a141e");
//! # }
//! ```
//!
use std::fmt;
use std::str;
use std::ops::Add;
use typenum::*;
use {GenericArray, ArrayLength};

static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";
static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";

impl<T: ArrayLength<u8>> fmt::LowerHex for GenericArray<u8, T>
    where T: Add<T>,
          <T as Add<T>>::Output: ArrayLength<u8>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let max_digits = f.precision().unwrap_or(self.len());
        if T::to_usize() < 1024 {
            // For small arrays use a stack allocated
            // buffer of 2x number of bytes
            let mut res = GenericArray::<u8, Sum<T, T>>::default();
            for (i, c) in self.iter().take(max_digits).enumerate() {
                res[i * 2] = LOWER_CHARS[(c >> 4) as usize];
                res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
            }
            f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits * 2]) })?;
        } else {
            // For large array use chunks of up to 1024 bytes (2048 hex chars)
            let mut buf = [0u8; 2048];
            for chunk in self[..max_digits].chunks(1024) {
                for (i, c) in chunk.iter().enumerate() {
                    buf[i * 2] = LOWER_CHARS[(c >> 4) as usize];
                    buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
                }
                f.write_str(unsafe { str::from_utf8_unchecked(&buf[..chunk.len() * 2]) })?;
            }
        }
        Ok(())
    }
}

impl<T: ArrayLength<u8>> fmt::UpperHex for GenericArray<u8, T>
    where T: Add<T>,
          <T as Add<T>>::Output: ArrayLength<u8>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let max_digits = f.precision().unwrap_or(self.len());
        if T::to_usize() < 1024 {
            // For small arrays use a stack allocated
            // buffer of 2x number of bytes
            let mut res = GenericArray::<u8, Sum<T, T>>::default();
            for (i, c) in self.iter().take(max_digits).enumerate() {
                res[i * 2] = UPPER_CHARS[(c >> 4) as usize];
                res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
            }
            f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits * 2]) })?;
        } else {
            // For large array use chunks of up to 1024 bytes (2048 hex chars)
            let mut buf = [0u8; 2048];
            for chunk in self[..max_digits].chunks(1024) {
                for (i, c) in chunk.iter().enumerate() {
                    buf[i * 2] = UPPER_CHARS[(c >> 4) as usize];
                    buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
                }
                f.write_str(unsafe { str::from_utf8_unchecked(&buf[..chunk.len() * 2]) })?;
            }
        }
        Ok(())
    }
}
<commit_msg>Change std to core in new code<commit_after>//! Generic array are commonly used as a return value for hash digests, so
//! it's a good idea to allow to hexlify them easily. This module implements
//! `std::fmt::LowerHex` and `std::fmt::UpperHex` traits.
//!
//! Example:
//!
//! ```rust
//! # #[macro_use]
//! # extern crate generic_array;
//! # extern crate typenum;
//! # fn main() {
//! let array = arr![u8; 10, 20, 30];
//! assert_eq!(format!("{:x}", array), "0a141e");
//! # }
//! ```
//!
use core::fmt;
use core::str;
use core::ops::Add;
use typenum::*;
use {GenericArray, ArrayLength};

static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";
static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";

impl<T: ArrayLength<u8>> fmt::LowerHex for GenericArray<u8, T>
    where T: Add<T>,
          <T as Add<T>>::Output: ArrayLength<u8>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let max_digits = f.precision().unwrap_or(self.len());
        if T::to_usize() < 1024 {
            // For small arrays use a stack allocated
            // buffer of 2x number of bytes
            let mut res = GenericArray::<u8, Sum<T, T>>::default();
            for (i, c) in self.iter().take(max_digits).enumerate() {
                res[i * 2] = LOWER_CHARS[(c >> 4) as usize];
                res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
            }
            f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits * 2]) })?;
        } else {
            // For large array use chunks of up to 1024 bytes (2048 hex chars)
            let mut buf = [0u8; 2048];
            for chunk in self[..max_digits].chunks(1024) {
                for (i, c) in chunk.iter().enumerate() {
                    buf[i * 2] = LOWER_CHARS[(c >> 4) as usize];
                    buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
                }
                f.write_str(unsafe { str::from_utf8_unchecked(&buf[..chunk.len() * 2]) })?;
            }
        }
        Ok(())
    }
}

impl<T: ArrayLength<u8>> fmt::UpperHex for GenericArray<u8, T>
    where T: Add<T>,
          <T as Add<T>>::Output: ArrayLength<u8>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let max_digits = f.precision().unwrap_or(self.len());
        if T::to_usize() < 1024 {
            // For small arrays use a stack allocated
            // buffer of 2x number of bytes
            let mut res = GenericArray::<u8, Sum<T, T>>::default();
            for (i, c) in self.iter().take(max_digits).enumerate() {
                res[i * 2] = UPPER_CHARS[(c >> 4) as usize];
                res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
            }
            f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits * 2]) })?;
        } else {
            // For large array use chunks of up to 1024 bytes (2048 hex chars)
            let mut buf = [0u8; 2048];
            for chunk in self[..max_digits].chunks(1024) {
                for (i, c) in chunk.iter().enumerate() {
                    buf[i * 2] = UPPER_CHARS[(c >> 4) as usize];
                    buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
                }
                f.write_str(unsafe { str::from_utf8_unchecked(&buf[..chunk.len() * 2]) })?;
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::path::MAIN_SEPARATOR;
use std::process::Command;

use clap::{App, Arg, Error};

#[derive(Debug)]
pub struct Args {
    pub cmd: String,
    pub paths: Vec<String>,
    pub filters: Vec<String>,
    pub ignores: Vec<String>,
    pub clear_screen: bool,
    pub signal: Option<String>,
    pub restart: bool,
    pub debounce: u64,
    pub debug: bool,
    pub run_initially: bool,
    pub no_shell: bool,
    pub no_vcs_ignore: bool,
    pub once: bool,
    pub poll: bool,
    pub poll_interval: u32,
}

#[cfg(target_family = "windows")]
pub fn clear_screen() {
    let _ = Command::new("cmd").arg("/c").arg("cls").status();
}

#[cfg(target_family = "unix")]
pub fn clear_screen() {
    let _ = Command::new("tput").arg("reset").status();
}

#[allow(unknown_lints)]
#[allow(or_fun_call)]
pub fn get_args() -> Args {
    let args = App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("command")
                 .help("Command to execute")
                 .multiple(true)
                 .required(true))
        .arg(Arg::with_name("extensions")
                 .help("Comma-separated list of file extensions to watch (js,css,html)")
                 .short("e")
                 .long("exts")
                 .takes_value(true))
        .arg(Arg::with_name("path")
                 .help("Watch a specific directory")
                 .short("w")
                 .long("watch")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true))
        .arg(Arg::with_name("clear")
                 .help("Clear screen before executing command")
                 .short("c")
                 .long("clear"))
        .arg(Arg::with_name("restart")
                 .help("Restart the process if it's still running")
                 .short("r")
                 .long("restart"))
        .arg(Arg::with_name("signal")
                 .help("Send signal to process upon changes, e.g. SIGHUP")
                 .short("s")
                 .long("signal")
                 .takes_value(true)
                 .number_of_values(1)
                 .value_name("signal"))
        .arg(Arg::with_name("kill")
                 .help("Send SIGKILL to child processes (deprecated, use -s SIGKILL instead)")
                 .short("k")
                 .long("kill"))
        .arg(Arg::with_name("debounce")
                 .help("Set the timeout between detected change and command execution, defaults to 500ms")
                 .takes_value(true)
                 .value_name("milliseconds")
                 .short("d")
                 .long("debounce"))
        .arg(Arg::with_name("verbose")
                 .help("Print debugging messages to stderr")
                 .short("v")
                 .long("verbose"))
        .arg(Arg::with_name("filter")
                 .help("Ignore all modifications except those matching the pattern")
                 .short("f")
                 .long("filter")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("ignore")
                 .help("Ignore modifications to paths matching the pattern")
                 .short("i")
                 .long("ignore")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
                 .help("Skip auto-loading of .gitignore files for filtering")
                 .long("no-vcs-ignore"))
        .arg(Arg::with_name("no-default-ignore")
                 .help("Skip auto-ignoring of commonly ignored globs")
                 .long("no-default-ignore"))
        .arg(Arg::with_name("postpone")
                 .help("Wait until first change to execute command")
                 .short("p")
                 .long("postpone"))
        .arg(Arg::with_name("poll")
                 .help("Forces polling mode")
                 .long("force-poll")
                 .value_name("interval"))
        .arg(Arg::with_name("no-shell")
                 .help("Do not wrap command in 'sh -c' resp. 'cmd.exe /C'")
                 .short("n")
                 .long("no-shell"))
        .arg(Arg::with_name("once").short("1").hidden(true))
        .get_matches();

    let cmd = values_t!(args.values_of("command"), String)
        .unwrap()
        .join(" ");
    let paths = values_t!(args.values_of("path"), String).unwrap_or(vec![String::from(".")]);

    // Treat --kill as --signal SIGKILL (for compatibility with older syntax)
    let signal = if args.is_present("kill") {
        Some("SIGKILL".to_string())
    } else {
        // Convert Option<&str> to Option<String>
        args.value_of("signal").map(str::to_string)
    };

    let mut filters = values_t!(args.values_of("filter"), String).unwrap_or(vec![]);

    if let Some(extensions) = args.values_of("extensions") {
        for exts in extensions {
            filters.extend(exts.split(',')
                               .filter(|ext| !ext.is_empty())
                               .map(|ext| format!("*.{}", ext.replace(".", ""))));

        }
    }

    let mut ignores = vec![];
    let default_ignores = vec![format!("**{}.DS_Store", MAIN_SEPARATOR),
                               String::from("*.pyc"),
                               String::from("#*#"),
                               String::from(".#*"),
                               String::from(".*.sw?"),
                               String::from(".*.sw?x"),
                               format!("**{}.git{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
                               format!("**{}.hg{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
                               format!("**{}.svn{}**", MAIN_SEPARATOR, MAIN_SEPARATOR)];

    if args.occurrences_of("no-default-ignore") == 0 {
        ignores.extend(default_ignores)
    };
    ignores.extend(values_t!(args.values_of("ignore"), String).unwrap_or(vec![]));

    let poll_interval = if args.occurrences_of("poll") > 0 {
        value_t!(args.value_of("poll"), u32).unwrap_or_else(|e| e.exit())
    } else {
        1000
    };

    let debounce = if args.occurrences_of("debounce") > 0 {
        value_t!(args.value_of("debounce"), u64).unwrap_or_else(|e| e.exit())
     } else {
         500
     };

    if signal.is_some() && args.is_present("postpone") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--postpone and --signal are mutually exclusive".to_string())
            .exit();
    }

    if signal.is_some() && args.is_present("kill") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--kill and --signal is ambiguous.\n       Hint: Use only '--signal SIGKILL' without --kill".to_string())
            .exit();
    }

    Args {
        cmd: cmd,
        paths: paths,
        filters: filters,
        ignores: ignores,
        signal: signal,
        clear_screen: args.is_present("clear"),
        restart: args.is_present("restart"),
        debounce: debounce,
        debug: args.is_present("verbose"),
        run_initially: !args.is_present("postpone"),
        no_shell: args.is_present("no-shell"),
        no_vcs_ignore: args.is_present("no-vcs-ignore"),
        once: args.is_present("once"),
        poll: args.occurrences_of("poll") > 0,
        poll_interval: poll_interval,
    }
}
<commit_msg>Add .pyo to the Python temporary file ignore<commit_after>use std::path::MAIN_SEPARATOR;
use std::process::Command;

use clap::{App, Arg, Error};

#[derive(Debug)]
pub struct Args {
    pub cmd: String,
    pub paths: Vec<String>,
    pub filters: Vec<String>,
    pub ignores: Vec<String>,
    pub clear_screen: bool,
    pub signal: Option<String>,
    pub restart: bool,
    pub debounce: u64,
    pub debug: bool,
    pub run_initially: bool,
    pub no_shell: bool,
    pub no_vcs_ignore: bool,
    pub once: bool,
    pub poll: bool,
    pub poll_interval: u32,
}

#[cfg(target_family = "windows")]
pub fn clear_screen() {
    let _ = Command::new("cmd").arg("/c").arg("cls").status();
}

#[cfg(target_family = "unix")]
pub fn clear_screen() {
    let _ = Command::new("tput").arg("reset").status();
}

#[allow(unknown_lints)]
#[allow(or_fun_call)]
pub fn get_args() -> Args {
    let args = App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("command")
                 .help("Command to execute")
                 .multiple(true)
                 .required(true))
        .arg(Arg::with_name("extensions")
                 .help("Comma-separated list of file extensions to watch (js,css,html)")
                 .short("e")
                 .long("exts")
                 .takes_value(true))
        .arg(Arg::with_name("path")
                 .help("Watch a specific directory")
                 .short("w")
                 .long("watch")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true))
        .arg(Arg::with_name("clear")
                 .help("Clear screen before executing command")
                 .short("c")
                 .long("clear"))
        .arg(Arg::with_name("restart")
                 .help("Restart the process if it's still running")
                 .short("r")
                 .long("restart"))
        .arg(Arg::with_name("signal")
                 .help("Send signal to process upon changes, e.g. SIGHUP")
                 .short("s")
                 .long("signal")
                 .takes_value(true)
                 .number_of_values(1)
                 .value_name("signal"))
        .arg(Arg::with_name("kill")
                 .help("Send SIGKILL to child processes (deprecated, use -s SIGKILL instead)")
                 .short("k")
                 .long("kill"))
        .arg(Arg::with_name("debounce")
                 .help("Set the timeout between detected change and command execution, defaults to 500ms")
                 .takes_value(true)
                 .value_name("milliseconds")
                 .short("d")
                 .long("debounce"))
        .arg(Arg::with_name("verbose")
                 .help("Print debugging messages to stderr")
                 .short("v")
                 .long("verbose"))
        .arg(Arg::with_name("filter")
                 .help("Ignore all modifications except those matching the pattern")
                 .short("f")
                 .long("filter")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("ignore")
                 .help("Ignore modifications to paths matching the pattern")
                 .short("i")
                 .long("ignore")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
                 .help("Skip auto-loading of .gitignore files for filtering")
                 .long("no-vcs-ignore"))
        .arg(Arg::with_name("no-default-ignore")
                 .help("Skip auto-ignoring of commonly ignored globs")
                 .long("no-default-ignore"))
        .arg(Arg::with_name("postpone")
                 .help("Wait until first change to execute command")
                 .short("p")
                 .long("postpone"))
        .arg(Arg::with_name("poll")
                 .help("Forces polling mode")
                 .long("force-poll")
                 .value_name("interval"))
        .arg(Arg::with_name("no-shell")
                 .help("Do not wrap command in 'sh -c' resp. 'cmd.exe /C'")
                 .short("n")
                 .long("no-shell"))
        .arg(Arg::with_name("once").short("1").hidden(true))
        .get_matches();

    let cmd = values_t!(args.values_of("command"), String)
        .unwrap()
        .join(" ");
    let paths = values_t!(args.values_of("path"), String).unwrap_or(vec![String::from(".")]);

    // Treat --kill as --signal SIGKILL (for compatibility with older syntax)
    let signal = if args.is_present("kill") {
        Some("SIGKILL".to_string())
    } else {
        // Convert Option<&str> to Option<String>
        args.value_of("signal").map(str::to_string)
    };

    let mut filters = values_t!(args.values_of("filter"), String).unwrap_or(vec![]);

    if let Some(extensions) = args.values_of("extensions") {
        for exts in extensions {
            filters.extend(exts.split(',')
                               .filter(|ext| !ext.is_empty())
                               .map(|ext| format!("*.{}", ext.replace(".", ""))));

        }
    }

    let mut ignores = vec![];
    let default_ignores = vec![format!("**{}.DS_Store", MAIN_SEPARATOR),
                               String::from("*.py[co]"),
                               String::from("#*#"),
                               String::from(".#*"),
                               String::from(".*.sw?"),
                               String::from(".*.sw?x"),
                               format!("**{}.git{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
                               format!("**{}.hg{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
                               format!("**{}.svn{}**", MAIN_SEPARATOR, MAIN_SEPARATOR)];

    if args.occurrences_of("no-default-ignore") == 0 {
        ignores.extend(default_ignores)
    };
    ignores.extend(values_t!(args.values_of("ignore"), String).unwrap_or(vec![]));

    let poll_interval = if args.occurrences_of("poll") > 0 {
        value_t!(args.value_of("poll"), u32).unwrap_or_else(|e| e.exit())
    } else {
        1000
    };

    let debounce = if args.occurrences_of("debounce") > 0 {
        value_t!(args.value_of("debounce"), u64).unwrap_or_else(|e| e.exit())
     } else {
         500
     };

    if signal.is_some() && args.is_present("postpone") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--postpone and --signal are mutually exclusive".to_string())
            .exit();
    }

    if signal.is_some() && args.is_present("kill") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--kill and --signal is ambiguous.\n       Hint: Use only '--signal SIGKILL' without --kill".to_string())
            .exit();
    }

    Args {
        cmd: cmd,
        paths: paths,
        filters: filters,
        ignores: ignores,
        signal: signal,
        clear_screen: args.is_present("clear"),
        restart: args.is_present("restart"),
        debounce: debounce,
        debug: args.is_present("verbose"),
        run_initially: !args.is_present("postpone"),
        no_shell: args.is_present("no-shell"),
        no_vcs_ignore: args.is_present("no-vcs-ignore"),
        once: args.is_present("once"),
        poll: args.occurrences_of("poll") > 0,
        poll_interval: poll_interval,
    }
}
<|endoftext|>


<commit_before>use mmu::{Descriptor, TableDescriptor};
use core::mem::size_of;
use notex::Notex;

const IDT_COUNT: usize = 256;

#[no_mangle]
pub static idtDesc: Notex<TableDescriptor> =
    notex!(TableDescriptor{ limit: 0 , base: 0});

#[allow(non_upper_case_globals)]
static IDT_NOTEX: Notex<[Descriptor; IDT_COUNT]> =
    notex!([ Descriptor { f0: 0, f1: 0 } ; IDT_COUNT]);

extern {
    fn lidt2();
}

pub fn init() {
    unsafe {
        let idt = IDT_NOTEX.lock();
        let idt_addr = &(idt[0]) as *const Descriptor as usize;
        let mut idt_desc = idtDesc.lock();
        idt_desc.limit = (size_of::<Descriptor>() * IDT_COUNT - 1) as u16;
        idt_desc.base = idt_addr as u32;
        lidt2();
    }
}

pub fn register_interrupt(number: usize, handler: unsafe extern fn()) {
    let mut idt = IDT_NOTEX.lock();
    idt[number].set_trap_descriptor(0x08, handler as u32, 0);
}
<commit_msg>Minor cleanup<commit_after>use mmu::{Descriptor, TableDescriptor};
use core::mem::size_of;
use notex::Notex;

const IDT_COUNT: usize = 256;

#[no_mangle]
#[allow(non_upper_case_globals)]
pub static idtDesc: Notex<TableDescriptor> =
    notex!(TableDescriptor{ limit: 0 , base: 0});

static IDT_NOTEX: Notex<[Descriptor; IDT_COUNT]> =
    notex!([ Descriptor { f0: 0, f1: 0 } ; IDT_COUNT]);

extern {
    fn lidt2();
}

pub fn init() {
    unsafe {
        let idt = IDT_NOTEX.lock();
        let idt_addr = &(idt[0]) as *const Descriptor as usize;
        let mut idt_desc = idtDesc.lock();
        idt_desc.limit = (size_of::<Descriptor>() * IDT_COUNT - 1) as u16;
        idt_desc.base = idt_addr as u32;
        lidt2();
    }
}

pub fn register_interrupt(number: usize, handler: unsafe extern fn()) {
    let mut idt = IDT_NOTEX.lock();
    idt[number].set_trap_descriptor(0x08, handler as u32, 0);
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::{result, thread, time};
use std::cell::{RefCell, RefMut};

use reqwest::{Response};
//use serde_json;

use errors::Error;
use client::MatrixClient;
use matrix_types::Event;

type Result<T> = result::Result<T, Error>;

#[derive(Clone)]
pub struct RoomEvent<'a> {
    pub room_id: &'a str,
    pub raw_event: Event,
}

pub struct Bot <'a, 'b> {
    client: RefCell<&'b mut MatrixClient>,
    root_services: Vec<&'a str>,
    all_services: HashMap<&'a str, RefCell<Box<Node<'a>>>>,
}

impl<'a, 'b> Bot<'a, 'b> {
    pub fn new(client: &'b mut MatrixClient) -> Self {
        Bot {
            client: RefCell::new(client),
            root_services: Vec::new(),
            all_services: HashMap::new(),
        }
    }

    pub fn join(&self, room_id: &str) -> Result<Response> {
        self.client.borrow().join(room_id)
    }

    pub fn join_public(&self, room_id: &str) -> Result<Response> {
        let pub_room = self.client.borrow().get_public_room_id(room_id);

        match pub_room {
            Some(id) => self.join(&id),
            None => Err("Could not join invalid room.".into()),
        }
    }

    pub fn leave(&self, room_id: &str) -> Result<Response> {
        self.client.borrow().leave(room_id)
    }

    pub fn leave_public(&self, room_name: &str) -> Result<Response> {
        let pub_room = self.client.borrow().get_public_room_id(room_name);

        match pub_room {
            Some(id) => self.leave(&id),
            None => Err(format!("Could not find room: {}", room_name).into()),
        }
    }

    pub fn say(&self, room_id: &str, message: &str) -> Result<Response> {
        self.client.borrow_mut().send_msg(room_id, message)
    }

    pub fn reply(&self, event: &RoomEvent, message: &str) -> Result<Response> {
        self.say(event.room_id, message)
    }

    pub fn kick(&self, room_id: &str, user_id: &str, reason: Option<&str>) {
        self.client.borrow().kick(room_id, user_id, reason);
    }

    /*
    pub fn action(&self, room_id: &str, action: &str) {
    }

    pub fn set_name(&self, name: &str) {
    }
    */

    pub fn register_service(&mut self,
                            name: &'a str,
                            parent: Option<&'a str>,
                            mut service: Box<Node<'a>>) -> Option<&'a str> {
        match parent {
            Some(p) => {
                self.all_services.get_mut(p).expect("Invalid parent node")
                    .borrow_mut().register_child(name)
            },
            None => self.root_services.push(name),
        };

        service.on_load();

        self.all_services.insert(name, RefCell::new(service));

        Some(name)
    }

    pub fn get_service(&self, name: &str) -> RefMut<Box<Node<'a>>> {
        self.all_services.get(name).unwrap().borrow_mut()
    }

    pub fn propagate_event(&self, event: &RoomEvent) {
        for service in &self.root_services {
            self.all_services.get(service).unwrap()
                .borrow_mut().handle(self, event.clone());
        }
    }

    pub fn run(&mut self, initial_rooms: &Vec<String>) {
        for room in initial_rooms {
            if let Some(rid) = self.client.borrow().get_public_room_id(room) {
                println!("Joining {} id: {}", &room, &rid);
                self.join(&rid);
            } else {
                println!("Could not join room {}", &room);
            }
        }

        let mut next_batch: String = self.client.borrow().sync(None).unwrap().next_batch;

        let delay = time::Duration::from_millis(500);

        loop {
            match self.client.borrow().sync(Some(&next_batch)) {
                Ok(sync_data) => {
                    /*
                    if let Ok(x) = serde_json::to_string_pretty(&sync_data) {
                        println!("{}", x);
                    }
                    */

                    for (room_id, room) in sync_data.rooms.join {
                        for raw_event in &room.timeline.events {
                            self.propagate_event(
                                &RoomEvent{
                                    room_id: &room_id,
                                    raw_event: raw_event.clone()
                                });
                        }
                    }

                    for (room_id, room) in sync_data.rooms.invite {
                        for raw_event in &room.invite_state.events {
                            self.propagate_event(
                                &RoomEvent{
                                    room_id: &room_id,
                                    raw_event: raw_event.clone()
                                });
                        }
                    }

                    for (room_id, room) in sync_data.rooms.leave {
                        for raw_event in &room.timeline.events {
                            self.propagate_event(
                                &RoomEvent{
                                    room_id: &room_id,
                                    raw_event: raw_event.clone()
                                });
                        }
                    }

                    next_batch = sync_data.next_batch;
                },
                Err(e) => {
                    println!("Error: {:?}", e);
                }
            }

            thread::sleep(delay);
        }
    }
}

pub trait Node<'a> {
    fn children(&self) -> Option<&Vec<&'a str>> {
        None
    }

    fn register_child(&mut self, name: &'a str) {
    }

    fn propagate_event(&self, bot: &Bot, event: &RoomEvent) {
        if let Some(children) = self.children() {
            for child in children {
                bot.get_service(child).handle(bot, event.clone());
            }
        }
    }

    fn handle(&mut self, bot: &Bot, event: RoomEvent) {
        self.propagate_event(bot, &event);
    }

    fn on_load(&mut self) { }

    fn on_exit(&self) { }
}
<commit_msg>Fix regression due to borrow being held by match<commit_after>use std::collections::HashMap;
use std::{result, thread, time};
use std::cell::{RefCell, RefMut};

use reqwest::{Response};
//use serde_json;

use errors::Error;
use client::MatrixClient;
use matrix_types::Event;

type Result<T> = result::Result<T, Error>;

#[derive(Clone)]
pub struct RoomEvent<'a> {
    pub room_id: &'a str,
    pub raw_event: Event,
}

pub struct Bot <'a, 'b> {
    client: RefCell<&'b mut MatrixClient>,
    root_services: Vec<&'a str>,
    all_services: HashMap<&'a str, RefCell<Box<Node<'a>>>>,
}

impl<'a, 'b> Bot<'a, 'b> {
    pub fn new(client: &'b mut MatrixClient) -> Self {
        Bot {
            client: RefCell::new(client),
            root_services: Vec::new(),
            all_services: HashMap::new(),
        }
    }

    pub fn join(&self, room_id: &str) -> Result<Response> {
        self.client.borrow().join(room_id)
    }

    pub fn join_public(&self, room_id: &str) -> Result<Response> {
        let pub_room = self.client.borrow().get_public_room_id(room_id);

        match pub_room {
            Some(id) => self.join(&id),
            None => Err("Could not join invalid room.".into()),
        }
    }

    pub fn leave(&self, room_id: &str) -> Result<Response> {
        self.client.borrow().leave(room_id)
    }

    pub fn leave_public(&self, room_name: &str) -> Result<Response> {
        let pub_room = self.client.borrow().get_public_room_id(room_name);

        match pub_room {
            Some(id) => self.leave(&id),
            None => Err(format!("Could not find room: {}", room_name).into()),
        }
    }

    pub fn say(&self, room_id: &str, message: &str) -> Result<Response> {
        self.client.borrow_mut().send_msg(room_id, message)
    }

    pub fn reply(&self, event: &RoomEvent, message: &str) -> Result<Response> {
        self.say(event.room_id, message)
    }

    pub fn kick(&self, room_id: &str, user_id: &str, reason: Option<&str>) {
        self.client.borrow().kick(room_id, user_id, reason);
    }

    /*
    pub fn action(&self, room_id: &str, action: &str) {
    }

    pub fn set_name(&self, name: &str) {
    }
    */

    pub fn register_service(&mut self,
                            name: &'a str,
                            parent: Option<&'a str>,
                            mut service: Box<Node<'a>>) -> Option<&'a str> {
        match parent {
            Some(p) => {
                self.all_services.get_mut(p).expect("Invalid parent node")
                    .borrow_mut().register_child(name)
            },
            None => self.root_services.push(name),
        };

        service.on_load();

        self.all_services.insert(name, RefCell::new(service));

        Some(name)
    }

    pub fn get_service(&self, name: &str) -> RefMut<Box<Node<'a>>> {
        self.all_services.get(name).unwrap().borrow_mut()
    }

    pub fn propagate_event(&self, event: &RoomEvent) {
        for service in &self.root_services {
            self.all_services.get(service).unwrap()
                .borrow_mut().handle(self, event.clone());
        }
    }

    pub fn run(&mut self, initial_rooms: &Vec<String>) {
        for room in initial_rooms {
            if let Some(rid) = self.client.borrow().get_public_room_id(room) {
                println!("Joining {} id: {}", &room, &rid);
                self.join(&rid);
            } else {
                println!("Could not join room {}", &room);
            }
        }

        let mut next_batch: String = self.client.borrow().sync(None).unwrap().next_batch;

        let delay = time::Duration::from_millis(500);

        loop {
            let sync = self.client.borrow().sync(Some(&next_batch));

            match sync {
                Ok(sync_data) => {
                    /*
                    if let Ok(x) = serde_json::to_string_pretty(&sync_data) {
                        println!("{}", x);
                    }
                    */

                    for (room_id, room) in sync_data.rooms.join {
                        for raw_event in &room.timeline.events {
                            self.propagate_event(
                                &RoomEvent{
                                    room_id: &room_id,
                                    raw_event: raw_event.clone()
                                });
                        }
                    }

                    for (room_id, room) in sync_data.rooms.invite {
                        for raw_event in &room.invite_state.events {
                            self.propagate_event(
                                &RoomEvent{
                                    room_id: &room_id,
                                    raw_event: raw_event.clone()
                                });
                        }
                    }

                    for (room_id, room) in sync_data.rooms.leave {
                        for raw_event in &room.timeline.events {
                            self.propagate_event(
                                &RoomEvent{
                                    room_id: &room_id,
                                    raw_event: raw_event.clone()
                                });
                        }
                    }

                    next_batch = sync_data.next_batch;
                },
                Err(e) => {
                    println!("Error: {:?}", e);
                }
            }

            thread::sleep(delay);
        }
    }
}

pub trait Node<'a> {
    fn children(&self) -> Option<&Vec<&'a str>> {
        None
    }

    fn register_child(&mut self, name: &'a str) {
    }

    fn propagate_event(&self, bot: &Bot, event: &RoomEvent) {
        if let Some(children) = self.children() {
            for child in children {
                bot.get_service(child).handle(bot, event.clone());
            }
        }
    }

    fn handle(&mut self, bot: &Bot, event: RoomEvent) {
        self.propagate_event(bot, &event);
    }

    fn on_load(&mut self) { }

    fn on_exit(&self) { }
}
<|endoftext|>


<commit_before>use bus::{Bus};
use z80::instructions::{Instruction, Src8, Dest8, Src16};
use z80::registers::{Reg8, Reg16, Registers};

#[derive(Debug, Default)]
pub struct Cpu {
    regs: Registers
}

impl Cpu {
    pub fn new() -> Cpu {
        Cpu {
            regs: Registers::new()
        }
    }

    pub fn tick(&mut self, bus: &mut Bus) {
        let mut pc = self.regs.read16(Reg16::PC);
        let instruction = Instruction::decode(|| {
            let word = bus.read_word(pc);
            pc += 1;
            word
        });
        println!("Got instruction: {:?}", instruction);
        self.handle_instruction(bus, instruction);
        self.regs.write16(Reg16::PC, pc);
    }

    fn handle_instruction(&mut self, bus: &mut Bus, instruction: Instruction) {
        use z80::instructions::Instruction::*;
        match instruction {
            Load8(dest, src) => {
                let val = self.read_src8(bus, src);
                self.write_dest8(bus, dest, val);
            }
            Load16(dest, src) => {
                let val = match src {
                    Src16::Imm(val) => val,
                    Src16::Reg(reg) => self.regs.read16(reg),
                };
                self.regs.write16(dest, val);
            }
            Push(reg) => {
                let sp = self.regs.read16(Reg16::SP) - 2;
                self.regs.write16(Reg16::SP, sp);
                bus.write_double(sp, self.regs.read16(reg));
            }
            Pop(reg) => {
                let sp = self.regs.read16(Reg16::SP);
                self.regs.write16(reg, bus.read_double(sp));
                self.regs.write16(Reg16::SP, sp-2);
            }
            Add(src) => {
                self.do_add(bus, src, false);
            }
            AddCarry(src) => {
                let carry = self.regs.carry_flag();
                self.do_add(bus, src, carry);
            }
            Sub(src) => {
                self.do_sub(bus, src, false, true);
            }
            SubCarry(src) => {
                let carry = self.regs.carry_flag();
                self.do_sub(bus, src, carry, true);
            }
            And(src) => {
                let left = self.regs.read8(Reg8::A);
                let right = self.read_src8(bus, src);
                let val = left & right;
                self.regs.write8(Reg8::A, val);
                self.regs.set_zero_flag(val == 0);
                self.regs.set_half_carry_flag(false);
                self.regs.set_sub_flag(false);
                self.regs.set_carry_flag(true);
            }
            Or(src) => {
                let left = self.regs.read8(Reg8::A);
                let right = self.read_src8(bus, src);
                let val = left | right;
                self.regs.write8(Reg8::A, val);
                self.regs.set_zero_flag(val == 0);
                self.regs.set_half_carry_flag(false);
                self.regs.set_sub_flag(false);
                self.regs.set_carry_flag(false);
            }
            Xor(src) => {
                let left = self.regs.read8(Reg8::A);
                let right = self.read_src8(bus, src);
                let val = left ^ right;
                self.regs.write8(Reg8::A, val);
                self.regs.set_zero_flag(val == 0);
                self.regs.set_half_carry_flag(false);
                self.regs.set_sub_flag(false);
                self.regs.set_carry_flag(false);
            }
            Compare(src) => {
                self.do_sub(bus, src, false, true);
            }
            Increment(Dest8::Reg(reg)) => {
                let pre = self.regs.read8(reg);
                let post = pre+1;
                self.regs.write8(reg, post);
                self.regs.set_zero_flag(post == 0);
                self.regs.set_sub_flag(false);
                self.regs.set_half_carry_flag((pre & 0xF) + 1 > 0xF);
            }
            Increment(Dest8::Indir(reg)) => {
                let addr = self.regs.read16(reg);
                let pre = bus.read_word(addr);
                let post = pre+1;
                bus.write_word(addr, post);
                self.regs.set_zero_flag(post == 0);
                self.regs.set_sub_flag(false);
                self.regs.set_half_carry_flag((pre & 0xF) + 1 > 0xF);
            }
            Decrement(Dest8::Reg(reg)) => {
                let pre = self.regs.read8(reg);
                let post = pre-1;
                self.regs.write8(reg, post);
                self.regs.set_zero_flag(post == 0);
                self.regs.set_sub_flag(true);
                self.regs.set_half_carry_flag((pre & 0xF) + 1 > 0xF);
            }
            Decrement(Dest8::Indir(reg)) => {
                let addr = self.regs.read16(reg);
                let pre = bus.read_word(addr);
                let post = pre-1;
                bus.write_word(addr, post);
                self.regs.set_zero_flag(post == 0);
                self.regs.set_sub_flag(true);
                self.regs.set_half_carry_flag((pre & 0xF) < 1);
            }
            DecimalAdjust => {
                let mut a = self.regs.read8(Reg8::A);
                if self.regs.sub_flag() {
                    if self.regs.half_carry_flag() {
                        a -= 0x06;
                    }
                    if self.regs.carry_flag() {
                        a -= 0x60;
                    }
                } else {
                    if (a & 0x0F) > 0x09 || self.regs.half_carry_flag() {
                        a += 0x06;
                    }
                    if a > 0x90 || self.regs.carry_flag() {
                        a += 0x60;
                        self.regs.set_carry_flag(true);
                    }
                }
                self.regs.write8(Reg8::A, a);
                self.regs.set_zero_flag(a == 0);
                self.regs.set_half_carry_flag(false);
            }
            Complement => {
                let val = !self.regs.read8(Reg8::A);
                self.regs.write8(Reg8::A, val);
                self.regs.set_sub_flag(true);
                self.regs.set_half_carry_flag(true);
            }
            _ => panic!("Unimplemented instruction: {:?}", instruction),
        }
        println!("{:?}", self);
    }

    fn read_src8(&self, bus: &mut Bus, src: Src8) -> u8 {
        match src {
            Src8::Imm(val) => val,
            Src8::Reg(reg) => self.regs.read8(reg),
            Src8::Indir(reg) => bus.read_word(self.regs.read16(reg)),
            Src8::Mem(addr) => bus.read_word(addr),
        }
    }

    fn write_dest8(&mut self, bus: &mut Bus, dest: Dest8, val: u8) {
        match dest {
            Dest8::Reg(reg) => self.regs.write8(reg, val),
            Dest8::Indir(reg) => bus.write_word(self.regs.read16(reg), val),
            Dest8::Mem(addr) => bus.write_word(addr, val),
        }
    }

    fn do_add(&mut self, bus: &mut Bus, src: Src8, carry: bool) {
        let left = self.regs.read8(Reg8::A);
        let right = self.read_src8(bus, src);
        let carry = if carry { 1 } else { 0 };
        let val = left + right + carry;
        self.regs.write8(Reg8::A, val);
        self.regs.set_zero_flag(val == 0);
        self.regs.set_sub_flag(false);
        self.regs.set_half_carry_flag(
            ((left & 0xF) + (right & 0xF) + carry) > 0xF);
        self.regs.set_carry_flag(
            ((left as u16) + (right as u16) + (carry as u16)) > 0xFF);
    }

    fn do_sub(&mut self, bus: &mut Bus, src: Src8, carry: bool, store: bool) {
        let left = self.regs.read8(Reg8::A);
        let right = self.read_src8(bus, src);
        let carry = if carry { 1 } else { 0 };
        let val = left - right - carry;
        if store { self.regs.write8(Reg8::A, val); }
        self.regs.set_zero_flag(val == 0);
        self.regs.set_sub_flag(true);
        self.regs.set_half_carry_flag((left & 0xF) < (right & 0xF) + carry);
        self.regs.set_carry_flag(left < right + carry);
    }
}
<commit_msg>Print unknown opcodes in hex<commit_after>use bus::{Bus};
use z80::instructions::{Instruction, Src8, Dest8, Src16};
use z80::registers::{Reg8, Reg16, Registers};

#[derive(Debug, Default)]
pub struct Cpu {
    regs: Registers
}

impl Cpu {
    pub fn new() -> Cpu {
        Cpu {
            regs: Registers::new()
        }
    }

    pub fn tick(&mut self, bus: &mut Bus) {
        let mut pc = self.regs.read16(Reg16::PC);
        let instruction = Instruction::decode(|| {
            let word = bus.read_word(pc);
            pc += 1;
            word
        });
        println!("Got instruction: {:?}", instruction);
        self.handle_instruction(bus, instruction);
        self.regs.write16(Reg16::PC, pc);
    }

    fn handle_instruction(&mut self, bus: &mut Bus, instruction: Instruction) {
        use z80::instructions::Instruction::*;
        match instruction {
            Load8(dest, src) => {
                let val = self.read_src8(bus, src);
                self.write_dest8(bus, dest, val);
            }
            Load16(dest, src) => {
                let val = match src {
                    Src16::Imm(val) => val,
                    Src16::Reg(reg) => self.regs.read16(reg),
                };
                self.regs.write16(dest, val);
            }
            Push(reg) => {
                let sp = self.regs.read16(Reg16::SP) - 2;
                self.regs.write16(Reg16::SP, sp);
                bus.write_double(sp, self.regs.read16(reg));
            }
            Pop(reg) => {
                let sp = self.regs.read16(Reg16::SP);
                self.regs.write16(reg, bus.read_double(sp));
                self.regs.write16(Reg16::SP, sp-2);
            }
            Add(src) => {
                self.do_add(bus, src, false);
            }
            AddCarry(src) => {
                let carry = self.regs.carry_flag();
                self.do_add(bus, src, carry);
            }
            Sub(src) => {
                self.do_sub(bus, src, false, true);
            }
            SubCarry(src) => {
                let carry = self.regs.carry_flag();
                self.do_sub(bus, src, carry, true);
            }
            And(src) => {
                let left = self.regs.read8(Reg8::A);
                let right = self.read_src8(bus, src);
                let val = left & right;
                self.regs.write8(Reg8::A, val);
                self.regs.set_zero_flag(val == 0);
                self.regs.set_half_carry_flag(false);
                self.regs.set_sub_flag(false);
                self.regs.set_carry_flag(true);
            }
            Or(src) => {
                let left = self.regs.read8(Reg8::A);
                let right = self.read_src8(bus, src);
                let val = left | right;
                self.regs.write8(Reg8::A, val);
                self.regs.set_zero_flag(val == 0);
                self.regs.set_half_carry_flag(false);
                self.regs.set_sub_flag(false);
                self.regs.set_carry_flag(false);
            }
            Xor(src) => {
                let left = self.regs.read8(Reg8::A);
                let right = self.read_src8(bus, src);
                let val = left ^ right;
                self.regs.write8(Reg8::A, val);
                self.regs.set_zero_flag(val == 0);
                self.regs.set_half_carry_flag(false);
                self.regs.set_sub_flag(false);
                self.regs.set_carry_flag(false);
            }
            Compare(src) => {
                self.do_sub(bus, src, false, true);
            }
            Increment(Dest8::Reg(reg)) => {
                let pre = self.regs.read8(reg);
                let post = pre+1;
                self.regs.write8(reg, post);
                self.regs.set_zero_flag(post == 0);
                self.regs.set_sub_flag(false);
                self.regs.set_half_carry_flag((pre & 0xF) + 1 > 0xF);
            }
            Increment(Dest8::Indir(reg)) => {
                let addr = self.regs.read16(reg);
                let pre = bus.read_word(addr);
                let post = pre+1;
                bus.write_word(addr, post);
                self.regs.set_zero_flag(post == 0);
                self.regs.set_sub_flag(false);
                self.regs.set_half_carry_flag((pre & 0xF) + 1 > 0xF);
            }
            Decrement(Dest8::Reg(reg)) => {
                let pre = self.regs.read8(reg);
                let post = pre-1;
                self.regs.write8(reg, post);
                self.regs.set_zero_flag(post == 0);
                self.regs.set_sub_flag(true);
                self.regs.set_half_carry_flag((pre & 0xF) + 1 > 0xF);
            }
            Decrement(Dest8::Indir(reg)) => {
                let addr = self.regs.read16(reg);
                let pre = bus.read_word(addr);
                let post = pre-1;
                bus.write_word(addr, post);
                self.regs.set_zero_flag(post == 0);
                self.regs.set_sub_flag(true);
                self.regs.set_half_carry_flag((pre & 0xF) < 1);
            }
            DecimalAdjust => {
                let mut a = self.regs.read8(Reg8::A);
                if self.regs.sub_flag() {
                    if self.regs.half_carry_flag() {
                        a -= 0x06;
                    }
                    if self.regs.carry_flag() {
                        a -= 0x60;
                    }
                } else {
                    if (a & 0x0F) > 0x09 || self.regs.half_carry_flag() {
                        a += 0x06;
                    }
                    if a > 0x90 || self.regs.carry_flag() {
                        a += 0x60;
                        self.regs.set_carry_flag(true);
                    }
                }
                self.regs.write8(Reg8::A, a);
                self.regs.set_zero_flag(a == 0);
                self.regs.set_half_carry_flag(false);
            }
            Complement => {
                let val = !self.regs.read8(Reg8::A);
                self.regs.write8(Reg8::A, val);
                self.regs.set_sub_flag(true);
                self.regs.set_half_carry_flag(true);
            }
            Unknown(opcode) => panic!("Got unknown opcode: 0x{:x}", opcode),
            _ => panic!("Unimplemented instruction: {:?}", instruction),
        }
        println!("{:?}", self);
    }

    fn read_src8(&self, bus: &mut Bus, src: Src8) -> u8 {
        match src {
            Src8::Imm(val) => val,
            Src8::Reg(reg) => self.regs.read8(reg),
            Src8::Indir(reg) => bus.read_word(self.regs.read16(reg)),
            Src8::Mem(addr) => bus.read_word(addr),
        }
    }

    fn write_dest8(&mut self, bus: &mut Bus, dest: Dest8, val: u8) {
        match dest {
            Dest8::Reg(reg) => self.regs.write8(reg, val),
            Dest8::Indir(reg) => bus.write_word(self.regs.read16(reg), val),
            Dest8::Mem(addr) => bus.write_word(addr, val),
        }
    }

    fn do_add(&mut self, bus: &mut Bus, src: Src8, carry: bool) {
        let left = self.regs.read8(Reg8::A);
        let right = self.read_src8(bus, src);
        let carry = if carry { 1 } else { 0 };
        let val = left + right + carry;
        self.regs.write8(Reg8::A, val);
        self.regs.set_zero_flag(val == 0);
        self.regs.set_sub_flag(false);
        self.regs.set_half_carry_flag(
            ((left & 0xF) + (right & 0xF) + carry) > 0xF);
        self.regs.set_carry_flag(
            ((left as u16) + (right as u16) + (carry as u16)) > 0xFF);
    }

    fn do_sub(&mut self, bus: &mut Bus, src: Src8, carry: bool, store: bool) {
        let left = self.regs.read8(Reg8::A);
        let right = self.read_src8(bus, src);
        let carry = if carry { 1 } else { 0 };
        let val = left - right - carry;
        if store { self.regs.write8(Reg8::A, val); }
        self.regs.set_zero_flag(val == 0);
        self.regs.set_sub_flag(true);
        self.regs.set_half_carry_flag((left & 0xF) < (right & 0xF) + carry);
        self.regs.set_carry_flag(left < right + carry);
    }
}
<|endoftext|>


<commit_before>pub struct Core {
	pub pc: u32,
	pub sp: u32,
	pub ir: u16,
	pub dar: [u32; 16],

	// Memory should probably be located elsewhere
	pub mem: [u8; 1024],
}

fn op_illegal(core: &mut Core) {
	panic!("Illegal instruction {:>0irwidth$x} at {:>0pcwidth$x}", core.ir, core.pc-2, irwidth=4, pcwidth=8);
}

fn op_set_d0(core: &mut Core) {
	core.dar[0] = 0xabcd;
}

fn op_set_d1(core: &mut Core) {
	core.dar[1] = 0xbcde;
}

impl Core {
	pub fn new(base: u32) -> Core {
		Core { pc: base, sp: 0, ir: 0, dar: [0u32; 16], mem: [0u8; 1024] }
	}
	pub fn new_mem(base: u32, contents: &[u8]) -> Core {
		let mut m = [0u8; 1024];
		let mut b = base as usize;
		for byte in contents {
			m[b] = *byte;
			b+=1;
		}
		Core { pc: base, sp: 0, ir: 0, dar: [0u32; 16], mem: m }
	}
	pub fn reset(&mut self) {
		self.jump(0);
		self.sp = self.read_imm_32();
		let new_pc = self.read_imm_32();
		self.jump(new_pc);
	}
	pub fn read_imm_32(&mut self) -> u32 {
		let b = self.pc as usize;
		self.pc += 4;
		return ((self.mem[b+0] as u32) << 24
			|   (self.mem[b+1] as u32) << 16
			|   (self.mem[b+2] as u32) <<  8
			|   (self.mem[b+3] as u32) <<  0
			) as u32;
	}
	pub fn read_imm_16(&mut self) -> u16 {
		let b = self.pc as usize;
		self.pc += 2;
		return ((self.mem[b+0] as u16) << 8
			|   (self.mem[b+1] as u16) << 0
			) as u16;
	}
	pub fn jump(&mut self, pc: u32) {
    	self.pc = pc;
	}
	pub fn execute(&mut self) {
		// Read an instruction from PC (increments PC by 2)
		self.ir = self.read_imm_16();
		// Covers all possible IR values (64k entries)
		let mut instruction_handler:[fn(&mut Core);0x10000] = [op_illegal; 0x10000];
		// a few fake instructions
		instruction_handler[0xA] = op_set_d0;
		instruction_handler[0xB] = op_set_d1;
		let op_index = self.ir as usize;

		// Call instruction handler to mutate Core accordingly
		instruction_handler[op_index](self);

		// TODO: Perform CPU-cycle accounting for this instruction
	}
}

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

	#[test]
	fn new_sets_pc() {
		let cpu = Core::new(256);
	    assert_eq!(256, cpu.pc);
	}

	#[test]
	fn new_mem_sets_pc_and_mem() {
		let base = 128;
		let cpu = Core::new_mem(base, &[1u8, 2u8, 3u8, 4u8, 5u8, 6u8]);
	    assert_eq!(128, cpu.pc);
	    assert_eq!(1, cpu.mem[128]);
	    assert_eq!(2, cpu.mem[129]);
	}

	#[test]
	fn a_jump_changes_pc() {
		let mut cpu = Core::new(0);
		cpu.jump(128);
	    assert_eq!(128, cpu.pc);
	}

	#[test]
	fn an_imm_read32_changes_pc() {
		let base = 128;
		let mut cpu = Core::new(base);
		cpu.read_imm_32();
	    assert_eq!(base+4, cpu.pc);
	}

	#[test]
	fn an_imm_read32_reads_from_pc() {
		let base = 128;
		let mut cpu = Core::new_mem(base, &[2u8, 1u8, 3u8, 4u8]);
		let val = cpu.read_imm_32();
	    assert_eq!((2<<24)+(1<<16)+(3<<8)+4, val);
	}

	#[test]
	fn an_imm_read16_changes_pc() {
		let base = 128;
		let mut cpu = Core::new(base);
		cpu.read_imm_16();
	    assert_eq!(base+2, cpu.pc);
	}

	#[test]
	fn an_imm_read16_reads_from_pc() {
		let base = 128;
		let mut cpu = Core::new_mem(base, &[2u8, 1u8, 3u8, 4u8]);
		let val = cpu.read_imm_16();
	    assert_eq!((2<<8)+(1<<0), val);
	}

	#[test]
	fn a_reset_reads_sp_and_pc_from_0() {
		let mut cpu = Core::new_mem(0, &[0u8,0u8,1u8,0u8, 0u8,0u8,0u8,128u8]);
		cpu.reset();
	    assert_eq!(256, cpu.sp);
	    assert_eq!(128, cpu.pc);
	}

	#[test]
	#[should_panic(expected = "instruction bad1")]
	fn execute_reads_from_pc_and_panics_on_illegal_instruction() {
		let mut cpu = Core::new_mem(0xbd, &[0xba,0xd1,1u8,0u8, 0u8,0u8,0u8,128u8]);
		cpu.execute();
	}

	#[test]
	fn execute_can_execute_instruction_handler_0a() {
		let mut cpu = Core::new_mem(0xbd, &[0x00, 0x0A, 1u8,0u8, 0u8,0u8,0u8,128u8]);
		cpu.execute();
	    assert_eq!(0xabcd, cpu.dar[0]);
	    assert_eq!(0x0000, cpu.dar[1]);
	}

	#[test]
	fn execute_can_execute_instruction_handler_0b() {
		let mut cpu = Core::new_mem(0xbd, &[0x00, 0x0B, 1u8,0u8, 0u8,0u8,0u8,128u8]);
		cpu.execute();
	    assert_eq!(0x0000, cpu.dar[0]);
	    assert_eq!(0xbcde, cpu.dar[1]);
	}
}<commit_msg>Implement first real instruction<commit_after>pub type InstructionSet = [fn(&mut Core);0x10000];
pub type Handler = fn(&mut Core);

pub struct Core {
	pub pc: u32,
	pub sp: u32,
	pub ir: u16,
	pub dar: [u32; 16],
	pub ophandlers: InstructionSet,
	pub x_flag: u32,
	pub c_flag: u32,
	pub v_flag: u32,
	pub n_flag: u32,
	pub not_z_flag: u32,

	// Memory should probably be located elsewhere
	pub mem: [u8; 1024],
}

#[macro_use]
mod ops {
	use super::Core;

	macro_rules! ir_dx {
		($e:ident) => (($e.ir >> 9 & 7) as usize);
	}
	macro_rules! ir_dy {
		($e:ident) => (($e.ir & 7) as usize);
	}
	macro_rules! dx {
		($e:ident) => ($e.dar[ir_dx!($e)]);
	}
	macro_rules! dy {
		($e:ident) => ($e.dar[ir_dy!($e)]);
	}
	macro_rules! mask_out_above_8 {
		($e:expr) => ($e & 0xff)
	}
	macro_rules! mask_out_below_8 {
		($e:expr) => ($e & !0xff)
	}
	macro_rules! low_nibble {
		($e:expr) => ($e & 0x0f);
	}
	macro_rules! high_nibble {
		($e:expr) => ($e & 0xf0);
	}
	macro_rules! true1 {
		($e:expr) => (if $e {1} else {0})
	}

	pub mod fake {
		use super::super::Core;

		pub fn set_d0(core: &mut Core) {
			core.dar[0] = 0xabcd;
		}

		pub fn set_d1(core: &mut Core) {
			core.dar[1] = 0xbcde;
		}

		pub fn set_dx(core: &mut Core) {
			dx!(core) = 0xcdef;
		}

		use super::super::InstructionSet;
		use super::super::Handler;
		use super::illegal;
		const SET_DX_0: usize = 0b0100_0000_0000_0000;

		pub fn instruction_set() -> InstructionSet {
			// Covers all possible IR values (64k entries)
			let mut handler:[Handler; 0x10000] = [illegal; 0x10000];

			// a few fake instructions
			handler[0xA] = set_d0;
			handler[0xB] = set_d1;

			for i in 0..8 {
				let opcode = SET_DX_0 | (i << 9);
				println!("{:x}", opcode);
				handler[opcode] = set_dx;
			}
			handler
		}
	}

	pub fn illegal(core: &mut Core) {
		panic!("Illegal instruction {:04x} at {:08x}", core.ir, core.pc-2);
	}

	// First real instruction, ported from https://github.com/kstenerud/Musashi
	pub fn abcd_8_rr(core: &mut Core) {
		// unsigned int* r_dst = &(m68ki_cpu.dar[(m68ki_cpu.ir >> 9) & 7]);
		// unsigned int src = (m68ki_cpu.dar[m68ki_cpu.ir & 7]);
		// unsigned int dst = *r_dst;
		// unsigned int res = ((src) & 0x0f) + ((dst) & 0x0f) + ((m68ki_cpu.x_flag>>8)&1);
		let dst = dx!(core);
		let src = dy!(core);
		let mut res = low_nibble!(src) + low_nibble!(dst) + core.x_flag_as_1();

		// m68ki_cpu.v_flag = ~res;
		core.v_flag = !res;

		// if(res > 9)
		//  res += 6;
		// res += ((src) & 0xf0) + ((dst) & 0xf0);
		// m68ki_cpu.x_flag = m68ki_cpu.c_flag = (res > 0x99) << 8;
		if res > 9 {
			res += 6;
		}
		res += high_nibble!(src) + high_nibble!(dst);
		core.c_flag = true1!(res > 0x99) << 8;
		core.x_flag = core.c_flag;

		if core.c_flag > 0 {
			res -= 0xa0;
		}

		// m68ki_cpu.v_flag &= res;
		// m68ki_cpu.n_flag = (res);
		core.v_flag &= res;
		core.n_flag = res;

		// res = ((res) & 0xff);
		// m68ki_cpu.not_z_flag |= res;
		res = mask_out_above_8!(res);
		core.not_z_flag |= res;

		// *r_dst = ((*r_dst) & ~0xff) | res;
		dx!(core) = mask_out_below_8!(dst) | res;
	}

	use super::Handler;
	struct OpcodeHandler {
		mask: u32,
		matching: u32,
		name: String,
		handler: Handler
	}

	use super::InstructionSet;
	macro_rules! op_entry {
	    ($mask:expr, $matching:expr, $handler:ident) => (OpcodeHandler { mask: $mask, matching: $matching, handler: $handler, name: stringify!($handler).to_string() })
	}
	pub fn instruction_set() -> InstructionSet {
		// Covers all possible IR values (64k entries)
		let mut handler:[Handler; 0x10000] = [illegal; 0x10000];
		// the optable contains opcode mask, matching mask and the corresponding handler + name
		let optable = vec![op_entry!(0xf1f8, 0xc100, abcd_8_rr)];
		for op in optable {
			for opcode in 0..0x10000 {
				if (opcode & op.mask) == op.matching {
					println!("{:16b}: {}", opcode, op.name);
					handler[opcode as usize] = op.handler;
				}
			}
		}
		handler
	}
}

impl Core {
	pub fn new(base: u32) -> Core {
		Core { pc: base, sp: 0, ir: 0, dar: [0u32; 16], mem: [0u8; 1024], ophandlers: ops::fake::instruction_set(), x_flag: 0, v_flag: 0, c_flag: 0, n_flag: 0, not_z_flag: 0xffffffff}
	}
	pub fn new_mem(base: u32, contents: &[u8]) -> Core {
		let mut m = [0u8; 1024];
		let mut b = base as usize;
		for byte in contents {
			m[b] = *byte;
			b+=1;
		}
		Core { pc: base, sp: 0, ir: 0, dar: [0u32; 16], mem: m, ophandlers: ops::fake::instruction_set(), x_flag: 0, v_flag: 0, c_flag: 0, n_flag: 0, not_z_flag: 0xffffffff }
	}
	pub fn reset(&mut self) {
		self.jump(0);
		self.sp = self.read_imm_32();
		let new_pc = self.read_imm_32();
		self.jump(new_pc);
	}
	pub fn x_flag_as_1(&self) -> u32 {
		(self.x_flag>>8)&1
	}
	pub fn read_imm_32(&mut self) -> u32 {
		let b = self.pc as usize;
		self.pc += 4;
		return ((self.mem[b+0] as u32) << 24
			|   (self.mem[b+1] as u32) << 16
			|   (self.mem[b+2] as u32) <<  8
			|   (self.mem[b+3] as u32) <<  0
			) as u32;
	}
	pub fn read_imm_16(&mut self) -> u16 {
		let b = self.pc as usize;
		self.pc += 2;
		return ((self.mem[b+0] as u16) << 8
			|   (self.mem[b+1] as u16) << 0
			) as u16;
	}
	pub fn jump(&mut self, pc: u32) {
		self.pc = pc;
	}
	pub fn execute1(&mut self) {
		// Read an instruction from PC (increments PC by 2)
		self.ir = self.read_imm_16();
		let opcode = self.ir as usize;

		// Call instruction handler to mutate Core accordingly
		self.ophandlers[opcode](self);

		// TODO: Perform CPU-cycle accounting for this instruction
	}
}

#[cfg(test)]
mod tests {
	use super::Core;
	use super::ops; //::instruction_set;

	#[test]
	fn new_sets_pc() {
		let cpu = Core::new(256);
		assert_eq!(256, cpu.pc);
	}

	#[test]
	fn new_mem_sets_pc_and_mem() {
		let base = 128;
		let cpu = Core::new_mem(base, &[1u8, 2u8, 3u8, 4u8, 5u8, 6u8]);
		assert_eq!(128, cpu.pc);
		assert_eq!(1, cpu.mem[128]);
		assert_eq!(2, cpu.mem[129]);
	}

	#[test]
	fn a_jump_changes_pc() {
		let mut cpu = Core::new(0);
		cpu.jump(128);
		assert_eq!(128, cpu.pc);
	}

	#[test]
	fn an_imm_read32_changes_pc() {
		let base = 128;
		let mut cpu = Core::new(base);
		cpu.read_imm_32();
		assert_eq!(base+4, cpu.pc);
	}

	#[test]
	fn an_imm_read32_reads_from_pc() {
		let base = 128;
		let mut cpu = Core::new_mem(base, &[2u8, 1u8, 3u8, 4u8]);
		let val = cpu.read_imm_32();
		assert_eq!((2<<24)+(1<<16)+(3<<8)+4, val);
	}

	#[test]
	fn an_imm_read16_changes_pc() {
		let base = 128;
		let mut cpu = Core::new(base);
		cpu.read_imm_16();
		assert_eq!(base+2, cpu.pc);
	}

	#[test]
	fn an_imm_read16_reads_from_pc() {
		let base = 128;
		let mut cpu = Core::new_mem(base, &[2u8, 1u8, 3u8, 4u8]);
		let val = cpu.read_imm_16();
		assert_eq!((2<<8)+(1<<0), val);
	}

	#[test]
	fn a_reset_reads_sp_and_pc_from_0() {
		let mut cpu = Core::new_mem(0, &[0u8,0u8,1u8,0u8, 0u8,0u8,0u8,128u8]);
		cpu.reset();
		assert_eq!(256, cpu.sp);
		assert_eq!(128, cpu.pc);
	}

	#[test]
	#[should_panic(expected = "instruction bad1")]
	fn execute_reads_from_pc_and_panics_on_illegal_instruction() {
		let mut cpu = Core::new_mem(0xbd, &[0xba,0xd1,1u8,0u8, 0u8,0u8,0u8,128u8]);
		cpu.execute1();
	}

	#[test]
	fn execute_can_execute_instruction_handler_0a() {
		let mut cpu = Core::new_mem(0xbd, &[0x00, 0x0A, 1u8,0u8, 0u8,0u8,0u8,128u8]);
		cpu.execute1();
		assert_eq!(0xabcd, cpu.dar[0]);
		assert_eq!(0x0000, cpu.dar[1]);
	}

	#[test]
	fn execute_can_execute_instruction_handler_0b() {
		let mut cpu = Core::new_mem(0xbd, &[0x00, 0x0B, 1u8,0u8, 0u8,0u8,0u8,128u8]);
		cpu.execute1();
		assert_eq!(0x0000, cpu.dar[0]);
		assert_eq!(0xbcde, cpu.dar[1]);
	}

	#[test]
	fn execute_can_execute_set_dx() {
		// first byte 40 is register D0
		// 42 == D1
		// 44 == D2
		// 46 == D3
		// 48 == D4
		// 4a == D5
		// 4c == D6
		// 4e == D7
		let mut cpu = Core::new_mem(0x40, &[0x4c, 0x00, 1u8, 0u8]);
		cpu.execute1();
		assert_eq!(0xcdef, cpu.dar[6]);
	}

	#[test]
	fn low_nibble() {
		assert_eq!(0x0a, low_nibble!(0xba));
	}
	#[test]
	fn high_nibble() {
		assert_eq!(0xb0, high_nibble!(0xba));
	}
	#[test]
	fn mask_out_below_8() {
		assert_eq!(0x2bcdef00, mask_out_below_8!(0x2bcdef73));
	}
	#[test]
	fn mask_out_above_8() {
		assert_eq!(0xf1, mask_out_above_8!(0x2bcdeff1));
	}
	#[test]
	fn dx_and_dy() {
		let mut core = Core::new(0x40);
		core.dar[0] = 0x00;
		core.dar[1] = 0x11;
		core.dar[2] = 0x22;
		core.dar[3] = 0x33;
		core.dar[4] = 0x44;
		core.dar[5] = 0x55;
		core.dar[6] = 0x66;
		core.dar[7] = 0x77;

		core.ir = 0b1111_1001_1111_1010;
		assert_eq!(0x22, dy!(core));
		assert_eq!(0x44, dx!(core));

		core.ir = 0b1111_1011_1111_1110;
		assert_eq!(0x66, dy!(core));
		assert_eq!(0x55, dx!(core));
	}

	#[test]
	fn array_elems() {
		let mut arr = [1, 2, 3, 4];
		let mut marr = &mut arr;
		let mut elem: &mut i32 = &mut (marr[1]);
		// let mut elem2: &mut i32 = &mut (arr[2]);
		assert_eq!(2, *elem);
		*elem = 200;
		assert_eq!(200, *elem);
		// assert_eq!(200, &mut marr[1]);
	}

	#[test]
	fn abcd_8_rr() {
		// opcodes c100 - c107, c300 - c307, etc.
		// or more generally c[13579bdf]0[0-7]
		// where [13579bdf] is DX (dest regno) and [0-7] is DY (src regno)
		// so c300 means D1 = D0 + D1 in BCD
		let mut cpu = Core::new_mem(0x40, &[0xc3, 0x00]);
		cpu.ophandlers = ops::instruction_set();

		cpu.dar[0] = 0x16;
		cpu.dar[1] = 0x26;
		cpu.execute1();

		// 16 + 26 is 42
		assert_eq!(0x42, cpu.dar[1]);
	}
}<|endoftext|>


<commit_before>extern crate rand;

use std;

// A struct to contain info we need to print with every character
pub struct Control {
    pub seed: f64,
    pub spread: f64,
    pub frequency: f64,
    pub background_mode: bool,
    pub dialup_mode: bool,
}

// A wrapper around colored_print
pub fn print_with_lolcat(s: String, c: &mut Control) {
    let original_seed = c.seed;
    let mut skipping = false;
    let mut whitespace_after_newline = true;

    for character in s.chars() {
        // Strip out any color chars
        if character == '\x1b' {
            skipping = true;
            continue;
        }
        if skipping && character == 'm' {
            skipping = false;
            continue;
        }
        if skipping {
            continue;
        }

        if !character.is_whitespace() {
            whitespace_after_newline = false;
        }

        if whitespace_after_newline {
            print!("{}", character);
            continue;
        }

        c.seed += 1.0;

        if c.background_mode {
            let bg = get_color_tuple(c);
            let fg = calc_fg_color(bg);
            colored_print(fg, bg, character);
        } else {
            let fg = get_color_tuple(c);
            let black = (0u8, 0u8, 0u8);
            colored_print(fg, black, character);
        }
    }

    print!("\n"); // A newline, because lines() gave us a single line without it
    c.seed = original_seed + 1.0; // Reset the seed, but bump it a bit
}

fn calc_fg_color(bg: (u8, u8, u8)) -> (u8, u8, u8) {
    // Currently, it only computes the forground clolor based on some threshold
    // on grayscale value.
    // TODO: Add a better algorithm for computing forground color
    if conv_grayscale(bg) > 0xA0_u8 {
        (0u8, 0u8, 0u8)
    } else {
        (0xffu8, 0xffu8, 0xffu8)
    }
}

fn linear_to_srgb(intensity: f64) -> f64 {
    if intensity <= 0.0031308 {
        (12.92 * intensity)
    } else {
        (1.055 * intensity.powf(1.0 / 2.4) - 0.055)
    }
}

fn srgb_to_linear(intensity: f64) -> f64 {
    if intensity < 0.04045 {
        (intensity / 12.92)
    } else {
        ((intensity + 0.055) / 1.055).powf(2.4)
    }
}

fn conv_grayscale(color: (u8, u8, u8)) -> u8 {
    // See https://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
    const SCALE: f64 = 256.0;

    // Changing SRGB to Linear for gamma correction
    let red = srgb_to_linear((color.0 as f64) / SCALE);
    let green = srgb_to_linear((color.1 as f64) / SCALE);
    let blue = srgb_to_linear((color.2 as f64) / SCALE);

    // Converting to grayscale
    let gray_linear = red * 0.299 + green * 0.587 + blue * 0.114;

    // Gamma correction
    let gray_srgb = linear_to_srgb(gray_linear);

    (gray_srgb * SCALE) as u8
}

fn colored_print(fg: (u8, u8, u8), bg: (u8, u8, u8), c: char) {
    print!(
        "\x1b[38;2;{};{};{};48;2;{};{};{}m{}\x1b[0m",
        fg.0, fg.1, fg.2, bg.0, bg.1, bg.2, c
    );
}

fn get_color_tuple(c: &Control) -> (u8, u8, u8) {
    let i = c.frequency * c.seed / c.spread;
    let red = i.sin() * 127.00 + 128.00;
    let green = (i + (std::f64::consts::PI * 2.00 / 3.00)).sin() * 127.00 + 128.00;
    let blue = (i + (std::f64::consts::PI * 4.00 / 3.00)).sin() * 127.00 + 128.00;

    (red as u8, green as u8, blue as u8)
}
<commit_msg>Do not paint background in foreground mode<commit_after>extern crate rand;

use std;

// A struct to contain info we need to print with every character
pub struct Control {
    pub seed: f64,
    pub spread: f64,
    pub frequency: f64,
    pub background_mode: bool,
    pub dialup_mode: bool,
}

// A wrapper around colored_print
pub fn print_with_lolcat(s: String, c: &mut Control) {
    let original_seed = c.seed;
    let mut skipping = false;
    let mut whitespace_after_newline = true;

    for character in s.chars() {
        // Strip out any color chars
        if character == '\x1b' {
            skipping = true;
            continue;
        }
        if skipping && character == 'm' {
            skipping = false;
            continue;
        }
        if skipping {
            continue;
        }

        if !character.is_whitespace() {
            whitespace_after_newline = false;
        }

        if whitespace_after_newline {
            print!("{}", character);
            continue;
        }

        c.seed += 1.0;

        if c.background_mode {
            let bg = get_color_tuple(c);
            let fg = calc_fg_color(bg);
            colored_print_with_background(fg, bg, character);
        } else {
            let fg = get_color_tuple(c);
            colored_print(fg, character);
        }
    }

    print!("\n"); // A newline, because lines() gave us a single line without it
    c.seed = original_seed + 1.0; // Reset the seed, but bump it a bit
}

fn calc_fg_color(bg: (u8, u8, u8)) -> (u8, u8, u8) {
    // Currently, it only computes the forground clolor based on some threshold
    // on grayscale value.
    // TODO: Add a better algorithm for computing forground color
    if conv_grayscale(bg) > 0xA0_u8 {
        (0u8, 0u8, 0u8)
    } else {
        (0xffu8, 0xffu8, 0xffu8)
    }
}

fn linear_to_srgb(intensity: f64) -> f64 {
    if intensity <= 0.0031308 {
        (12.92 * intensity)
    } else {
        (1.055 * intensity.powf(1.0 / 2.4) - 0.055)
    }
}

fn srgb_to_linear(intensity: f64) -> f64 {
    if intensity < 0.04045 {
        (intensity / 12.92)
    } else {
        ((intensity + 0.055) / 1.055).powf(2.4)
    }
}

fn conv_grayscale(color: (u8, u8, u8)) -> u8 {
    // See https://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
    const SCALE: f64 = 256.0;

    // Changing SRGB to Linear for gamma correction
    let red = srgb_to_linear((color.0 as f64) / SCALE);
    let green = srgb_to_linear((color.1 as f64) / SCALE);
    let blue = srgb_to_linear((color.2 as f64) / SCALE);

    // Converting to grayscale
    let gray_linear = red * 0.299 + green * 0.587 + blue * 0.114;

    // Gamma correction
    let gray_srgb = linear_to_srgb(gray_linear);

    (gray_srgb * SCALE) as u8
}

fn colored_print(fg: (u8, u8, u8), c: char) {
    print!("\x1b[38;2;{};{};{};48m{}\x1b[0m", fg.0, fg.1, fg.2, c);
}

fn colored_print_with_background(fg: (u8, u8, u8), bg: (u8, u8, u8), c: char) {
    print!(
        "\x1b[38;2;{};{};{};48;2;{};{};{}m{}\x1b[0m",
        fg.0, fg.1, fg.2, bg.0, bg.1, bg.2, c
    );
}

fn get_color_tuple(c: &Control) -> (u8, u8, u8) {
    let i = c.frequency * c.seed / c.spread;
    let red = i.sin() * 127.00 + 128.00;
    let green = (i + (std::f64::consts::PI * 2.00 / 3.00)).sin() * 127.00 + 128.00;
    let blue = (i + (std::f64::consts::PI * 4.00 / 3.00)).sin() * 127.00 + 128.00;

    (red as u8, green as u8, blue as u8)
}
<|endoftext|>