<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::io;
use std::result;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use byteorder::{ByteOrder, LittleEndian};

use BusDevice;
use super::*;
use sys_util::{self, EventFd, GuestAddress, GuestMemory, Result};

//TODO crosvm uses 0 here, but IIRC virtio specified some other vendor id that should be used
const VENDOR_ID: u32 = 0;

//required by the virtio mmio device register layout at offset 0 from base
const MMIO_MAGIC_VALUE: u32 = 0x74726976;

//current version specified by the mmio standard (legacy devices used 1 here)
const MMIO_VERSION: u32 = 2;

#[derive(Debug)]
pub enum ActivateError
{
    EventFd(sys_util::Error),
    TryClone(sys_util::Error),
    EpollCtl(io::Error),
    BadActivate
}

pub type ActivateResult = result::Result<(), ActivateError>;

/// Trait for virtio devices to be driven by a virtio transport.
///
/// The lifecycle of a virtio device is to be moved to a virtio transport, which will then query the
/// device. Once the guest driver has configured the device, `VirtioDevice::activate` will be called
/// and all the events, memory, and queues for device operation will be moved into the device.
/// Optionally, a virtio device can implement device reset in which it returns said resources and
/// resets its internal.
pub trait VirtioDevice: Send {
    /// The virtio device type.
    fn device_type(&self) -> u32;

    /// The maximum size of each queue that this device supports.
    fn queue_max_sizes(&self) -> &[u16];

    /// The set of feature bits shifted by `page * 32`.
    fn features(&self, page: u32) -> u32 {
        let _ = page;
        0
    }

    /// Acknowledges that this set of features should be enabled.
    fn ack_features(&mut self, page: u32, value: u32) {
        let _ = page;
        let _ = value;
    }

    /// Reads this device configuration space at `offset`.
    fn read_config(&self, offset: u64, data: &mut [u8]) {
        let _ = offset;
        let _ = data;
    }

    /// Writes to this device configuration space at `offset`.
    fn write_config(&mut self, offset: u64, data: &[u8]) {
        let _ = offset;
        let _ = data;
    }

    /// Activates this device for real usage.
    fn activate(
        &mut self,
        mem: GuestMemory,
        interrupt_evt: EventFd,
        status: Arc<AtomicUsize>,
        queues: Vec<Queue>,
        queue_evts: Vec<EventFd>,
    ) -> ActivateResult;

    /// Optionally deactivates this device and returns ownership of the guest memory map, interrupt
    /// event, and queue events.
    fn reset(&mut self) -> Option<(EventFd, Vec<EventFd>)> {
        None
    }
}

/// Implements the
/// [MMIO](http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-1090002)
/// transport for virtio devices.
///
/// This requires 3 points of installation to work with a VM:
///
/// 1. Mmio reads and writes must be sent to this device at what is referred to here as MMIO base.
/// 1. `Mmio::queue_evts` must be installed at `virtio::NOITFY_REG_OFFSET` offset from the MMIO
/// base. Each event in the array must be signaled if the index is written at that offset.
/// 1. `Mmio::interrupt_evt` must signal an interrupt that the guest driver is listening to when it
/// is written to.
///
/// Typically one page (4096 bytes) of MMIO address space is sufficient to handle this transport
/// and inner virtio device.
pub struct MmioDevice {
    device: Box<VirtioDevice>,
    device_activated: bool,

    features_select: u32,
    acked_features_select: u32,
    queue_select: u32,
    interrupt_status: Arc<AtomicUsize>,
    interrupt_evt: Option<EventFd>,
    driver_status: u32,
    config_generation: u32,
    queues: Vec<Queue>,
    queue_evts: Vec<EventFd>,
    mem: Option<GuestMemory>,
}

impl MmioDevice {
    /// Constructs a new MMIO transport for the given virtio device.
    pub fn new(mem: GuestMemory, device: Box<VirtioDevice>) -> Result<MmioDevice> {
        let mut queue_evts = Vec::new();
        for _ in device.queue_max_sizes().iter() {
            queue_evts.push(EventFd::new()?)
        }
        let queues = device
            .queue_max_sizes()
            .iter()
            .map(|&s| Queue::new(s))
            .collect();
        Ok(MmioDevice {
            device: device,
            device_activated: false,
            features_select: 0,
            acked_features_select: 0,
            queue_select: 0,
            interrupt_status: Arc::new(AtomicUsize::new(0)),
            interrupt_evt: Some(EventFd::new()?),
            driver_status: 0,
            config_generation: 0,
            queues: queues,
            queue_evts: queue_evts,
            mem: Some(mem),
        })
    }

    /// Gets the list of queue events that must be triggered whenever the VM writes to
    /// `virtio::NOITFY_REG_OFFSET` past the MMIO base. Each event must be triggered when the
    /// value being written equals the index of the event in this list.
    pub fn queue_evts(&self) -> &[EventFd] {
        self.queue_evts.as_slice()
    }

    /// Gets the event this device uses to interrupt the VM when the used queue is changed.
    pub fn interrupt_evt(&self) -> Option<&EventFd> {
        self.interrupt_evt.as_ref()
    }

    fn is_driver_ready(&self) -> bool {
        let ready_bits = DEVICE_ACKNOWLEDGE | DEVICE_DRIVER | DEVICE_DRIVER_OK | DEVICE_FEATURES_OK;
        self.driver_status == ready_bits && self.driver_status & DEVICE_FAILED == 0
    }

    fn are_queues_valid(&self) -> bool {
        if let Some(mem) = self.mem.as_ref() {
            self.queues.iter().all(|q| q.is_valid(mem))
        } else {
            false
        }
    }

    fn with_queue<U, F>(&self, d: U, f: F) -> U
    where
        F: FnOnce(&Queue) -> U,
    {
        match self.queues.get(self.queue_select as usize) {
            Some(queue) => f(queue),
            None => d,
        }
    }

    fn with_queue_mut<F: FnOnce(&mut Queue)>(&mut self, f: F) -> bool {
        if let Some(queue) = self.queues.get_mut(self.queue_select as usize) {
            f(queue);
            true
        } else {
            false
        }
    }
}

impl BusDevice for MmioDevice {
    fn read(&mut self, offset: u64, data: &mut [u8]) {
        match offset {
            0x00...0xff if data.len() == 4 => {
                let v =
                    match offset {
                        0x0 => MMIO_MAGIC_VALUE,
                        0x04 => MMIO_VERSION,
                        0x08 => self.device.device_type(),
                        0x0c => VENDOR_ID, // vendor id
                        0x10 => {
                            self.device.features(self.features_select)
                                | if self.features_select == 1 { 0x1 } else { 0x0 }
                        }
                        0x34 => self.with_queue(0, |q| q.get_max_size() as u32),
                        0x44 => self.with_queue(0, |q| q.ready as u32),
                        0x60 => self.interrupt_status.load(Ordering::SeqCst) as u32,
                        0x70 => self.driver_status,
                        0xfc => self.config_generation,
                        _ => {
                            warn!("unknown virtio mmio register read: 0x{:x}", offset);
                            return;
                        }
                    };
                LittleEndian::write_u32(data, v);
            }
            0x100...0xfff => self.device.read_config(offset - 0x100, data),
            _ => {
                warn!(
                    "invalid virtio mmio read: 0x{:x}:0x{:x}",
                    offset,
                    data.len()
                );
            }
        };
    }

    fn write(&mut self, offset: u64, data: &[u8]) {
        fn hi(v: &mut GuestAddress, x: u32) {
            *v = (*v & 0xffffffff) | ((x as u64) << 32)
        }

        fn lo(v: &mut GuestAddress, x: u32) {
            *v = (*v & !0xffffffff) | (x as u64)
        }

        let mut mut_q = false;
        match offset {
            0x00...0xff if data.len() == 4 => {
                let v = LittleEndian::read_u32(data);
                match offset {
                    0x14 => self.features_select = v,
                    0x20 => self.device.ack_features(self.acked_features_select, v),
                    0x24 => self.acked_features_select = v,
                    0x30 => self.queue_select = v,
                    0x38 => mut_q = self.with_queue_mut(|q| q.size = v as u16),
                    0x44 => mut_q = self.with_queue_mut(|q| q.ready = v == 1),
                    0x64 => {
                        self.interrupt_status
                            .fetch_and(!(v as usize), Ordering::SeqCst);
                    }
                    0x70 => self.driver_status = v,
                    0x80 => mut_q = self.with_queue_mut(|q| lo(&mut q.desc_table, v)),
                    0x84 => mut_q = self.with_queue_mut(|q| hi(&mut q.desc_table, v)),
                    0x90 => mut_q = self.with_queue_mut(|q| lo(&mut q.avail_ring, v)),
                    0x94 => mut_q = self.with_queue_mut(|q| hi(&mut q.avail_ring, v)),
                    0xa0 => mut_q = self.with_queue_mut(|q| lo(&mut q.used_ring, v)),
                    0xa4 => mut_q = self.with_queue_mut(|q| hi(&mut q.used_ring, v)),
                    _ => {
                        warn!("unknown virtio mmio register write: 0x{:x}", offset);
                        return;
                    }
                }
            }
            0x100...0xfff => return self.device.write_config(offset - 0x100, data),
            _ => {
                warn!(
                    "invalid virtio mmio write: 0x{:x}:0x{:x}",
                    offset,
                    data.len()
                );
                return;
            }
        }

        if self.device_activated && mut_q {
            warn!("virtio queue was changed after device was activated");
        }

        if !self.device_activated && self.is_driver_ready() && self.are_queues_valid() {
            if let Some(interrupt_evt) = self.interrupt_evt.take() {
                if let Some(mem) = self.mem.take() {
                    self.device.activate(
                        mem,
                        interrupt_evt,
                        self.interrupt_status.clone(),
                        self.queues.clone(),
                        self.queue_evts.split_off(0),
                    ).unwrap();
                    self.device_activated = true;
                }
            }
        }
    }
}
<commit_msg>virtio/mmio.rs: ran rustfmt 0.3.4-nightly<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::io;
use std::result;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use byteorder::{ByteOrder, LittleEndian};

use BusDevice;
use super::*;
use sys_util::{self, EventFd, GuestAddress, GuestMemory, Result};

//TODO crosvm uses 0 here, but IIRC virtio specified some other vendor id that should be used
const VENDOR_ID: u32 = 0;

//required by the virtio mmio device register layout at offset 0 from base
const MMIO_MAGIC_VALUE: u32 = 0x74726976;

//current version specified by the mmio standard (legacy devices used 1 here)
const MMIO_VERSION: u32 = 2;

#[derive(Debug)]
pub enum ActivateError {
    EventFd(sys_util::Error),
    TryClone(sys_util::Error),
    EpollCtl(io::Error),
    BadActivate,
}

pub type ActivateResult = result::Result<(), ActivateError>;

/// Trait for virtio devices to be driven by a virtio transport.
///
/// The lifecycle of a virtio device is to be moved to a virtio transport, which will then query the
/// device. Once the guest driver has configured the device, `VirtioDevice::activate` will be called
/// and all the events, memory, and queues for device operation will be moved into the device.
/// Optionally, a virtio device can implement device reset in which it returns said resources and
/// resets its internal.
pub trait VirtioDevice: Send {
    /// The virtio device type.
    fn device_type(&self) -> u32;

    /// The maximum size of each queue that this device supports.
    fn queue_max_sizes(&self) -> &[u16];

    /// The set of feature bits shifted by `page * 32`.
    fn features(&self, page: u32) -> u32 {
        let _ = page;
        0
    }

    /// Acknowledges that this set of features should be enabled.
    fn ack_features(&mut self, page: u32, value: u32) {
        let _ = page;
        let _ = value;
    }

    /// Reads this device configuration space at `offset`.
    fn read_config(&self, offset: u64, data: &mut [u8]) {
        let _ = offset;
        let _ = data;
    }

    /// Writes to this device configuration space at `offset`.
    fn write_config(&mut self, offset: u64, data: &[u8]) {
        let _ = offset;
        let _ = data;
    }

    /// Activates this device for real usage.
    fn activate(
        &mut self,
        mem: GuestMemory,
        interrupt_evt: EventFd,
        status: Arc<AtomicUsize>,
        queues: Vec<Queue>,
        queue_evts: Vec<EventFd>,
    ) -> ActivateResult;

    /// Optionally deactivates this device and returns ownership of the guest memory map, interrupt
    /// event, and queue events.
    fn reset(&mut self) -> Option<(EventFd, Vec<EventFd>)> {
        None
    }
}

/// Implements the
/// [MMIO](http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-1090002)
/// transport for virtio devices.
///
/// This requires 3 points of installation to work with a VM:
///
/// 1. Mmio reads and writes must be sent to this device at what is referred to here as MMIO base.
/// 1. `Mmio::queue_evts` must be installed at `virtio::NOITFY_REG_OFFSET` offset from the MMIO
/// base. Each event in the array must be signaled if the index is written at that offset.
/// 1. `Mmio::interrupt_evt` must signal an interrupt that the guest driver is listening to when it
/// is written to.
///
/// Typically one page (4096 bytes) of MMIO address space is sufficient to handle this transport
/// and inner virtio device.
pub struct MmioDevice {
    device: Box<VirtioDevice>,
    device_activated: bool,

    features_select: u32,
    acked_features_select: u32,
    queue_select: u32,
    interrupt_status: Arc<AtomicUsize>,
    interrupt_evt: Option<EventFd>,
    driver_status: u32,
    config_generation: u32,
    queues: Vec<Queue>,
    queue_evts: Vec<EventFd>,
    mem: Option<GuestMemory>,
}

impl MmioDevice {
    /// Constructs a new MMIO transport for the given virtio device.
    pub fn new(mem: GuestMemory, device: Box<VirtioDevice>) -> Result<MmioDevice> {
        let mut queue_evts = Vec::new();
        for _ in device.queue_max_sizes().iter() {
            queue_evts.push(EventFd::new()?)
        }
        let queues = device
            .queue_max_sizes()
            .iter()
            .map(|&s| Queue::new(s))
            .collect();
        Ok(MmioDevice {
            device: device,
            device_activated: false,
            features_select: 0,
            acked_features_select: 0,
            queue_select: 0,
            interrupt_status: Arc::new(AtomicUsize::new(0)),
            interrupt_evt: Some(EventFd::new()?),
            driver_status: 0,
            config_generation: 0,
            queues: queues,
            queue_evts: queue_evts,
            mem: Some(mem),
        })
    }

    /// Gets the list of queue events that must be triggered whenever the VM writes to
    /// `virtio::NOITFY_REG_OFFSET` past the MMIO base. Each event must be triggered when the
    /// value being written equals the index of the event in this list.
    pub fn queue_evts(&self) -> &[EventFd] {
        self.queue_evts.as_slice()
    }

    /// Gets the event this device uses to interrupt the VM when the used queue is changed.
    pub fn interrupt_evt(&self) -> Option<&EventFd> {
        self.interrupt_evt.as_ref()
    }

    fn is_driver_ready(&self) -> bool {
        let ready_bits = DEVICE_ACKNOWLEDGE | DEVICE_DRIVER | DEVICE_DRIVER_OK | DEVICE_FEATURES_OK;
        self.driver_status == ready_bits && self.driver_status & DEVICE_FAILED == 0
    }

    fn are_queues_valid(&self) -> bool {
        if let Some(mem) = self.mem.as_ref() {
            self.queues.iter().all(|q| q.is_valid(mem))
        } else {
            false
        }
    }

    fn with_queue<U, F>(&self, d: U, f: F) -> U
    where
        F: FnOnce(&Queue) -> U,
    {
        match self.queues.get(self.queue_select as usize) {
            Some(queue) => f(queue),
            None => d,
        }
    }

    fn with_queue_mut<F: FnOnce(&mut Queue)>(&mut self, f: F) -> bool {
        if let Some(queue) = self.queues.get_mut(self.queue_select as usize) {
            f(queue);
            true
        } else {
            false
        }
    }
}

impl BusDevice for MmioDevice {
    fn read(&mut self, offset: u64, data: &mut [u8]) {
        match offset {
            0x00...0xff if data.len() == 4 => {
                let v =
                    match offset {
                        0x0 => MMIO_MAGIC_VALUE,
                        0x04 => MMIO_VERSION,
                        0x08 => self.device.device_type(),
                        0x0c => VENDOR_ID, // vendor id
                        0x10 => {
                            self.device.features(self.features_select)
                                | if self.features_select == 1 { 0x1 } else { 0x0 }
                        }
                        0x34 => self.with_queue(0, |q| q.get_max_size() as u32),
                        0x44 => self.with_queue(0, |q| q.ready as u32),
                        0x60 => self.interrupt_status.load(Ordering::SeqCst) as u32,
                        0x70 => self.driver_status,
                        0xfc => self.config_generation,
                        _ => {
                            warn!("unknown virtio mmio register read: 0x{:x}", offset);
                            return;
                        }
                    };
                LittleEndian::write_u32(data, v);
            }
            0x100...0xfff => self.device.read_config(offset - 0x100, data),
            _ => {
                warn!(
                    "invalid virtio mmio read: 0x{:x}:0x{:x}",
                    offset,
                    data.len()
                );
            }
        };
    }

    fn write(&mut self, offset: u64, data: &[u8]) {
        fn hi(v: &mut GuestAddress, x: u32) {
            *v = (*v & 0xffffffff) | ((x as u64) << 32)
        }

        fn lo(v: &mut GuestAddress, x: u32) {
            *v = (*v & !0xffffffff) | (x as u64)
        }

        let mut mut_q = false;
        match offset {
            0x00...0xff if data.len() == 4 => {
                let v = LittleEndian::read_u32(data);
                match offset {
                    0x14 => self.features_select = v,
                    0x20 => self.device.ack_features(self.acked_features_select, v),
                    0x24 => self.acked_features_select = v,
                    0x30 => self.queue_select = v,
                    0x38 => mut_q = self.with_queue_mut(|q| q.size = v as u16),
                    0x44 => mut_q = self.with_queue_mut(|q| q.ready = v == 1),
                    0x64 => {
                        self.interrupt_status
                            .fetch_and(!(v as usize), Ordering::SeqCst);
                    }
                    0x70 => self.driver_status = v,
                    0x80 => mut_q = self.with_queue_mut(|q| lo(&mut q.desc_table, v)),
                    0x84 => mut_q = self.with_queue_mut(|q| hi(&mut q.desc_table, v)),
                    0x90 => mut_q = self.with_queue_mut(|q| lo(&mut q.avail_ring, v)),
                    0x94 => mut_q = self.with_queue_mut(|q| hi(&mut q.avail_ring, v)),
                    0xa0 => mut_q = self.with_queue_mut(|q| lo(&mut q.used_ring, v)),
                    0xa4 => mut_q = self.with_queue_mut(|q| hi(&mut q.used_ring, v)),
                    _ => {
                        warn!("unknown virtio mmio register write: 0x{:x}", offset);
                        return;
                    }
                }
            }
            0x100...0xfff => return self.device.write_config(offset - 0x100, data),
            _ => {
                warn!(
                    "invalid virtio mmio write: 0x{:x}:0x{:x}",
                    offset,
                    data.len()
                );
                return;
            }
        }

        if self.device_activated && mut_q {
            warn!("virtio queue was changed after device was activated");
        }

        if !self.device_activated && self.is_driver_ready() && self.are_queues_valid() {
            if let Some(interrupt_evt) = self.interrupt_evt.take() {
                if let Some(mem) = self.mem.take() {
                    self.device
                        .activate(
                            mem,
                            interrupt_evt,
                            self.interrupt_status.clone(),
                            self.queues.clone(),
                            self.queue_evts.split_off(0),
                        )
                        .unwrap();
                    self.device_activated = true;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use mysql::error::Error;
use mysql::{Conn, Opts, OptsBuilder};
use std::result::Result;
use r2d2;
use mysql::prelude::Queryable;

#[derive(Clone, Debug)]
pub struct MysqlConnectionManager {
    params: Opts,
}

impl MysqlConnectionManager {
    pub fn new(params: OptsBuilder) -> MysqlConnectionManager {
        MysqlConnectionManager {
            params: Opts::from(params),
        }
    }
}

impl r2d2::ManageConnection for MysqlConnectionManager {
    type Connection = Conn;
    type Error = Error;

    fn connect(&self) -> Result<Conn, Error> {
        Conn::new(self.params.clone())
    }

    fn is_valid(&self, conn: &mut Conn) -> Result<(), Error> {
        conn.query("SELECT version()").map(|_: String| ())
    }

    fn has_broken(&self, conn: &mut Conn) -> bool {
        self.is_valid(conn).is_err()
    }
}
<commit_msg>Update pool.rs<commit_after>use mysql::error::Error;
use mysql::{Conn, Opts, OptsBuilder};
use std::result::Result;
use r2d2;
use mysql::prelude::Queryable;

#[derive(Clone, Debug)]
pub struct MysqlConnectionManager {
    params: Opts,
}

impl MysqlConnectionManager {
    pub fn new(params: OptsBuilder) -> MysqlConnectionManager {
        MysqlConnectionManager {
            params: Opts::from(params),
        }
    }
}

impl r2d2::ManageConnection for MysqlConnectionManager {
    type Connection = Conn;
    type Error = Error;

    fn connect(&self) -> Result<Conn, Error> {
        Conn::new(self.params.clone())
    }

    fn is_valid(&self, conn: &mut Conn) -> Result<(), Error> {
        conn.query("SELECT version()").map(|_: Vec<String>| ())
    }

    fn has_broken(&self, conn: &mut Conn) -> bool {
        self.is_valid(conn).is_err()
    }
}
<|endoftext|>


<commit_before>//! Binary machine code emission.
//!
//! The `binemit` module contains code for translating Cretonne's intermediate representation into
//! binary machine code.

mod relaxation;
mod memorysink;

pub use regalloc::RegDiversions;
pub use self::relaxation::relax_branches;
pub use self::memorysink::{MemoryCodeSink, RelocSink, TrapSink};

use ir::{ExternalName, JumpTable, Function, Inst, TrapCode, SourceLoc};
use std::fmt;

/// Offset in bytes from the beginning of the function.
///
/// Cretonne can be used as a cross compiler, so we don't want to use a type like `usize` which
/// depends on the *host* platform, not the *target* platform.
pub type CodeOffset = u32;

/// Addend to add to the symbol value.
pub type Addend = i64;

/// Relocation kinds for every ISA
#[derive(Debug)]
pub enum Reloc {
    /// Intel PC-relative 4-byte
    IntelPCRel4,
    /// Intel absolute 4-byte
    IntelAbs4,
    /// Intel absolute 8-byte
    IntelAbs8,
    /// Intel GOT PC-relative 4-byte
    IntelGOTPCRel4,
    /// Intel PLT-relative 4-byte
    IntelPLTRel4,
    /// Arm32 call target
    Arm32Call,
    /// Arm64 call target
    Arm64Call,
    /// RISC-V call target
    RiscvCall,
}

impl fmt::Display for Reloc {
    /// Display trait implementation drops the arch, since its used in contexts where the arch is
    /// already unambigious, e.g. cton syntax with isa specified. In other contexts, use Debug.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Reloc::IntelPCRel4 => write!(f, "{}", "PCRel4"),
            Reloc::IntelAbs4 => write!(f, "{}", "Abs4"),
            Reloc::IntelAbs8 => write!(f, "{}", "Abs8"),
            Reloc::IntelGOTPCRel4 => write!(f, "{}", "GOTPCRel4"),
            Reloc::IntelPLTRel4 => write!(f, "{}", "PLTRel4"),
            Reloc::Arm32Call | Reloc::Arm64Call | Reloc::RiscvCall => write!(f, "{}", "Call"),
        }
    }
}

/// Abstract interface for adding bytes to the code segment.
///
/// A `CodeSink` will receive all of the machine code for a function. It also accepts relocations
/// which are locations in the code section that need to be fixed up when linking.
pub trait CodeSink {
    /// Get the current position.
    fn offset(&self) -> CodeOffset;

    /// Add 1 byte to the code section.
    fn put1(&mut self, u8);

    /// Add 2 bytes to the code section.
    fn put2(&mut self, u16);

    /// Add 4 bytes to the code section.
    fn put4(&mut self, u32);

    /// Add 8 bytes to the code section.
    fn put8(&mut self, u64);

    /// Add a relocation referencing an EBB at the current offset.
    fn reloc_ebb(&mut self, Reloc, CodeOffset);

    /// Add a relocation referencing an external symbol plus the addend at the current offset.
    fn reloc_external(&mut self, Reloc, &ExternalName, Addend);

    /// Add a relocation referencing a jump table.
    fn reloc_jt(&mut self, Reloc, JumpTable);

    /// Add trap information for the current offset.
    fn trap(&mut self, TrapCode, SourceLoc);
}

/// Report a bad encoding error.
#[inline(never)]
pub fn bad_encoding(func: &Function, inst: Inst) -> ! {
    panic!(
        "Bad encoding {} for {}",
        func.encodings[inst],
        func.dfg.display_inst(inst, None)
    );
}

/// Emit a function to `sink`, given an instruction emitter function.
///
/// This function is called from the `TargetIsa::emit_function()` implementations with the
/// appropriate instruction emitter.
pub fn emit_function<CS, EI>(func: &Function, emit_inst: EI, sink: &mut CS)
where
    CS: CodeSink,
    EI: Fn(&Function, Inst, &mut RegDiversions, &mut CS),
{
    let mut divert = RegDiversions::new();
    for ebb in func.layout.ebbs() {
        divert.clear();
        debug_assert_eq!(func.offsets[ebb], sink.offset());
        for inst in func.layout.ebb_insts(ebb) {
            emit_inst(func, inst, &mut divert, sink);
        }
    }
}
<commit_msg>Use `#[cold]` rather than `#[inline(never)]`.<commit_after>//! Binary machine code emission.
//!
//! The `binemit` module contains code for translating Cretonne's intermediate representation into
//! binary machine code.

mod relaxation;
mod memorysink;

pub use regalloc::RegDiversions;
pub use self::relaxation::relax_branches;
pub use self::memorysink::{MemoryCodeSink, RelocSink, TrapSink};

use ir::{ExternalName, JumpTable, Function, Inst, TrapCode, SourceLoc};
use std::fmt;

/// Offset in bytes from the beginning of the function.
///
/// Cretonne can be used as a cross compiler, so we don't want to use a type like `usize` which
/// depends on the *host* platform, not the *target* platform.
pub type CodeOffset = u32;

/// Addend to add to the symbol value.
pub type Addend = i64;

/// Relocation kinds for every ISA
#[derive(Debug)]
pub enum Reloc {
    /// Intel PC-relative 4-byte
    IntelPCRel4,
    /// Intel absolute 4-byte
    IntelAbs4,
    /// Intel absolute 8-byte
    IntelAbs8,
    /// Intel GOT PC-relative 4-byte
    IntelGOTPCRel4,
    /// Intel PLT-relative 4-byte
    IntelPLTRel4,
    /// Arm32 call target
    Arm32Call,
    /// Arm64 call target
    Arm64Call,
    /// RISC-V call target
    RiscvCall,
}

impl fmt::Display for Reloc {
    /// Display trait implementation drops the arch, since its used in contexts where the arch is
    /// already unambigious, e.g. cton syntax with isa specified. In other contexts, use Debug.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Reloc::IntelPCRel4 => write!(f, "{}", "PCRel4"),
            Reloc::IntelAbs4 => write!(f, "{}", "Abs4"),
            Reloc::IntelAbs8 => write!(f, "{}", "Abs8"),
            Reloc::IntelGOTPCRel4 => write!(f, "{}", "GOTPCRel4"),
            Reloc::IntelPLTRel4 => write!(f, "{}", "PLTRel4"),
            Reloc::Arm32Call | Reloc::Arm64Call | Reloc::RiscvCall => write!(f, "{}", "Call"),
        }
    }
}

/// Abstract interface for adding bytes to the code segment.
///
/// A `CodeSink` will receive all of the machine code for a function. It also accepts relocations
/// which are locations in the code section that need to be fixed up when linking.
pub trait CodeSink {
    /// Get the current position.
    fn offset(&self) -> CodeOffset;

    /// Add 1 byte to the code section.
    fn put1(&mut self, u8);

    /// Add 2 bytes to the code section.
    fn put2(&mut self, u16);

    /// Add 4 bytes to the code section.
    fn put4(&mut self, u32);

    /// Add 8 bytes to the code section.
    fn put8(&mut self, u64);

    /// Add a relocation referencing an EBB at the current offset.
    fn reloc_ebb(&mut self, Reloc, CodeOffset);

    /// Add a relocation referencing an external symbol plus the addend at the current offset.
    fn reloc_external(&mut self, Reloc, &ExternalName, Addend);

    /// Add a relocation referencing a jump table.
    fn reloc_jt(&mut self, Reloc, JumpTable);

    /// Add trap information for the current offset.
    fn trap(&mut self, TrapCode, SourceLoc);
}

/// Report a bad encoding error.
#[cold]
pub fn bad_encoding(func: &Function, inst: Inst) -> ! {
    panic!(
        "Bad encoding {} for {}",
        func.encodings[inst],
        func.dfg.display_inst(inst, None)
    );
}

/// Emit a function to `sink`, given an instruction emitter function.
///
/// This function is called from the `TargetIsa::emit_function()` implementations with the
/// appropriate instruction emitter.
pub fn emit_function<CS, EI>(func: &Function, emit_inst: EI, sink: &mut CS)
where
    CS: CodeSink,
    EI: Fn(&Function, Inst, &mut RegDiversions, &mut CS),
{
    let mut divert = RegDiversions::new();
    for ebb in func.layout.ebbs() {
        divert.clear();
        debug_assert_eq!(func.offsets[ebb], sink.offset());
        for inst in func.layout.ebb_insts(ebb) {
            emit_inst(func, inst, &mut divert, sink);
        }
    }
}
<|endoftext|>


<commit_before>use tungstenite::{protocol::Message, error::Error};
use tokio_tungstenite::{connect_async, WebSocketStream, MaybeTlsStream};
use url;

// subscribe to trading pair ticker updates
pub async fn subscribe(
    connect_addr: &str,
    pairs: Vec<String>,
) -> Result<WebSocketStream<MaybeTlsStream<tokio::net::TcpStream>>, Error>
 {

    let url = url::Url::parse(&connect_addr).map_err(|err| Error::Url(err.to_string().into()))?;
    let (mut ws_stream, _) = connect_async(url).await?;
    for pair in pairs.iter() {
        let msg = message_subscribe(pair).into();
        ws_stream.send(msg).await?;
    }
    Ok(ws_stream)
}

fn message_subscribe(channel: &str) -> Message {
    Message::text(format!(
        "{{ \"command\": \"subscribe\", \"channel\": \"{}\" }}",
        channel
    ))
}
<commit_msg>make Message public<commit_after>pub use tungstenite::protocol::Message;
use tungstenite::error::Error;
use tokio_tungstenite::{connect_async, WebSocketStream, MaybeTlsStream};
use url;

// subscribe to trading pair ticker updates
pub async fn subscribe(
    connect_addr: &str,
    pairs: Vec<String>,
) -> Result<WebSocketStream<MaybeTlsStream<tokio::net::TcpStream>>, Error>
 {

    let url = url::Url::parse(&connect_addr).map_err(|err| Error::Url(err.to_string().into()))?;
    let (mut ws_stream, _) = connect_async(url).await?;
    for pair in pairs.iter() {
        let msg = message_subscribe(pair).into();
        ws_stream.send(msg).await?;
    }
    Ok(ws_stream)
}

fn message_subscribe(channel: &str) -> Message {
    Message::text(format!(
        "{{ \"command\": \"subscribe\", \"channel\": \"{}\" }}",
        channel
    ))
}
<|endoftext|>


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

use vector::{Line2f, Vec2f};

/// 2D Quadrilateral
///
/// ```text
///   p3____p2
///    |    |
///    |____|
///   p0    p1
/// ```
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Quad2f {
    pub points: (Vec2f, Vec2f, Vec2f, Vec2f)
}

/// Return type for Quad2f::iblerp
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum IBLerpResult {
    NoSolution,
    /// One solutions (as parametric coordinate)
    OneSolution(Vec2f),
    /// Two solutions (as parametric coordinates)
    TwoSolutions(Vec2f, Vec2f),
    ManySolutions
}

/// Return type for Quad2f::inv_bilerp_u
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum InvBilerpResult {
    NoSolution,
    /// One solutions (as parametric coordinate)
    OneSolution(f32),
    /// Two solutions (as parametric coordinates)
    TwoSolutions(f32, f32),
    ManySolutions
}

impl Quad2f {
    pub fn new(a: Vec2f, b: Vec2f, c: Vec2f, d: Vec2f) -> Quad2f {
        Quad2f {
            points: (a, b, c, d)
        }
    }

    // TODO(nicholasbishop): code dedup

    /// Inverse bilinear interpolation
    ///
    /// Adapted from stackoverflow.com/questions/808441
    pub fn iblerp(self, point: Vec2f) -> IBLerpResult {
        let p0mp = self.points.0 - point;
        let p1mp = self.points.1 - point;
        let p0mp3 = self.points.0 - self.points.3;
        let p1mp2 = self.points.1 - self.points.2;

        let a = p0mp.cross(p0mp3);
        let b0 = p0mp.cross(p1mp2);
        let b1 = p1mp.cross(p0mp3);
        let b = (b0 + b1) / 2.0;
        let c = p1mp.cross(p1mp2);

        let calc_st = |s| {
            let den = (1.0 - s) * p0mp3.x + s * p1mp2.x;
            let t = if den == 0.0 {
                // TODO(nicholasbishop): perhaps there's a more
                // efficient way to solve this, the SO post doesn't
                // seem to cover this case
                let rb = self.points.0.lerp(self.points.1, s);
                let rt = self.points.3.lerp(self.points.2, s);
                Line2f::new(rb, rt).closest_parametric_point(point)
            }
            else {
                ((1.0 - s) * (p0mp.x) + s * p1mp.x) / den
            };
            Vec2f::new(s, t)
        };

        let den = a - (2.0 * b) + c;
        if den == 0.0 {
            let m = a - c;
            if m == 0.0 {
                if a == 0.0 {
                    IBLerpResult::ManySolutions
                }
                else {
                    IBLerpResult::NoSolution
                }
            }
            else {
                IBLerpResult::OneSolution(calc_st(a / m))
            }
        }
        else {
            let left = a - b;
            let right = (b.powi(2) - a*c).sqrt();
            let s0 = (left + right) / den;
            let s1 = (left - right) / den;
            IBLerpResult::TwoSolutions(calc_st(s0), calc_st(s1))
        }
    }

    /// Calculate horizontal parametric coordinate from cartesian point.
    pub fn inv_bilerp_u(self, point: Vec2f) -> InvBilerpResult {
        let p0mp = self.points.0 - point;
        let p1mp = self.points.1 - point;
        let p0mp3 = self.points.0 - self.points.3;
        let p1mp2 = self.points.1 - self.points.2;

        let a = p0mp.cross(p0mp3);
        let b0 = p0mp.cross(p1mp2);
        let b1 = p1mp.cross(p0mp3);
        let b = (b0 + b1) / 2.0;
        let c = p1mp.cross(p1mp2);

        let den = a - (2.0 * b) + c;
        if den == 0.0 {
            let m = a - c;
            if m == 0.0 {
                if a == 0.0 {
                    InvBilerpResult::ManySolutions
                }
                else {
                    InvBilerpResult::NoSolution
                }
            }
            else {
                InvBilerpResult::OneSolution(a / m)
            }
        }
        else {
            let left = a - b;
            let right = (b.powi(2) - a*c).sqrt();
            let s0 = (left + right) / den;
            let s1 = (left - right) / den;
            InvBilerpResult::TwoSolutions(s0, s1)
        }
    }

    pub fn blerp(self, uv: Vec2f) -> Vec2f {
        let rb = self.points.0.lerp(self.points.1, uv.x);
        let rt = self.points.3.lerp(self.points.2, uv.x);
        rb.lerp(rt, uv.y)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use vector::vec2f;

    #[test]
    fn test_inv_bilerp_u() {
        let q = Quad2f::new(vec2f(0, 0),
                            vec2f(4, 0),
                            vec2f(4, 4),
                            vec2f(0, 4));
        assert_eq!(q.inv_bilerp_u(vec2f(2, 2)),
                   InvBilerpResult::OneSolution(0.5));
        assert_eq!(q.inv_bilerp_u(vec2f(1, 2)),
                   InvBilerpResult::OneSolution(0.25));
        assert_eq!(q.inv_bilerp_u(vec2f(1, 3)),
                   InvBilerpResult::OneSolution(0.25));
    }

    #[test]
    fn test_iblerp() {
        let q = Quad2f::new(vec2f(0, 0),
                            vec2f(4, 0),
                            vec2f(4, 4),
                            vec2f(0, 4));
        assert_eq!(q.iblerp(vec2f(2, 2)),
                   IBLerpResult::OneSolution(vec2f(0.5, 0.5)));
    }
}
<commit_msg>Update quad art<commit_after>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use vector::{Line2f, Vec2f};

/// 2D Quadrilateral
///
/// ```text
///          top
///     p3________p2
///      |        |
///      |        |
/// left |        | right
///      |        |
///      |________|
///     p0        p1
///        bottom
/// ```
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Quad2f {
    pub points: (Vec2f, Vec2f, Vec2f, Vec2f)
}

/// Return type for Quad2f::iblerp
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum IBLerpResult {
    NoSolution,
    /// One solutions (as parametric coordinate)
    OneSolution(Vec2f),
    /// Two solutions (as parametric coordinates)
    TwoSolutions(Vec2f, Vec2f),
    ManySolutions
}

/// Return type for Quad2f::inv_bilerp_u
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum InvBilerpResult {
    NoSolution,
    /// One solutions (as parametric coordinate)
    OneSolution(f32),
    /// Two solutions (as parametric coordinates)
    TwoSolutions(f32, f32),
    ManySolutions
}

impl Quad2f {
    pub fn new(a: Vec2f, b: Vec2f, c: Vec2f, d: Vec2f) -> Quad2f {
        Quad2f {
            points: (a, b, c, d)
        }
    }

    // TODO(nicholasbishop): code dedup

    /// Inverse bilinear interpolation
    ///
    /// Adapted from stackoverflow.com/questions/808441
    pub fn iblerp(self, point: Vec2f) -> IBLerpResult {
        let p0mp = self.points.0 - point;
        let p1mp = self.points.1 - point;
        let p0mp3 = self.points.0 - self.points.3;
        let p1mp2 = self.points.1 - self.points.2;

        let a = p0mp.cross(p0mp3);
        let b0 = p0mp.cross(p1mp2);
        let b1 = p1mp.cross(p0mp3);
        let b = (b0 + b1) / 2.0;
        let c = p1mp.cross(p1mp2);

        let calc_st = |s| {
            let den = (1.0 - s) * p0mp3.x + s * p1mp2.x;
            let t = if den == 0.0 {
                // TODO(nicholasbishop): perhaps there's a more
                // efficient way to solve this, the SO post doesn't
                // seem to cover this case
                let rb = self.points.0.lerp(self.points.1, s);
                let rt = self.points.3.lerp(self.points.2, s);
                Line2f::new(rb, rt).closest_parametric_point(point)
            }
            else {
                ((1.0 - s) * (p0mp.x) + s * p1mp.x) / den
            };
            Vec2f::new(s, t)
        };

        let den = a - (2.0 * b) + c;
        if den == 0.0 {
            let m = a - c;
            if m == 0.0 {
                if a == 0.0 {
                    IBLerpResult::ManySolutions
                }
                else {
                    IBLerpResult::NoSolution
                }
            }
            else {
                IBLerpResult::OneSolution(calc_st(a / m))
            }
        }
        else {
            let left = a - b;
            let right = (b.powi(2) - a*c).sqrt();
            let s0 = (left + right) / den;
            let s1 = (left - right) / den;
            IBLerpResult::TwoSolutions(calc_st(s0), calc_st(s1))
        }
    }

    /// Calculate horizontal parametric coordinate from cartesian point.
    pub fn inv_bilerp_u(self, point: Vec2f) -> InvBilerpResult {
        let p0mp = self.points.0 - point;
        let p1mp = self.points.1 - point;
        let p0mp3 = self.points.0 - self.points.3;
        let p1mp2 = self.points.1 - self.points.2;

        let a = p0mp.cross(p0mp3);
        let b0 = p0mp.cross(p1mp2);
        let b1 = p1mp.cross(p0mp3);
        let b = (b0 + b1) / 2.0;
        let c = p1mp.cross(p1mp2);

        let den = a - (2.0 * b) + c;
        if den == 0.0 {
            let m = a - c;
            if m == 0.0 {
                if a == 0.0 {
                    InvBilerpResult::ManySolutions
                }
                else {
                    InvBilerpResult::NoSolution
                }
            }
            else {
                InvBilerpResult::OneSolution(a / m)
            }
        }
        else {
            let left = a - b;
            let right = (b.powi(2) - a*c).sqrt();
            let s0 = (left + right) / den;
            let s1 = (left - right) / den;
            InvBilerpResult::TwoSolutions(s0, s1)
        }
    }

    pub fn blerp(self, uv: Vec2f) -> Vec2f {
        let rb = self.points.0.lerp(self.points.1, uv.x);
        let rt = self.points.3.lerp(self.points.2, uv.x);
        rb.lerp(rt, uv.y)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use vector::vec2f;

    #[test]
    fn test_inv_bilerp_u() {
        let q = Quad2f::new(vec2f(0, 0),
                            vec2f(4, 0),
                            vec2f(4, 4),
                            vec2f(0, 4));
        assert_eq!(q.inv_bilerp_u(vec2f(2, 2)),
                   InvBilerpResult::OneSolution(0.5));
        assert_eq!(q.inv_bilerp_u(vec2f(1, 2)),
                   InvBilerpResult::OneSolution(0.25));
        assert_eq!(q.inv_bilerp_u(vec2f(1, 3)),
                   InvBilerpResult::OneSolution(0.25));
    }

    #[test]
    fn test_iblerp() {
        let q = Quad2f::new(vec2f(0, 0),
                            vec2f(4, 0),
                            vec2f(4, 4),
                            vec2f(0, 4));
        assert_eq!(q.iblerp(vec2f(2, 2)),
                   IBLerpResult::OneSolution(vec2f(0.5, 0.5)));
    }
}
<|endoftext|>


<commit_before>//! Structs for reading a ZIP archive

use crc32::Crc32Reader;
use compression::CompressionMethod;
use spec;
use result::{ZipResult, ZipError};
use std::io;
use std::io::prelude::*;
use std::collections::HashMap;
use flate2;
use flate2::FlateReadExt;
use podio::{ReadPodExt, LittleEndian};
use types::ZipFileData;
use cp437::FromCp437;
use msdos_time::{TmMsDosExt, MsDosDateTime};

#[cfg(feature = "bzip2")]
use bzip2::read::BzDecoder;

/// Wrapper for reading the contents of a ZIP file.
///
/// ```
/// fn doit() -> zip::result::ZipResult<()>
/// {
///     use std::io::prelude::*;
///
///     // For demonstration purposes we read from an empty buffer.
///     // Normally a File object would be used.
///     let buf: &[u8] = &[0u8; 128];
///     let mut reader = std::io::Cursor::new(buf);
///
///     let mut zip = try!(zip::ZipArchive::new(reader));
///
///     for i in 0..zip.len()
///     {
///         let mut file = zip.by_index(i).unwrap();
///         println!("Filename: {}", file.name());
///         let first_byte = try!(file.bytes().next().unwrap());
///         println!("{}", first_byte);
///     }
///     Ok(())
/// }
///
/// println!("Result: {:?}", doit());
/// ```
pub struct ZipArchive<R: Read + io::Seek>
{
    reader: R,
    files: Vec<ZipFileData>,
    names_map: HashMap<String, usize>,
}

enum ZipFileReader<'a> {
    Stored(Crc32Reader<io::Take<&'a mut Read>>),
    Deflated(Crc32Reader<flate2::read::DeflateDecoder<io::Take<&'a mut Read>>>),
    #[cfg(feature = "bzip2")]
    Bzip2(Crc32Reader<BzDecoder<io::Take<&'a mut Read>>>),
}

/// A struct for reading a zip file
pub struct ZipFile<'a> {
    data: &'a ZipFileData,
    reader: ZipFileReader<'a>,
}

fn unsupported_zip_error<T>(detail: &'static str) -> ZipResult<T>
{
    Err(ZipError::UnsupportedArchive(detail))
}

impl<R: Read+io::Seek> ZipArchive<R>
{
    /// Opens a Zip archive and parses the central directory
    pub fn new(mut reader: R) -> ZipResult<ZipArchive<R>> {
        let footer = try!(spec::CentralDirectoryEnd::find_and_parse(&mut reader));

        if footer.disk_number != footer.disk_with_central_directory { return unsupported_zip_error("Support for multi-disk files is not implemented") }

        let directory_start = footer.central_directory_offset as u64;
        let number_of_files = footer.number_of_files_on_this_disk as usize;

        let mut files = Vec::with_capacity(number_of_files);
        let mut names_map = HashMap::new();

        try!(reader.seek(io::SeekFrom::Start(directory_start)));
        for _ in 0 .. number_of_files
        {
            let file = try!(central_header_to_zip_file(&mut reader));
            names_map.insert(file.file_name.clone(), files.len());
            files.push(file);
        }

        Ok(ZipArchive { reader: reader, files: files, names_map: names_map })
    }

    /// Number of files contained in this zip.
    ///
    /// ```
    /// fn iter() {
    ///     let mut zip = zip::ZipArchive::new(std::io::Cursor::new(vec![])).unwrap();
    ///
    ///     for i in 0..zip.len() {
    ///         let mut file = zip.by_index(i).unwrap();
    ///         // Do something with file i
    ///     }
    /// }
    /// ```
    pub fn len(&self) -> usize
    {
        self.files.len()
    }

    /// Search for a file entry by name
    pub fn by_name<'a>(&'a mut self, name: &str) -> ZipResult<ZipFile<'a>>
    {
        let index = match self.names_map.get(name) {
            Some(index) => *index,
            None => { return Err(ZipError::FileNotFound); },
        };
        self.by_index(index)
    }

    /// Get a contained file by index
    pub fn by_index<'a>(&'a mut self, file_number: usize) -> ZipResult<ZipFile<'a>>
    {
        if file_number >= self.files.len() { return Err(ZipError::FileNotFound); }
        let ref data = self.files[file_number];
        let pos = data.data_start;

        if data.encrypted
        {
            return unsupported_zip_error("Encrypted files are not supported")
        }

        try!(self.reader.seek(io::SeekFrom::Start(pos)));
        let limit_reader = (self.reader.by_ref() as &mut Read).take(data.compressed_size);

        let reader = match data.compression_method
        {
            CompressionMethod::Stored =>
            {
                ZipFileReader::Stored(Crc32Reader::new(
                    limit_reader,
                    data.crc32))
            },
            CompressionMethod::Deflated =>
            {
                let deflate_reader = limit_reader.deflate_decode();
                ZipFileReader::Deflated(Crc32Reader::new(
                    deflate_reader,
                    data.crc32))
            },
            #[cfg(feature = "bzip2")]
            CompressionMethod::Bzip2 =>
            {
                let bzip2_reader = BzDecoder::new(limit_reader);
                ZipFileReader::Bzip2(Crc32Reader::new(
                    bzip2_reader,
                    data.crc32))
            },
            _ => return unsupported_zip_error("Compression method not supported"),
        };
        Ok(ZipFile { reader: reader, data: data })
    }

    /// Unwrap and return the inner reader object
    ///
    /// The position of the reader is undefined.
    pub fn into_inner(self) -> R
    {
        self.reader
    }
}

fn central_header_to_zip_file<R: Read+io::Seek>(reader: &mut R) -> ZipResult<ZipFileData>
{
    // Parse central header
    let signature = try!(reader.read_u32::<LittleEndian>());
    if signature != spec::CENTRAL_DIRECTORY_HEADER_SIGNATURE
    {
        return Err(ZipError::InvalidArchive("Invalid Central Directory header"))
    }

    try!(reader.read_u16::<LittleEndian>());
    try!(reader.read_u16::<LittleEndian>());
    let flags = try!(reader.read_u16::<LittleEndian>());
    let encrypted = flags & 1 == 1;
    let is_utf8 = flags & (1 << 11) != 0;
    let compression_method = try!(reader.read_u16::<LittleEndian>());
    let last_mod_time = try!(reader.read_u16::<LittleEndian>());
    let last_mod_date = try!(reader.read_u16::<LittleEndian>());
    let crc32 = try!(reader.read_u32::<LittleEndian>());
    let compressed_size = try!(reader.read_u32::<LittleEndian>());
    let uncompressed_size = try!(reader.read_u32::<LittleEndian>());
    let file_name_length = try!(reader.read_u16::<LittleEndian>()) as usize;
    let extra_field_length = try!(reader.read_u16::<LittleEndian>()) as usize;
    let file_comment_length = try!(reader.read_u16::<LittleEndian>()) as usize;
    try!(reader.read_u16::<LittleEndian>());
    try!(reader.read_u16::<LittleEndian>());
    try!(reader.read_u32::<LittleEndian>());
    let offset = try!(reader.read_u32::<LittleEndian>()) as u64;
    let file_name_raw = try!(ReadPodExt::read_exact(reader, file_name_length));
    let extra_field = try!(ReadPodExt::read_exact(reader, extra_field_length));
    let file_comment_raw  = try!(ReadPodExt::read_exact(reader, file_comment_length));

    let file_name = match is_utf8
    {
        true => String::from_utf8_lossy(&*file_name_raw).into_owned(),
        false => file_name_raw.from_cp437(),
    };
    let file_comment = match is_utf8
    {
        true => String::from_utf8_lossy(&*file_comment_raw).into_owned(),
        false => file_comment_raw.from_cp437(),
    };

    // Remember end of central header
    let return_position = try!(reader.seek(io::SeekFrom::Current(0)));

    // Parse local header
    try!(reader.seek(io::SeekFrom::Start(offset)));
    let signature = try!(reader.read_u32::<LittleEndian>());
    if signature != spec::LOCAL_FILE_HEADER_SIGNATURE
    {
        return Err(ZipError::InvalidArchive("Invalid local file header"))
    }

    try!(reader.seek(io::SeekFrom::Current(22)));
    let file_name_length = try!(reader.read_u16::<LittleEndian>()) as u64;
    let extra_field_length = try!(reader.read_u16::<LittleEndian>()) as u64;
    let magic_and_header = 4 + 22 + 2 + 2;
    let data_start = offset + magic_and_header + file_name_length + extra_field_length;

    // Construct the result
    let mut result = ZipFileData
    {
        encrypted: encrypted,
        compression_method: CompressionMethod::from_u16(compression_method),
        last_modified_time: try!(::time::Tm::from_msdos(MsDosDateTime::new(last_mod_time, last_mod_date))),
        crc32: crc32,
        compressed_size: compressed_size as u64,
        uncompressed_size: uncompressed_size as u64,
        file_name: file_name,
        file_comment: file_comment,
        header_start: offset,
        data_start: data_start,
    };

    try!(parse_extra_field(&mut result, &*extra_field));

    // Go back after the central header
    try!(reader.seek(io::SeekFrom::Start(return_position)));

    Ok(result)
}

fn parse_extra_field(_file: &mut ZipFileData, data: &[u8]) -> ZipResult<()>
{
    let mut reader = io::Cursor::new(data);

    while (reader.position() as usize) < data.len()
    {
        let kind = try!(reader.read_u16::<LittleEndian>());
        let len = try!(reader.read_u16::<LittleEndian>());
        match kind
        {
            _ => try!(reader.seek(io::SeekFrom::Current(len as i64))),
        };
    }
    Ok(())
}

/// Methods for retreiving information on zip files
impl<'a> ZipFile<'a> {
    fn get_reader(&mut self) -> &mut Read {
        match self.reader {
           ZipFileReader::Stored(ref mut r) => r as &mut Read,
           ZipFileReader::Deflated(ref mut r) => r as &mut Read,
           #[cfg(feature = "bzip2")]
           ZipFileReader::Bzip2(ref mut r) => r as &mut Read,
        }
    }
    /// Get the name of the file
    pub fn name(&self) -> &str {
        &*self.data.file_name
    }
    /// Get the comment of the file
    pub fn comment(&self) -> &str {
        &*self.data.file_comment
    }
    /// Get the compression method used to store the file
    pub fn compression(&self) -> CompressionMethod {
        self.data.compression_method
    }
    /// Get the size of the file in the archive
    pub fn compressed_size(&self) -> u64 {
        self.data.compressed_size
    }
    /// Get the size of the file when uncompressed
    pub fn size(&self) -> u64 {
        self.data.uncompressed_size
    }
    /// Get the time the file was last modified
    pub fn last_modified(&self) -> ::time::Tm {
        self.data.last_modified_time
    }
}

impl<'a> Read for ZipFile<'a> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.get_reader().read(buf)
     }
}
<commit_msg>Add crc32 accessor for ZipFile<commit_after>//! Structs for reading a ZIP archive

use crc32::Crc32Reader;
use compression::CompressionMethod;
use spec;
use result::{ZipResult, ZipError};
use std::io;
use std::io::prelude::*;
use std::collections::HashMap;
use flate2;
use flate2::FlateReadExt;
use podio::{ReadPodExt, LittleEndian};
use types::ZipFileData;
use cp437::FromCp437;
use msdos_time::{TmMsDosExt, MsDosDateTime};

#[cfg(feature = "bzip2")]
use bzip2::read::BzDecoder;

/// Wrapper for reading the contents of a ZIP file.
///
/// ```
/// fn doit() -> zip::result::ZipResult<()>
/// {
///     use std::io::prelude::*;
///
///     // For demonstration purposes we read from an empty buffer.
///     // Normally a File object would be used.
///     let buf: &[u8] = &[0u8; 128];
///     let mut reader = std::io::Cursor::new(buf);
///
///     let mut zip = try!(zip::ZipArchive::new(reader));
///
///     for i in 0..zip.len()
///     {
///         let mut file = zip.by_index(i).unwrap();
///         println!("Filename: {}", file.name());
///         let first_byte = try!(file.bytes().next().unwrap());
///         println!("{}", first_byte);
///     }
///     Ok(())
/// }
///
/// println!("Result: {:?}", doit());
/// ```
pub struct ZipArchive<R: Read + io::Seek>
{
    reader: R,
    files: Vec<ZipFileData>,
    names_map: HashMap<String, usize>,
}

enum ZipFileReader<'a> {
    Stored(Crc32Reader<io::Take<&'a mut Read>>),
    Deflated(Crc32Reader<flate2::read::DeflateDecoder<io::Take<&'a mut Read>>>),
    #[cfg(feature = "bzip2")]
    Bzip2(Crc32Reader<BzDecoder<io::Take<&'a mut Read>>>),
}

/// A struct for reading a zip file
pub struct ZipFile<'a> {
    data: &'a ZipFileData,
    reader: ZipFileReader<'a>,
}

fn unsupported_zip_error<T>(detail: &'static str) -> ZipResult<T>
{
    Err(ZipError::UnsupportedArchive(detail))
}

impl<R: Read+io::Seek> ZipArchive<R>
{
    /// Opens a Zip archive and parses the central directory
    pub fn new(mut reader: R) -> ZipResult<ZipArchive<R>> {
        let footer = try!(spec::CentralDirectoryEnd::find_and_parse(&mut reader));

        if footer.disk_number != footer.disk_with_central_directory { return unsupported_zip_error("Support for multi-disk files is not implemented") }

        let directory_start = footer.central_directory_offset as u64;
        let number_of_files = footer.number_of_files_on_this_disk as usize;

        let mut files = Vec::with_capacity(number_of_files);
        let mut names_map = HashMap::new();

        try!(reader.seek(io::SeekFrom::Start(directory_start)));
        for _ in 0 .. number_of_files
        {
            let file = try!(central_header_to_zip_file(&mut reader));
            names_map.insert(file.file_name.clone(), files.len());
            files.push(file);
        }

        Ok(ZipArchive { reader: reader, files: files, names_map: names_map })
    }

    /// Number of files contained in this zip.
    ///
    /// ```
    /// fn iter() {
    ///     let mut zip = zip::ZipArchive::new(std::io::Cursor::new(vec![])).unwrap();
    ///
    ///     for i in 0..zip.len() {
    ///         let mut file = zip.by_index(i).unwrap();
    ///         // Do something with file i
    ///     }
    /// }
    /// ```
    pub fn len(&self) -> usize
    {
        self.files.len()
    }

    /// Search for a file entry by name
    pub fn by_name<'a>(&'a mut self, name: &str) -> ZipResult<ZipFile<'a>>
    {
        let index = match self.names_map.get(name) {
            Some(index) => *index,
            None => { return Err(ZipError::FileNotFound); },
        };
        self.by_index(index)
    }

    /// Get a contained file by index
    pub fn by_index<'a>(&'a mut self, file_number: usize) -> ZipResult<ZipFile<'a>>
    {
        if file_number >= self.files.len() { return Err(ZipError::FileNotFound); }
        let ref data = self.files[file_number];
        let pos = data.data_start;

        if data.encrypted
        {
            return unsupported_zip_error("Encrypted files are not supported")
        }

        try!(self.reader.seek(io::SeekFrom::Start(pos)));
        let limit_reader = (self.reader.by_ref() as &mut Read).take(data.compressed_size);

        let reader = match data.compression_method
        {
            CompressionMethod::Stored =>
            {
                ZipFileReader::Stored(Crc32Reader::new(
                    limit_reader,
                    data.crc32))
            },
            CompressionMethod::Deflated =>
            {
                let deflate_reader = limit_reader.deflate_decode();
                ZipFileReader::Deflated(Crc32Reader::new(
                    deflate_reader,
                    data.crc32))
            },
            #[cfg(feature = "bzip2")]
            CompressionMethod::Bzip2 =>
            {
                let bzip2_reader = BzDecoder::new(limit_reader);
                ZipFileReader::Bzip2(Crc32Reader::new(
                    bzip2_reader,
                    data.crc32))
            },
            _ => return unsupported_zip_error("Compression method not supported"),
        };
        Ok(ZipFile { reader: reader, data: data })
    }

    /// Unwrap and return the inner reader object
    ///
    /// The position of the reader is undefined.
    pub fn into_inner(self) -> R
    {
        self.reader
    }
}

fn central_header_to_zip_file<R: Read+io::Seek>(reader: &mut R) -> ZipResult<ZipFileData>
{
    // Parse central header
    let signature = try!(reader.read_u32::<LittleEndian>());
    if signature != spec::CENTRAL_DIRECTORY_HEADER_SIGNATURE
    {
        return Err(ZipError::InvalidArchive("Invalid Central Directory header"))
    }

    try!(reader.read_u16::<LittleEndian>());
    try!(reader.read_u16::<LittleEndian>());
    let flags = try!(reader.read_u16::<LittleEndian>());
    let encrypted = flags & 1 == 1;
    let is_utf8 = flags & (1 << 11) != 0;
    let compression_method = try!(reader.read_u16::<LittleEndian>());
    let last_mod_time = try!(reader.read_u16::<LittleEndian>());
    let last_mod_date = try!(reader.read_u16::<LittleEndian>());
    let crc32 = try!(reader.read_u32::<LittleEndian>());
    let compressed_size = try!(reader.read_u32::<LittleEndian>());
    let uncompressed_size = try!(reader.read_u32::<LittleEndian>());
    let file_name_length = try!(reader.read_u16::<LittleEndian>()) as usize;
    let extra_field_length = try!(reader.read_u16::<LittleEndian>()) as usize;
    let file_comment_length = try!(reader.read_u16::<LittleEndian>()) as usize;
    try!(reader.read_u16::<LittleEndian>());
    try!(reader.read_u16::<LittleEndian>());
    try!(reader.read_u32::<LittleEndian>());
    let offset = try!(reader.read_u32::<LittleEndian>()) as u64;
    let file_name_raw = try!(ReadPodExt::read_exact(reader, file_name_length));
    let extra_field = try!(ReadPodExt::read_exact(reader, extra_field_length));
    let file_comment_raw  = try!(ReadPodExt::read_exact(reader, file_comment_length));

    let file_name = match is_utf8
    {
        true => String::from_utf8_lossy(&*file_name_raw).into_owned(),
        false => file_name_raw.from_cp437(),
    };
    let file_comment = match is_utf8
    {
        true => String::from_utf8_lossy(&*file_comment_raw).into_owned(),
        false => file_comment_raw.from_cp437(),
    };

    // Remember end of central header
    let return_position = try!(reader.seek(io::SeekFrom::Current(0)));

    // Parse local header
    try!(reader.seek(io::SeekFrom::Start(offset)));
    let signature = try!(reader.read_u32::<LittleEndian>());
    if signature != spec::LOCAL_FILE_HEADER_SIGNATURE
    {
        return Err(ZipError::InvalidArchive("Invalid local file header"))
    }

    try!(reader.seek(io::SeekFrom::Current(22)));
    let file_name_length = try!(reader.read_u16::<LittleEndian>()) as u64;
    let extra_field_length = try!(reader.read_u16::<LittleEndian>()) as u64;
    let magic_and_header = 4 + 22 + 2 + 2;
    let data_start = offset + magic_and_header + file_name_length + extra_field_length;

    // Construct the result
    let mut result = ZipFileData
    {
        encrypted: encrypted,
        compression_method: CompressionMethod::from_u16(compression_method),
        last_modified_time: try!(::time::Tm::from_msdos(MsDosDateTime::new(last_mod_time, last_mod_date))),
        crc32: crc32,
        compressed_size: compressed_size as u64,
        uncompressed_size: uncompressed_size as u64,
        file_name: file_name,
        file_comment: file_comment,
        header_start: offset,
        data_start: data_start,
    };

    try!(parse_extra_field(&mut result, &*extra_field));

    // Go back after the central header
    try!(reader.seek(io::SeekFrom::Start(return_position)));

    Ok(result)
}

fn parse_extra_field(_file: &mut ZipFileData, data: &[u8]) -> ZipResult<()>
{
    let mut reader = io::Cursor::new(data);

    while (reader.position() as usize) < data.len()
    {
        let kind = try!(reader.read_u16::<LittleEndian>());
        let len = try!(reader.read_u16::<LittleEndian>());
        match kind
        {
            _ => try!(reader.seek(io::SeekFrom::Current(len as i64))),
        };
    }
    Ok(())
}

/// Methods for retreiving information on zip files
impl<'a> ZipFile<'a> {
    fn get_reader(&mut self) -> &mut Read {
        match self.reader {
           ZipFileReader::Stored(ref mut r) => r as &mut Read,
           ZipFileReader::Deflated(ref mut r) => r as &mut Read,
           #[cfg(feature = "bzip2")]
           ZipFileReader::Bzip2(ref mut r) => r as &mut Read,
        }
    }
    /// Get the name of the file
    pub fn name(&self) -> &str {
        &*self.data.file_name
    }
    /// Get the comment of the file
    pub fn comment(&self) -> &str {
        &*self.data.file_comment
    }
    /// Get the compression method used to store the file
    pub fn compression(&self) -> CompressionMethod {
        self.data.compression_method
    }
    /// Get the size of the file in the archive
    pub fn compressed_size(&self) -> u64 {
        self.data.compressed_size
    }
    /// Get the size of the file when uncompressed
    pub fn size(&self) -> u64 {
        self.data.uncompressed_size
    }
    /// Get the time the file was last modified
    pub fn last_modified(&self) -> ::time::Tm {
        self.data.last_modified_time
    }
    /// Get the CRC32 hash of the original file
    pub fn crc32(&self) -> u32 {
        self.data.crc32
    }
}

impl<'a> Read for ZipFile<'a> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.get_reader().read(buf)
     }
}
<|endoftext|>


<commit_before>// Copyright 2015 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use front::constraint_ast::Constraint;
use middle::semantics::symbol_table::SymbolTable;

trait AlphaConversion
{
  type TargetAST;
  fn convert(self, symbols: &SymbolTable) -> Self::TargetAST;
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AConstraint {
  XEqualY(u32, u32),
  XEqualC(u32, i32),
  XNotEqualY(u32, u32),
  XLessThanY(u32, u32),
}

impl AlphaConversion for Constraint
{
  type TargetAST = AConstraint;

  fn convert(self, symbols: &SymbolTable) -> AConstraint {
    match self {
      Constraint::XEqualY(x, y) => AConstraint::XEqualY(symbols[x], symbols[y]),
      Constraint::XEqualC(x, c) => AConstraint::XEqualC(symbols[x], c),
      Constraint::XNotEqualY(x, y) => AConstraint::XNotEqualY(symbols[x], symbols[y]),
      Constraint::XLessThanY(x, y) => AConstraint::XLessThanY(symbols[x], symbols[y])
    }
  }
}
<commit_msg>Alpha conversion of the entire program.<commit_after>// Copyright 2015 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use front::ast::{Program, Expr};
use front::constraint_ast::Constraint;
use middle::semantics::symbol_table::SymbolTable;

trait AlphaConversion
{
  type TargetAST;
  fn rename(self, symbols: &SymbolTable) -> Self::TargetAST;
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AConstraint {
  XEqualY(u32, u32),
  XEqualC(u32, i32),
  XNotEqualY(u32, u32),
  XLessThanY(u32, u32),
}

impl AlphaConversion for Constraint
{
  type TargetAST = AConstraint;

  fn rename(self, symbols: &SymbolTable) -> AConstraint {
    match self {
      Constraint::XEqualY(x, y) => AConstraint::XEqualY(symbols[x], symbols[y]),
      Constraint::XEqualC(x, c) => AConstraint::XEqualC(symbols[x], c),
      Constraint::XNotEqualY(x, y) => AConstraint::XNotEqualY(symbols[x], symbols[y]),
      Constraint::XLessThanY(x, y) => AConstraint::XLessThanY(symbols[x], symbols[y])
    }
  }
}

pub struct AProgram<C, D>
{
  pub args: Vec<u32>,
  pub def: AExpr<C, D>
}

pub enum AExpr<C, D>
{
  ReactiveSum(Vec<AExpr<C, D>>),
  Parallel(Vec<AExpr<C, D>>),
  Replicate(Box<AExpr<C, D>>),
  When(C, Box<AExpr<C, D>>),
  Unless(C, Box<AExpr<C, D>>),
  Tell(C),
  Next(Box<AExpr<C, D>>),
  Async(Box<AExpr<C, D>>),
  LetIn(u32, D, Box<AExpr<C, D>>)
}

fn alpha_conversion<C, D>(program: Program<C,D>)
  -> AProgram<<C as AlphaConversion>::TargetAST, D>
  where C: AlphaConversion
{
  let mut symbol_table = SymbolTable::new();
  AProgram {
    args: program.args.into_iter()
      .map(|arg| symbol_table.shadow(arg))
      .collect(),
    def: alpha_expr(&mut symbol_table, program.def)
  }
}

fn alpha_expr<C, D>(symbol_table: &mut SymbolTable, expr: Expr<C,D>)
  -> AExpr<<C as AlphaConversion>::TargetAST, D>
  where C: AlphaConversion
{
  match expr {
    Expr::ReactiveSum(exprs) => {
      AExpr::ReactiveSum(exprs.into_iter()
        .map(|expr| alpha_expr(symbol_table, expr))
        .collect())
    }
    Expr::Parallel(exprs) => {
      AExpr::Parallel(exprs.into_iter()
        .map(|expr| alpha_expr(symbol_table, expr))
        .collect())
    }
    Expr::Replicate(expr) => {
      AExpr::Replicate(box alpha_expr(symbol_table, *expr))
    }
    Expr::When(c, expr) => {
      AExpr::When(
        c.rename(symbol_table),
        box alpha_expr(symbol_table, *expr)
      )
    }
    Expr::Unless(c, expr) => {
      AExpr::Unless(
        c.rename(symbol_table),
        box alpha_expr(symbol_table, *expr)
      )
    },
    Expr::Tell(c) => {
      AExpr::Tell(c.rename(symbol_table))
    }
    Expr::Next(expr) => {
      AExpr::Next(box alpha_expr(symbol_table, *expr))
    }
    Expr::Async(expr) => {
      AExpr::Async(box alpha_expr(symbol_table, *expr))
    }
    Expr::LetIn(name, dom, expr) => {
      let uid = symbol_table.shadow(name.clone());
      let expr = box alpha_expr(symbol_table, *expr);
      symbol_table.unshadow(name);
      AExpr::LetIn(uid, dom, expr)
    }
  }
}
<|endoftext|>


<commit_before>use crate::direction::Direction;

pub struct Ship {
    state: ShipState,
    position: Vec<[u8; 2]>,
    dir: Direction,
}

impl Ship {
    pub fn new(pos: Vec<[u8; 2]>) -> Ship {
        let dir = Direction::from_positions(&pos[1], &pos[0]).unwrap();

        Ship {
            state: ShipState::Active,
            position: pos,
            dir: dir,
        }
    }

    pub fn pos(&self) -> &[[u8; 2]] {
        &self.position
    }

    pub fn set_pos(&mut self, pos: Vec<[u8; 2]>) -> Result<(), &'static str> {
        let dir = Direction::from_positions(&pos[1], &pos[0])?;

        self.position = pos;
        self.dir = dir;

        Ok(())
    }

    pub fn dir(&self) -> Direction {
        self.dir
    }

    pub fn len(&self) -> usize {
        self.position.len()
    }

    pub fn is_active(&self) -> bool {
        self.state == ShipState::Active
    }

    pub fn is_sunk(&self) -> bool {
        self.state == ShipState::Sunk
    }

    /// Sets the ship as having been sunk.
    ///
    /// # Errors
    ///
    /// Returns an error if the ship's state is not `ShipState::Active`.
    pub fn set_sunk(&mut self) -> Result<(), &'static str> {
        if self.state != ShipState::Active {
            Err("tried to sink a ship that was not active")
        } else {
            self.state = ShipState::Sunk;

            Ok(())
        }
    }
}

#[derive(PartialEq)]
enum ShipState {
    Placement,
    Active,
    Sunk
}

<commit_msg>Ship: add set_active()<commit_after>use crate::direction::Direction;

pub struct Ship {
    state: ShipState,
    position: Vec<[u8; 2]>,
    dir: Direction,
}

impl Ship {
    pub fn new(pos: Vec<[u8; 2]>) -> Ship {
        let dir = Direction::from_positions(&pos[1], &pos[0]).unwrap();

        Ship {
            state: ShipState::Active,
            position: pos,
            dir: dir,
        }
    }

    pub fn pos(&self) -> &[[u8; 2]] {
        &self.position
    }

    pub fn set_pos(&mut self, pos: Vec<[u8; 2]>) -> Result<(), &'static str> {
        let dir = Direction::from_positions(&pos[1], &pos[0])?;

        self.position = pos;
        self.dir = dir;

        Ok(())
    }

    pub fn dir(&self) -> Direction {
        self.dir
    }

    pub fn len(&self) -> usize {
        self.position.len()
    }

    pub fn is_active(&self) -> bool {
        self.state == ShipState::Active
    }

    /// Sets the ship as active.
    ///
    /// # Errors
    ///
    /// Returns an error if the ship's state is not `ShipState::Placement`.
    pub fn set_active(&mut self) -> Result<(), &'static str> {
        if self.state != ShipState::Placement {
            Err("tried to set a ship as active that wasn't in placement state")
        } else {
            self.state = ShipState::Active;

            Ok(())
        }
    }

    pub fn is_sunk(&self) -> bool {
        self.state == ShipState::Sunk
    }

    /// Sets the ship as having been sunk.
    ///
    /// # Errors
    ///
    /// Returns an error if the ship's state is not `ShipState::Active`.
    pub fn set_sunk(&mut self) -> Result<(), &'static str> {
        if self.state != ShipState::Active {
            Err("tried to sink a ship that was not active")
        } else {
            self.state = ShipState::Sunk;

            Ok(())
        }
    }
}

#[derive(PartialEq)]
enum ShipState {
    Placement,
    Active,
    Sunk
}

<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use rand::Rng;

fn main() {
    println!("Hello in my guessing game!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    println!("Input your guess, please:");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line!");

    println!("Your guess is: {}", guess);
}
<commit_msg>Add comparision between guess and secret_number<commit_after>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Hello in my guessing game!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    println!("Input your guess, please:");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line!");

    let guess: u32 = guess.trim().parse()
        .expect("It's not a valid number :(");

    println!("Your guess is: {}", guess);

    match guess.cmp(&secret_number) {
        Ordering::Less    => println!("Too low!"),
        Ordering::Greater => println!("Too big!"),
        Ordering::Equal   => println!("Great guess! You win!")
    }
}
<|endoftext|>


<commit_before>use floating_duration::TimeFormat;
use regex::Regex;
use std::fs::File;
use std::io::{Write, BufReader, BufRead, BufWriter};
use std::path;
use std::thread;
use std::process;
use term;
use time;

pub trait RunningTask {
    fn done(&mut self) -> bool;
    fn wait(self: Box<Self>);
    fn interrupt(self: Box<Self>);
}

pub trait Runnable {
    fn run(&self) -> Box<RunningTask>;
}

pub trait Task: Runnable {
    fn name(&self) -> String;
    fn should_run(&self, _: &path::Path) -> bool;
    fn start_delay(&self) -> time::Duration;
}

pub trait ShellTask: Task {
    fn command(&self) -> String;
    fn work_directory(&self) -> Option<path::PathBuf>;
    fn redirect_stdout(&self) -> Option<path::PathBuf>;
    fn redirect_stderr(&self) -> Option<path::PathBuf>;
    fn supress_stdout(&self) -> bool;
    fn supress_stderr(&self) -> bool;
}

fn handle_output<R: BufRead, W: Write>(reader: R, echo: bool, mut redirect: Option<BufWriter<W>>) {
    for line in reader.lines() {
        if !line.is_ok() {
            continue;
        }
        let line = line.unwrap();

        // TODO(sirver): My understanding is that \x1b[ should start every ANSI sequence, but I
        // also see \x1b( in my outputs - so I filtered that too. Figure out a more principled way
        // of removing color.
        // for now this is lifted from chalk/ansi-regex.
        lazy_static! {
            static ref REMOVE_ANSI: Regex = Regex::new("[\u{1b}\u{9b}][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]").unwrap();
            static ref REMOVE_SHIFT_INOUT: Regex = Regex::new("[\u{0e}\u{0f}]").unwrap();
        }
        let no_color = REMOVE_ANSI.replace_all(&line, "");
        let no_shift = REMOVE_SHIFT_INOUT.replace_all(&no_color, "");
        redirect.as_mut().map(|w| writeln!(w, "{}", no_shift).unwrap());
        if echo {
            println!("{}", line);
        }
    }
}

struct RunningShellTask {
    child: process::Child,
    start_time: time::PreciseTime,
    done: bool,
    name: String,
    io_threads: Vec<thread::JoinHandle<()>>,
}

impl RunningShellTask {
    pub fn spawn(command: &str,
                 name: String,
                 work_directory: Option<path::PathBuf>,
                 echo_stdout: bool,
                 redirect_stdout: Option<path::PathBuf>,
                 echo_stderr: bool,
                 redirect_stderr: Option<path::PathBuf>)
                 -> Self {
        let args = command.split_whitespace().collect::<Vec<&str>>();
        let mut terminal = term::stdout().unwrap();
        terminal.fg(term::color::CYAN).unwrap();
        write!(terminal, "\x1b[2J").unwrap(); // Clear the screen.
        writeln!(terminal, "==> {}", name).unwrap();
        terminal.reset().unwrap();
        terminal.flush().unwrap();

        let start_time = time::PreciseTime::now();

        let mut child = {
            let mut child = process::Command::new(args[0]);

            child.args(&args[1..])
                .stdin(process::Stdio::inherit())
                .stdout(process::Stdio::piped())
                .stderr(process::Stdio::piped());

            if let Some(path) = work_directory {
                child.current_dir(path);
            }
            child.spawn().unwrap_or_else(|e| panic!("failed to execute: {}", e))
        };

        let mut io_threads = Vec::new();
        let stdout = BufReader::new(child.stdout.take().unwrap());
        let redirect_stdout =
            redirect_stdout.map(|path| BufWriter::new(File::create(path).unwrap()));
        io_threads.push(thread::spawn(move || {
            handle_output(stdout, echo_stdout, redirect_stdout);
        }));
        let stderr = BufReader::new(child.stderr.take().unwrap());
        let redirect_stderr =
            redirect_stderr.map(|path| BufWriter::new(File::create(path).unwrap()));
        io_threads.push(thread::spawn(move || {
            handle_output(stderr, echo_stderr, redirect_stderr);
        }));

        RunningShellTask {
            start_time,
            name,
            child,
            done: false,
            io_threads: io_threads,
        }
    }

    fn finish(&mut self, success: bool) {
        self.done = true;

        let duration = self.start_time
            .to(time::PreciseTime::now())
            .to_std()
            .unwrap();
        let mut terminal = term::stdout().unwrap();
        terminal.fg(term::color::CYAN).unwrap();
        write!(terminal, "==> {}: ", self.name).unwrap();
        terminal.reset().unwrap();
        if success {
            terminal.fg(term::color::GREEN).unwrap();
            write!(terminal, "Success. ").unwrap();
        } else {
            terminal.fg(term::color::RED).unwrap();
            write!(terminal, "Failed. ").unwrap();
        }
        terminal.reset().unwrap();
        write!(terminal, "({})", TimeFormat(duration)).unwrap();
        writeln!(terminal, "").unwrap();
    }
}

impl Drop for RunningShellTask {
    fn drop(&mut self) {
        for handle in self.io_threads.drain(..) {
            handle.join().unwrap();
        }
    }
}

impl RunningTask for RunningShellTask {
    fn done(&mut self) -> bool {
        if self.done {
            return true;
        }

        let success = match self.child.try_wait().expect("try_wait") {
            Some(status) => status.success(),
            None => return false,
        };
        self.finish(success);
        true
    }

    fn wait(mut self: Box<Self>) {
        if self.done {
            return;
        }
        self.child.wait().expect("wait");
    }

    fn interrupt(mut self: Box<Self>) {
        if self.done {
            return;
        }
        self.child.kill().unwrap()
    }
}

impl<T: ShellTask> Runnable for T {
    /// Dispatches to 'program' with 'str'.
    fn run(&self) -> Box<RunningTask> {
        Box::new(RunningShellTask::spawn(&self.command(),
                                         self.name(),
                                         self.work_directory(),
                                         !self.supress_stdout(),
                                         self.redirect_stdout(),
                                         !self.supress_stderr(),
                                         self.redirect_stderr()))
    }
}
<commit_msg>Decreased writer buffer size to get faster feedback in the new file.<commit_after>use floating_duration::TimeFormat;
use regex::Regex;
use std::fs::File;
use std::io::{Write, BufReader, BufRead, BufWriter};
use std::path;
use std::thread;
use std::process;
use term;
use time;

pub trait RunningTask {
    fn done(&mut self) -> bool;
    fn wait(self: Box<Self>);
    fn interrupt(self: Box<Self>);
}

pub trait Runnable {
    fn run(&self) -> Box<RunningTask>;
}

pub trait Task: Runnable {
    fn name(&self) -> String;
    fn should_run(&self, _: &path::Path) -> bool;
    fn start_delay(&self) -> time::Duration;
}

pub trait ShellTask: Task {
    fn command(&self) -> String;
    fn work_directory(&self) -> Option<path::PathBuf>;
    fn redirect_stdout(&self) -> Option<path::PathBuf>;
    fn redirect_stderr(&self) -> Option<path::PathBuf>;
    fn supress_stdout(&self) -> bool;
    fn supress_stderr(&self) -> bool;
}

fn handle_output<R: BufRead, W: Write>(reader: R, echo: bool, mut redirect: Option<BufWriter<W>>) {
    for line in reader.lines() {
        if !line.is_ok() {
            continue;
        }
        let line = line.unwrap();

        // TODO(sirver): My understanding is that \x1b[ should start every ANSI sequence, but I
        // also see \x1b( in my outputs - so I filtered that too. Figure out a more principled way
        // of removing color.
        // for now this is lifted from chalk/ansi-regex.
        lazy_static! {
            static ref REMOVE_ANSI: Regex = Regex::new("[\u{1b}\u{9b}][\\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]").unwrap();
            static ref REMOVE_SHIFT_INOUT: Regex = Regex::new("[\u{0e}\u{0f}]").unwrap();
        }
        let no_color = REMOVE_ANSI.replace_all(&line, "");
        let no_shift = REMOVE_SHIFT_INOUT.replace_all(&no_color, "");
        redirect.as_mut().map(|w| writeln!(w, "{}", no_shift).unwrap());
        if echo {
            println!("{}", line);
        }
    }
}

struct RunningShellTask {
    child: process::Child,
    start_time: time::PreciseTime,
    done: bool,
    name: String,
    io_threads: Vec<thread::JoinHandle<()>>,
}

impl RunningShellTask {
    pub fn spawn(command: &str,
                 name: String,
                 work_directory: Option<path::PathBuf>,
                 echo_stdout: bool,
                 redirect_stdout: Option<path::PathBuf>,
                 echo_stderr: bool,
                 redirect_stderr: Option<path::PathBuf>)
                 -> Self {
        let args = command.split_whitespace().collect::<Vec<&str>>();
        let mut terminal = term::stdout().unwrap();
        terminal.fg(term::color::CYAN).unwrap();
        write!(terminal, "\x1b[2J").unwrap(); // Clear the screen.
        writeln!(terminal, "==> {}", name).unwrap();
        terminal.reset().unwrap();
        terminal.flush().unwrap();

        let start_time = time::PreciseTime::now();

        let mut child = {
            let mut child = process::Command::new(args[0]);

            child.args(&args[1..])
                .stdin(process::Stdio::inherit())
                .stdout(process::Stdio::piped())
                .stderr(process::Stdio::piped());

            if let Some(path) = work_directory {
                child.current_dir(path);
            }
            child.spawn().unwrap_or_else(|e| panic!("failed to execute: {}", e))
        };

        let mut io_threads = Vec::new();
        let stdout = BufReader::new(child.stdout.take().unwrap());
        let redirect_stdout =
            redirect_stdout.map(|path| BufWriter::with_capacity(4096, File::create(path).unwrap()));
        io_threads.push(thread::spawn(move || {
            handle_output(stdout, echo_stdout, redirect_stdout);
        }));
        let stderr = BufReader::new(child.stderr.take().unwrap());
        let redirect_stderr =
            redirect_stderr.map(|path| BufWriter::with_capacity(4096, File::create(path).unwrap()));
        io_threads.push(thread::spawn(move || {
            handle_output(stderr, echo_stderr, redirect_stderr);
        }));

        RunningShellTask {
            start_time,
            name,
            child,
            done: false,
            io_threads: io_threads,
        }
    }

    fn finish(&mut self, success: bool) {
        self.done = true;

        let duration = self.start_time
            .to(time::PreciseTime::now())
            .to_std()
            .unwrap();
        let mut terminal = term::stdout().unwrap();
        terminal.fg(term::color::CYAN).unwrap();
        write!(terminal, "==> {}: ", self.name).unwrap();
        terminal.reset().unwrap();
        if success {
            terminal.fg(term::color::GREEN).unwrap();
            write!(terminal, "Success. ").unwrap();
        } else {
            terminal.fg(term::color::RED).unwrap();
            write!(terminal, "Failed. ").unwrap();
        }
        terminal.reset().unwrap();
        write!(terminal, "({})", TimeFormat(duration)).unwrap();
        writeln!(terminal, "").unwrap();
    }
}

impl Drop for RunningShellTask {
    fn drop(&mut self) {
        for handle in self.io_threads.drain(..) {
            handle.join().unwrap();
        }
    }
}

impl RunningTask for RunningShellTask {
    fn done(&mut self) -> bool {
        if self.done {
            return true;
        }

        let success = match self.child.try_wait().expect("try_wait") {
            Some(status) => status.success(),
            None => return false,
        };
        self.finish(success);
        true
    }

    fn wait(mut self: Box<Self>) {
        if self.done {
            return;
        }
        self.child.wait().expect("wait");
    }

    fn interrupt(mut self: Box<Self>) {
        if self.done {
            return;
        }
        self.child.kill().unwrap()
    }
}

impl<T: ShellTask> Runnable for T {
    /// Dispatches to 'program' with 'str'.
    fn run(&self) -> Box<RunningTask> {
        Box::new(RunningShellTask::spawn(&self.command(),
                                         self.name(),
                                         self.work_directory(),
                                         !self.supress_stdout(),
                                         self.redirect_stdout(),
                                         !self.supress_stderr(),
                                         self.redirect_stderr()))
    }
}
<|endoftext|>