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

use std::{
    fmt::Debug,
    sync::{Once, ONCE_INIT},
};

use crate::engine::{
    types::{BlockDevState, FreeSpaceState, PoolExtendState, PoolState},
    MaybeDbusPath,
};

static INIT: Once = ONCE_INIT;
static mut ENGINE_LISTENER_LIST: Option<EngineListenerList> = None;

#[derive(Debug, Clone)]
pub enum EngineEvent<'a> {
    BlockdevStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: BlockDevState,
    },
    FilesystemRenamed {
        dbus_path: &'a MaybeDbusPath,
        from: &'a str,
        to: &'a str,
    },
    PoolExtendStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: PoolExtendState,
    },
    PoolRenamed {
        dbus_path: &'a MaybeDbusPath,
        from: &'a str,
        to: &'a str,
    },
    PoolSpaceStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: FreeSpaceState,
    },
    PoolStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: PoolState,
    },
}

pub trait EngineListener: Debug {
    fn notify(&self, event: &EngineEvent);
}

#[derive(Debug)]
pub struct EngineListenerList {
    listeners: Vec<Box<dyn EngineListener>>,
}

impl EngineListenerList {
    /// Create a new EngineListenerList.
    fn new() -> EngineListenerList {
        EngineListenerList {
            listeners: Vec::new(),
        }
    }

    /// Add a listener.
    pub fn register_listener(&mut self, listener: Box<dyn EngineListener>) {
        self.listeners.push(listener);
    }

    /// Notify a listener.
    pub fn notify(&self, event: &EngineEvent) {
        for listener in &self.listeners {
            listener.notify(&event);
        }
    }
}

pub fn get_engine_listener_list() -> &'static EngineListenerList {
    unsafe {
        INIT.call_once(|| ENGINE_LISTENER_LIST = Some(EngineListenerList::new()));
        match ENGINE_LISTENER_LIST {
            Some(ref ell) => ell,
            _ => panic!("ENGINE_LISTENER_LIST is None"),
        }
    }
}

pub fn get_engine_listener_list_mut() -> &'static mut EngineListenerList {
    unsafe {
        INIT.call_once(|| ENGINE_LISTENER_LIST = Some(EngineListenerList::new()));
        match ENGINE_LISTENER_LIST {
            Some(ref mut ell) => ell,
            _ => panic!("ENGINE_LISTENER_LIST is None"),
        }
    }
}
<commit_msg>Fix a comment<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::{
    fmt::Debug,
    sync::{Once, ONCE_INIT},
};

use crate::engine::{
    types::{BlockDevState, FreeSpaceState, PoolExtendState, PoolState},
    MaybeDbusPath,
};

static INIT: Once = ONCE_INIT;
static mut ENGINE_LISTENER_LIST: Option<EngineListenerList> = None;

#[derive(Debug, Clone)]
pub enum EngineEvent<'a> {
    BlockdevStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: BlockDevState,
    },
    FilesystemRenamed {
        dbus_path: &'a MaybeDbusPath,
        from: &'a str,
        to: &'a str,
    },
    PoolExtendStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: PoolExtendState,
    },
    PoolRenamed {
        dbus_path: &'a MaybeDbusPath,
        from: &'a str,
        to: &'a str,
    },
    PoolSpaceStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: FreeSpaceState,
    },
    PoolStateChanged {
        dbus_path: &'a MaybeDbusPath,
        state: PoolState,
    },
}

pub trait EngineListener: Debug {
    fn notify(&self, event: &EngineEvent);
}

#[derive(Debug)]
pub struct EngineListenerList {
    listeners: Vec<Box<dyn EngineListener>>,
}

impl EngineListenerList {
    /// Create a new EngineListenerList.
    fn new() -> EngineListenerList {
        EngineListenerList {
            listeners: Vec::new(),
        }
    }

    /// Add a listener.
    pub fn register_listener(&mut self, listener: Box<dyn EngineListener>) {
        self.listeners.push(listener);
    }

    /// Notify all listeners of the event.
    pub fn notify(&self, event: &EngineEvent) {
        for listener in &self.listeners {
            listener.notify(&event);
        }
    }
}

pub fn get_engine_listener_list() -> &'static EngineListenerList {
    unsafe {
        INIT.call_once(|| ENGINE_LISTENER_LIST = Some(EngineListenerList::new()));
        match ENGINE_LISTENER_LIST {
            Some(ref ell) => ell,
            _ => panic!("ENGINE_LISTENER_LIST is None"),
        }
    }
}

pub fn get_engine_listener_list_mut() -> &'static mut EngineListenerList {
    unsafe {
        INIT.call_once(|| ENGINE_LISTENER_LIST = Some(EngineListenerList::new()));
        match ENGINE_LISTENER_LIST {
            Some(ref mut ell) => ell,
            _ => panic!("ENGINE_LISTENER_LIST is None"),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Serde Developers
//
// 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.

#[macro_use]
extern crate serde_derive;

#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
//~^ HELP: #[serde(flatten)] cannot be used within enums
enum Foo {
    A {
        #[serde(flatten)]
        fields: HashMap<String, String>,
    }
}

fn main() {}
<commit_msg>Remove old flatten in enum compile-fail test<commit_after><|endoftext|>


<commit_before>// Copyright 2021 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::collections::VecDeque;
use std::io::{self, stdin};
use std::ops::DerefMut;
use std::path::PathBuf;
use std::sync::Arc;

use anyhow::{anyhow, bail, Context};
use base::{error, warn, Event, RawDescriptor, Terminal};
use cros_async::{EventAsync, Executor};
use data_model::DataInit;

use argh::FromArgs;
use futures::future::{AbortHandle, Abortable};
use hypervisor::ProtectionType;
use sync::Mutex;
use vm_memory::GuestMemory;
use vmm_vhost::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};

use crate::serial_device::{SerialDevice, SerialHardware, SerialParameters, SerialType};
use crate::virtio::console::{
    handle_input, process_transmit_queue, spawn_input_thread, virtio_console_config, ConsoleError,
};
use crate::virtio::vhost::user::device::handler::{
    DeviceRequestHandler, Doorbell, VhostUserBackend,
};
use crate::virtio::{self, copy_config};

async fn run_tx_queue(
    mut queue: virtio::Queue,
    mem: GuestMemory,
    doorbell: Arc<Mutex<Doorbell>>,
    kick_evt: EventAsync,
    mut output: Box<dyn io::Write>,
) {
    loop {
        if let Err(e) = kick_evt.next_val().await {
            error!("Failed to read kick event for tx queue: {}", e);
            break;
        }
        process_transmit_queue(&mem, &doorbell, &mut queue, &mut output);
    }
}

async fn run_rx_queue(
    mut queue: virtio::Queue,
    mem: GuestMemory,
    doorbell: Arc<Mutex<Doorbell>>,
    kick_evt: EventAsync,
    in_buffer: Arc<Mutex<VecDeque<u8>>>,
    in_avail_evt: EventAsync,
) {
    loop {
        if let Err(e) = in_avail_evt.next_val().await {
            error!("Failed reading in_avail_evt: {}", e);
            break;
        }
        match handle_input(&mem, &doorbell, in_buffer.lock().deref_mut(), &mut queue) {
            Ok(()) => {}
            Err(ConsoleError::RxDescriptorsExhausted) => {
                if let Err(e) = kick_evt.next_val().await {
                    error!("Failed to read kick event for rx queue: {}", e);
                    break;
                }
            }
        }
    }
}

struct ConsoleDevice {
    input: Option<Box<dyn io::Read + Send>>,
    output: Option<Box<dyn io::Write + Send>>,
    avail_features: u64,
}

impl SerialDevice for ConsoleDevice {
    fn new(
        protected_vm: ProtectionType,
        _evt: Event,
        input: Option<Box<dyn io::Read + Send>>,
        output: Option<Box<dyn io::Write + Send>>,
        _keep_rds: Vec<RawDescriptor>,
    ) -> ConsoleDevice {
        let avail_features = 1u64 << crate::virtio::VIRTIO_F_VERSION_1
            | virtio::base_features(protected_vm)
            | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
        ConsoleDevice {
            input,
            output,
            avail_features,
        }
    }
}

struct ConsoleBackend {
    ex: Executor,
    device: ConsoleDevice,
    acked_features: u64,
    acked_protocol_features: VhostUserProtocolFeatures,
    workers: [Option<AbortHandle>; Self::MAX_QUEUE_NUM],
}

impl ConsoleBackend {
    fn new(ex: &Executor, device: ConsoleDevice) -> Self {
        Self {
            ex: ex.clone(),
            device,
            acked_features: 0,
            acked_protocol_features: VhostUserProtocolFeatures::empty(),
            workers: Default::default(),
        }
    }
}

impl VhostUserBackend for ConsoleBackend {
    const MAX_QUEUE_NUM: usize = 2; /* transmit and receive queues */
    const MAX_VRING_LEN: u16 = 256;

    type Error = anyhow::Error;

    fn features(&self) -> u64 {
        self.device.avail_features
    }

    fn ack_features(&mut self, value: u64) -> anyhow::Result<()> {
        let unrequested_features = value & !self.device.avail_features;
        if unrequested_features != 0 {
            bail!("invalid features are given: {:#x}", unrequested_features);
        }

        self.acked_features |= value;

        Ok(())
    }

    fn acked_features(&self) -> u64 {
        self.acked_features
    }

    fn protocol_features(&self) -> VhostUserProtocolFeatures {
        VhostUserProtocolFeatures::CONFIG
    }

    fn ack_protocol_features(&mut self, features: u64) -> anyhow::Result<()> {
        let features = VhostUserProtocolFeatures::from_bits(features)
            .ok_or_else(|| anyhow!("invalid protocol features are given: {:#x}", features))?;
        let supported = self.protocol_features();
        self.acked_protocol_features = features & supported;
        Ok(())
    }

    fn acked_protocol_features(&self) -> u64 {
        self.acked_protocol_features.bits()
    }

    fn read_config(&self, offset: u64, data: &mut [u8]) {
        let config = virtio_console_config {
            max_nr_ports: 1.into(),
            ..Default::default()
        };
        copy_config(data, 0, config.as_slice(), offset);
    }

    fn reset(&mut self) {
        for handle in self.workers.iter_mut().filter_map(Option::take) {
            handle.abort();
        }
    }

    fn start_queue(
        &mut self,
        idx: usize,
        mut queue: virtio::Queue,
        mem: GuestMemory,
        doorbell: Arc<Mutex<Doorbell>>,
        kick_evt: Event,
    ) -> anyhow::Result<()> {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            warn!("Starting new queue handler without stopping old handler");
            handle.abort();
        }

        // Enable any virtqueue features that were negotiated (like VIRTIO_RING_F_EVENT_IDX).
        queue.ack_features(self.acked_features);

        let kick_evt = EventAsync::new(kick_evt.0, &self.ex)
            .context("Failed to create EventAsync for kick_evt")?;
        let (handle, registration) = AbortHandle::new_pair();
        match idx {
            // ReceiveQueue
            0 => {
                // See explanation in devices/src/virtio/console.rs
                // We need a multithreaded input polling because io::Read only provides
                // a blocking interface which we cannot use in an async function.
                let in_avail_evt = match Event::new() {
                    Ok(evt) => evt,
                    Err(e) => {
                        bail!("Failed creating Event: {}", e);
                    }
                };

                let input_unpacked = self
                    .device
                    .input
                    .take()
                    .ok_or_else(|| anyhow!("input source unavailable"))?;
                let in_buffer = spawn_input_thread(input_unpacked, &in_avail_evt)
                    .take()
                    .ok_or_else(|| anyhow!("input channel unavailable"))?;

                // Create the async 'in' event so we can await on it.
                let in_avail_async_evt = EventAsync::new(in_avail_evt.0, &self.ex)
                    .context("Failed to create EventAsync for in_avail_evt")?;

                self.ex
                    .spawn_local(Abortable::new(
                        run_rx_queue(
                            queue,
                            mem,
                            doorbell,
                            kick_evt,
                            in_buffer,
                            in_avail_async_evt,
                        ),
                        registration,
                    ))
                    .detach();
            }
            // TransmitQueue
            1 => {
                // Take ownership of output writer.
                // Safe because output should always be initialized to something
                let output_unwrapped: Box<dyn io::Write + Send> = self
                    .device
                    .output
                    .take()
                    .ok_or_else(|| anyhow!("no output available"))?;
                self.ex
                    .spawn_local(Abortable::new(
                        run_tx_queue(queue, mem, doorbell, kick_evt, output_unwrapped),
                        registration,
                    ))
                    .detach();
            }
            _ => bail!("attempted to start unknown queue: {}", idx),
        }

        self.workers[idx] = Some(handle);
        Ok(())
    }

    fn stop_queue(&mut self, idx: usize) {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            handle.abort();
        }
    }
}

fn run_console(params: &SerialParameters, socket: &str) -> anyhow::Result<()> {
    // We need to pass an event as per Serial Device API but we don't really use it anyway.
    let evt = Event::new()?;
    // Same for keep_rds, we don't really use this.
    let mut keep_rds = Vec::new();
    let console = match params.create_serial_device::<ConsoleDevice>(
        ProtectionType::Unprotected,
        &evt,
        &mut keep_rds,
    ) {
        Ok(c) => c,
        Err(e) => bail!(e),
    };

    let ex = Executor::new().context("Failed to create executor")?;
    let backend = ConsoleBackend::new(&ex, console);

    let handler = DeviceRequestHandler::new(backend);

    // run_until() returns an Result<Result<..>> which the ? operator lets us flatten.
    ex.run_until(handler.run(socket, &ex))?
}

#[derive(FromArgs)]
#[argh(description = "")]
struct Options {
    #[argh(option, description = "path to a socket", arg_name = "PATH")]
    socket: String,
    #[argh(option, description = "path to a file", arg_name = "OUTFILE")]
    output_file: Option<PathBuf>,
    #[argh(option, description = "path to a file", arg_name = "INFILE")]
    input_file: Option<PathBuf>,
}

/// Starts a vhost-user console device.
/// Returns an error if the given `args` is invalid or the device fails to run.
pub fn run_console_device(program_name: &str, args: &[&str]) -> anyhow::Result<()> {
    let Options {
        input_file,
        output_file,
        socket,
    } = match Options::from_args(&[program_name], args) {
        Ok(opts) => opts,
        Err(e) => {
            if e.status.is_err() {
                bail!(e.output);
            } else {
                println!("{}", e.output);
            }
            return Ok(());
        }
    };

    // Set stdin() in raw mode so we can send over individual keystrokes unbuffered
    stdin()
        .set_raw_mode()
        .context("Failed to set terminal raw mode")?;

    let type_ = match output_file {
        Some(_) => SerialType::File,
        None => SerialType::Stdout,
    };

    let params = SerialParameters {
        type_,
        hardware: SerialHardware::VirtioConsole,
        // Required only if type_ is SerialType::File or SerialType::UnixSocket
        path: output_file,
        input: input_file,
        num: 1,
        console: true,
        earlycon: false,
        // We do not support stdin-less mode
        stdin: true,
    };

    let res = run_console(&params, &socket);

    // Restore terminal capabilities back to what they were before
    stdin()
        .set_canon_mode()
        .context("Failed to restore canonical mode for terminal")?;

    if let Err(e) = res {
        bail!("error occurred: {:#}", e);
    }

    Ok(())
}
<commit_msg>devices: vhost-user: console: support VVU<commit_after>// Copyright 2021 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::collections::VecDeque;
use std::io::{self, stdin};
use std::ops::DerefMut;
use std::path::PathBuf;
use std::sync::Arc;

use anyhow::{anyhow, bail, Context};
use base::{error, warn, Event, RawDescriptor, Terminal};
use cros_async::{EventAsync, Executor};
use data_model::DataInit;

use argh::FromArgs;
use futures::future::{AbortHandle, Abortable};
use hypervisor::ProtectionType;
use sync::Mutex;
use vm_memory::GuestMemory;
use vmm_vhost::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};

use crate::serial_device::{SerialDevice, SerialHardware, SerialParameters, SerialType};
use crate::virtio::console::{
    handle_input, process_transmit_queue, spawn_input_thread, virtio_console_config, ConsoleError,
};
use crate::virtio::vhost::user::device::handler::{
    DeviceRequestHandler, Doorbell, VhostUserBackend,
};
use crate::virtio::vhost::user::device::vvu::pci::VvuPciDevice;
use crate::virtio::{self, copy_config};

async fn run_tx_queue(
    mut queue: virtio::Queue,
    mem: GuestMemory,
    doorbell: Arc<Mutex<Doorbell>>,
    kick_evt: EventAsync,
    mut output: Box<dyn io::Write>,
) {
    loop {
        if let Err(e) = kick_evt.next_val().await {
            error!("Failed to read kick event for tx queue: {}", e);
            break;
        }
        process_transmit_queue(&mem, &doorbell, &mut queue, &mut output);
    }
}

async fn run_rx_queue(
    mut queue: virtio::Queue,
    mem: GuestMemory,
    doorbell: Arc<Mutex<Doorbell>>,
    kick_evt: EventAsync,
    in_buffer: Arc<Mutex<VecDeque<u8>>>,
    in_avail_evt: EventAsync,
) {
    loop {
        if let Err(e) = in_avail_evt.next_val().await {
            error!("Failed reading in_avail_evt: {}", e);
            break;
        }
        match handle_input(&mem, &doorbell, in_buffer.lock().deref_mut(), &mut queue) {
            Ok(()) => {}
            Err(ConsoleError::RxDescriptorsExhausted) => {
                if let Err(e) = kick_evt.next_val().await {
                    error!("Failed to read kick event for rx queue: {}", e);
                    break;
                }
            }
        }
    }
}

struct ConsoleDevice {
    input: Option<Box<dyn io::Read + Send>>,
    output: Option<Box<dyn io::Write + Send>>,
    avail_features: u64,
}

impl SerialDevice for ConsoleDevice {
    fn new(
        protected_vm: ProtectionType,
        _evt: Event,
        input: Option<Box<dyn io::Read + Send>>,
        output: Option<Box<dyn io::Write + Send>>,
        _keep_rds: Vec<RawDescriptor>,
    ) -> ConsoleDevice {
        let avail_features = 1u64 << crate::virtio::VIRTIO_F_VERSION_1
            | virtio::base_features(protected_vm)
            | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
        ConsoleDevice {
            input,
            output,
            avail_features,
        }
    }
}

struct ConsoleBackend {
    ex: Executor,
    device: ConsoleDevice,
    acked_features: u64,
    acked_protocol_features: VhostUserProtocolFeatures,
    workers: [Option<AbortHandle>; Self::MAX_QUEUE_NUM],
}

impl ConsoleBackend {
    fn new(ex: &Executor, device: ConsoleDevice) -> Self {
        Self {
            ex: ex.clone(),
            device,
            acked_features: 0,
            acked_protocol_features: VhostUserProtocolFeatures::empty(),
            workers: Default::default(),
        }
    }
}

impl VhostUserBackend for ConsoleBackend {
    const MAX_QUEUE_NUM: usize = 2; /* transmit and receive queues */
    const MAX_VRING_LEN: u16 = 256;

    type Error = anyhow::Error;

    fn features(&self) -> u64 {
        self.device.avail_features
    }

    fn ack_features(&mut self, value: u64) -> anyhow::Result<()> {
        let unrequested_features = value & !self.device.avail_features;
        if unrequested_features != 0 {
            bail!("invalid features are given: {:#x}", unrequested_features);
        }

        self.acked_features |= value;

        Ok(())
    }

    fn acked_features(&self) -> u64 {
        self.acked_features
    }

    fn protocol_features(&self) -> VhostUserProtocolFeatures {
        VhostUserProtocolFeatures::CONFIG
    }

    fn ack_protocol_features(&mut self, features: u64) -> anyhow::Result<()> {
        let features = VhostUserProtocolFeatures::from_bits(features)
            .ok_or_else(|| anyhow!("invalid protocol features are given: {:#x}", features))?;
        let supported = self.protocol_features();
        self.acked_protocol_features = features & supported;
        Ok(())
    }

    fn acked_protocol_features(&self) -> u64 {
        self.acked_protocol_features.bits()
    }

    fn read_config(&self, offset: u64, data: &mut [u8]) {
        let config = virtio_console_config {
            max_nr_ports: 1.into(),
            ..Default::default()
        };
        copy_config(data, 0, config.as_slice(), offset);
    }

    fn reset(&mut self) {
        for handle in self.workers.iter_mut().filter_map(Option::take) {
            handle.abort();
        }
    }

    fn start_queue(
        &mut self,
        idx: usize,
        mut queue: virtio::Queue,
        mem: GuestMemory,
        doorbell: Arc<Mutex<Doorbell>>,
        kick_evt: Event,
    ) -> anyhow::Result<()> {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            warn!("Starting new queue handler without stopping old handler");
            handle.abort();
        }

        // Enable any virtqueue features that were negotiated (like VIRTIO_RING_F_EVENT_IDX).
        queue.ack_features(self.acked_features);

        let kick_evt = EventAsync::new(kick_evt.0, &self.ex)
            .context("Failed to create EventAsync for kick_evt")?;
        let (handle, registration) = AbortHandle::new_pair();
        match idx {
            // ReceiveQueue
            0 => {
                // See explanation in devices/src/virtio/console.rs
                // We need a multithreaded input polling because io::Read only provides
                // a blocking interface which we cannot use in an async function.
                let in_avail_evt = match Event::new() {
                    Ok(evt) => evt,
                    Err(e) => {
                        bail!("Failed creating Event: {}", e);
                    }
                };

                let input_unpacked = self
                    .device
                    .input
                    .take()
                    .ok_or_else(|| anyhow!("input source unavailable"))?;
                let in_buffer = spawn_input_thread(input_unpacked, &in_avail_evt)
                    .take()
                    .ok_or_else(|| anyhow!("input channel unavailable"))?;

                // Create the async 'in' event so we can await on it.
                let in_avail_async_evt = EventAsync::new(in_avail_evt.0, &self.ex)
                    .context("Failed to create EventAsync for in_avail_evt")?;

                self.ex
                    .spawn_local(Abortable::new(
                        run_rx_queue(
                            queue,
                            mem,
                            doorbell,
                            kick_evt,
                            in_buffer,
                            in_avail_async_evt,
                        ),
                        registration,
                    ))
                    .detach();
            }
            // TransmitQueue
            1 => {
                // Take ownership of output writer.
                // Safe because output should always be initialized to something
                let output_unwrapped: Box<dyn io::Write + Send> = self
                    .device
                    .output
                    .take()
                    .ok_or_else(|| anyhow!("no output available"))?;
                self.ex
                    .spawn_local(Abortable::new(
                        run_tx_queue(queue, mem, doorbell, kick_evt, output_unwrapped),
                        registration,
                    ))
                    .detach();
            }
            _ => bail!("attempted to start unknown queue: {}", idx),
        }

        self.workers[idx] = Some(handle);
        Ok(())
    }

    fn stop_queue(&mut self, idx: usize) {
        if let Some(handle) = self.workers.get_mut(idx).and_then(Option::take) {
            handle.abort();
        }
    }
}

#[derive(FromArgs)]
#[argh(description = "")]
struct Options {
    #[argh(option, description = "path to a vhost-user socket", arg_name = "PATH")]
    socket: Option<String>,
    #[argh(
        option,
        description = "VFIO-PCI device name (e.g. '0000:00:07.0')",
        arg_name = "STRING"
    )]
    vfio: Option<String>,
    #[argh(option, description = "path to a file", arg_name = "OUTFILE")]
    output_file: Option<PathBuf>,
    #[argh(option, description = "path to a file", arg_name = "INFILE")]
    input_file: Option<PathBuf>,
}

/// Starts a vhost-user console device.
/// Returns an error if the given `args` is invalid or the device fails to run.
pub fn run_console_device(program_name: &str, args: &[&str]) -> anyhow::Result<()> {
    let opts = match Options::from_args(&[program_name], args) {
        Ok(opts) => opts,
        Err(e) => {
            if e.status.is_err() {
                bail!(e.output);
            } else {
                println!("{}", e.output);
            }
            return Ok(());
        }
    };

    let type_ = match opts.output_file {
        Some(_) => SerialType::File,
        None => SerialType::Stdout,
    };

    let params = SerialParameters {
        type_,
        hardware: SerialHardware::VirtioConsole,
        // Required only if type_ is SerialType::File or SerialType::UnixSocket
        path: opts.output_file,
        input: opts.input_file,
        num: 1,
        console: true,
        earlycon: false,
        // We do not support stdin-less mode
        stdin: true,
    };

    let console = match params.create_serial_device::<ConsoleDevice>(
        ProtectionType::Unprotected,
        // We need to pass an event as per Serial Device API but we don't really use it anyway.
        &Event::new()?,
        // Same for keep_rds, we don't really use this.
        &mut Vec::new(),
    ) {
        Ok(c) => c,
        Err(e) => bail!(e),
    };
    let ex = Executor::new().context("Failed to create executor")?;
    let backend = ConsoleBackend::new(&ex, console);
    let handler = DeviceRequestHandler::new(backend);

    // Set stdin() in raw mode so we can send over individual keystrokes unbuffered
    stdin()
        .set_raw_mode()
        .context("Failed to set terminal raw mode")?;

    let res = match (opts.socket, opts.vfio) {
        (Some(socket), None) => {
            // run_until() returns an Result<Result<..>> which the ? operator lets us flatten.
            ex.run_until(handler.run(socket, &ex))?
        }
        (None, Some(vfio)) => {
            let device = VvuPciDevice::new(&vfio, ConsoleBackend::MAX_QUEUE_NUM)?;
            ex.run_until(handler.run_vvu(device, &ex))?
        }
        _ => Err(anyhow!("exactly one of `--socket` or `--vfio` is required")),
    };

    // Restore terminal capabilities back to what they were before
    stdin()
        .set_canon_mode()
        .context("Failed to restore canonical mode for terminal")?;

    res
}
<|endoftext|>


<commit_before><commit_msg>Link rustc error codes in diagnostics<commit_after><|endoftext|>


<commit_before>use segmentation;

/// Enable Interrupts.
pub unsafe fn enable() {
    asm!("sti");
}

/// Disable Interrupts.
pub unsafe fn disable() {
    asm!("cli");
}

/// Generate a software interrupt.
/// This is a macro because the argument needs to be an immediate.
#[macro_export]
macro_rules! int {
    ( $x:expr ) => {
        {
            asm!("int $0" :: "N" ($x));
        }
    };
}

/// A struct describing a pointer to a descriptor table (GDT / IDT).
/// This is in a format suitable for giving to 'lgdt' or 'lidt'.
#[derive(Debug)]
#[repr(C, packed)]
pub struct DescriptorTablePointer {
    /// Size of the DT.
    pub limit: u16,
    /// Pointer to the memory region containing the DT.
    pub base: u64,
}

/// Load GDT table.
pub unsafe fn lgdt(gdt: &DescriptorTablePointer) {
    asm!("lgdt ($0)" :: "r" (gdt) : "memory");
}

/// Load LDT table.
pub unsafe fn lldt(ldt: &DescriptorTablePointer) {
    asm!("lldt ($0)" :: "r" (ldt) : "memory");
}

/// Load IDT table.
pub unsafe fn lidt(idt: &DescriptorTablePointer) {
    asm!("lidt ($0)" :: "r" (idt) : "memory");
}

/// Load the task state register.
pub unsafe fn load_tss(sel: segmentation::SegmentSelector) {
    asm!("ltr $0" :: "r" (sel.bits()));
}

/// Halts the CPU by executing the `hlt` instruction.
#[inline(always)]
pub unsafe fn halt() {
    asm!("hlt" :::: "volatile");
}
<commit_msg>Add documentation<commit_after>//! Low level functions for special x86 instructions.

use segmentation;

/// Enable Interrupts.
pub unsafe fn enable() {
    asm!("sti");
}

/// Disable Interrupts.
pub unsafe fn disable() {
    asm!("cli");
}

/// Generate a software interrupt.
/// This is a macro because the argument needs to be an immediate.
#[macro_export]
macro_rules! int {
    ( $x:expr ) => {
        {
            asm!("int $0" :: "N" ($x));
        }
    };
}

/// A struct describing a pointer to a descriptor table (GDT / IDT).
/// This is in a format suitable for giving to 'lgdt' or 'lidt'.
#[derive(Debug)]
#[repr(C, packed)]
pub struct DescriptorTablePointer {
    /// Size of the DT.
    pub limit: u16,
    /// Pointer to the memory region containing the DT.
    pub base: u64,
}

/// Load GDT table.
pub unsafe fn lgdt(gdt: &DescriptorTablePointer) {
    asm!("lgdt ($0)" :: "r" (gdt) : "memory");
}

/// Load LDT table.
pub unsafe fn lldt(ldt: &DescriptorTablePointer) {
    asm!("lldt ($0)" :: "r" (ldt) : "memory");
}

/// Load IDT table.
pub unsafe fn lidt(idt: &DescriptorTablePointer) {
    asm!("lidt ($0)" :: "r" (idt) : "memory");
}

/// Load the task state register.
pub unsafe fn load_tss(sel: segmentation::SegmentSelector) {
    asm!("ltr $0" :: "r" (sel.bits()));
}

/// Halts the CPU by executing the `hlt` instruction.
#[inline(always)]
pub unsafe fn halt() {
    asm!("hlt" :::: "volatile");
}
<|endoftext|>


<commit_before>//
// sprocketnes/mapper.rs
//
// Author: Patrick Walton
//

use rom::Rom;
use util;

#[deriving(Eq)]
pub enum MapperResult {
    Continue,
    Irq,
}

pub trait Mapper {
    fn prg_loadb(&mut self, addr: u16) -> u8;
    fn prg_storeb(&mut self, addr: u16, val: u8);
    fn chr_loadb(&mut self, addr: u16) -> u8;
    fn chr_storeb(&mut self, addr: u16, val: u8);
    fn next_scanline(&mut self) -> MapperResult;
}

pub fn create_mapper(rom: ~Rom) -> ~Mapper:Send+Freeze {
    match rom.header.ines_mapper() {
        0 => {
            ~Nrom {
                rom: rom,
            } as ~Mapper:Freeze+Send
        },
        1 => ~SxRom::new(rom) as ~Mapper:Freeze+Send,
        4 => ~TxRom::new(rom) as ~Mapper:Freeze+Send,
        _ => fail!("unsupported mapper")
    }
}

//
// Mapper 0 (NROM)
//
// See http://wiki.nesdev.com/w/index.php/NROM
//

// TODO: RAM.
pub struct Nrom {
    rom: ~Rom,
}

impl Mapper for Nrom {
    fn prg_loadb(&mut self, addr: u16) -> u8 {
        if addr < 0x8000 {
            0u8
        } else if self.rom.prg.len() > 16384 {
            *self.rom.prg.get(addr as uint & 0x7fff)
        } else {
            *self.rom.prg.get(addr as uint & 0x3fff)
        }
    }
    fn prg_storeb(&mut self, _: u16, _: u8) {}  // Can't store to PRG-ROM.
    fn chr_loadb(&mut self, addr: u16) -> u8 { *self.rom.chr.get(addr as uint) }
    fn chr_storeb(&mut self, _: u16, _: u8) {}  // Can't store to CHR-ROM.
    fn next_scanline(&mut self) -> MapperResult { Continue }
}

//
// Mapper 1 (SxROM/MMC1)
//
// See http://wiki.nesdev.com/w/index.php/Nintendo_MMC1
//

struct SxCtrl(u8);

pub enum Mirroring {
    OneScreenLower,
    OneScreenUpper,
    Vertical,
    Horizontal,
}

enum SxPrgBankMode {
    Switch32K,      // Switch 32K at $8000, ignore low bit
    FixFirstBank,   // Fix first bank at $8000, switch 16K bank at $C000
    FixLastBank,    // Fix last bank at $C000, switch 16K bank at $8000
}

impl SxCtrl {
    fn prg_rom_mode(self) -> SxPrgBankMode {
        match (*self >> 2) & 3 {
            0 | 1 => Switch32K,
            2 => FixFirstBank,
            3 => FixLastBank,
            _ => fail!("can't happen")
        }
    }
}

pub struct SxRegs {
    ctrl: SxCtrl,   // $8000-$9FFF
    chr_bank_0: u8, // $A000-$BFFF
    chr_bank_1: u8, // $C000-$DFFF
    prg_bank: u8,   // $E000-$FFFF
}

pub struct SxRom {
    rom: ~Rom,
    regs: SxRegs,
    // The internal accumulator.
    accum: u8,
    // The write count. At the 5th write, we update the register.
    write_count: u8,
    prg_ram: ~([u8, ..8192]),
    chr_ram: ~([u8, ..8192]),
}

impl SxRom {
    fn new(rom: ~Rom) -> SxRom {
        SxRom {
            rom: rom,
            regs: SxRegs {
                ctrl: SxCtrl(3 << 2),
                chr_bank_0: 0,
                chr_bank_1: 0,
                prg_bank: 0,
            },
            accum: 0,
            write_count: 0,
            prg_ram: ~([ 0, ..8192 ]),
            chr_ram: ~([ 0, ..8192 ]),
        }
    }
}

impl Mapper for SxRom {
    fn prg_loadb(&mut self, addr: u16) -> u8 {
        if addr < 0x8000 {
            0u8
        } else if addr < 0xc000 {
            let bank = match self.regs.ctrl.prg_rom_mode() {
                Switch32K => self.regs.prg_bank & 0xfe,
                FixFirstBank => 0,
                FixLastBank => self.regs.prg_bank,
            };
            *self.rom.prg.get((bank as uint * 16384) | ((addr & 0x3fff) as uint))
        } else {
            let bank = match self.regs.ctrl.prg_rom_mode() {
                Switch32K => (self.regs.prg_bank & 0xfe) | 1,
                FixFirstBank => self.regs.prg_bank,
                FixLastBank => (*self.rom).header.prg_rom_size - 1,
            };
            *self.rom.prg.get((bank as uint * 16384) | ((addr & 0x3fff) as uint))
        }
    }

    fn prg_storeb(&mut self, addr: u16, val: u8) {
        if addr < 0x8000 {
            return;
        }

        // Check the reset flag.
        if (val & 0x80) != 0 {
            self.write_count = 0;
            self.accum = 0;
            self.regs.ctrl = SxCtrl(*self.regs.ctrl | (3 << 2));
            return;
        }

        // Write the lowest bit of the value into the right location of the accumulator.
        self.accum = self.accum | ((val & 1) << self.write_count);

        self.write_count += 1;
        if self.write_count == 5 {
            self.write_count = 0;

            // Write to the right internal register.
            if addr <= 0x9fff {
                self.regs.ctrl = SxCtrl(self.accum);
            } else if addr <= 0xbfff {
                self.regs.chr_bank_0 = self.accum;
            } else if addr <= 0xdfff {
                self.regs.chr_bank_1 = self.accum;
            } else {
                self.regs.prg_bank = self.accum;
            }

            self.accum = 0;
        }
    }

    // FIXME: Apparently this mapper can have CHR-ROM as well. Handle this case.
    fn chr_loadb(&mut self, addr: u16) -> u8     { self.chr_ram[addr]       }
    fn chr_storeb(&mut self, addr: u16, val: u8) { self.chr_ram[addr] = val }

    fn next_scanline(&mut self) -> MapperResult { Continue }
}

//
// Mapper 4 (TxROM/MMC3)
//
// See http://wiki.nesdev.com/w/index.php/MMC3
//

struct TxBankSelect(u8);

enum TxPrgBankMode {
    Swappable8000,
    SwappableC000,
}

impl TxBankSelect {
    fn bank_update_select(self) -> u8 { *self & 0x7 }
    fn prg_bank_mode(self) -> TxPrgBankMode {
        if (*self & 0x40) == 0 { Swappable8000 } else { SwappableC000 }
    }
    fn chr_a12_inversion(self) -> bool { (*self & 0x80) != 0 }
}

struct TxRegs {
    bank_select: TxBankSelect,  // Bank select (0x8000-0x9ffe even)
}

struct TxRom {
    rom: ~Rom,
    regs: TxRegs,
    prg_ram: ~([u8, ..8192]),

    chr_banks_2k: [u8, ..2],    // 2KB CHR-ROM banks
    chr_banks_1k: [u8, ..4],    // 1KB CHR-ROM banks
    prg_banks:    [u8, ..2],    // 8KB PRG-ROM banks

    scanline_counter: u8,
    irq_reload: u8,             // Copied into the scanline counter when it hits zero.
    irq_enabled: bool,
}

impl TxRom {
    fn new(rom: ~Rom) -> TxRom {
        TxRom {
            rom: rom,
            regs: TxRegs { bank_select: TxBankSelect(0) },
            prg_ram: ~([ 0, ..8192 ]),

            chr_banks_2k: [ 0, 0 ],
            chr_banks_1k: [ 0, 0, 0, 0 ],
            prg_banks: [ 0, 0 ],

            scanline_counter: 0,
            irq_reload: 0,
            irq_enabled: false,
        }
    }

    fn prg_bank_count(&self) -> u8 { self.rom.header.prg_rom_size * 2 }
}

impl Mapper for TxRom {
    fn prg_loadb(&mut self, addr: u16) -> u8 {
        if addr < 0x6000 {
            0u8
        } else if addr < 0x8000 {
            self.prg_ram[addr & 0x1fff]
        } else if addr < 0xa000 {
            // $8000-$9FFF might be switchable or fixed to the second to last bank.
            let bank = match self.regs.bank_select.prg_bank_mode() {
                Swappable8000 => self.prg_banks[0],
                SwappableC000 => self.prg_bank_count() - 2,
            };
            *self.rom.prg.get((bank as uint * 8192) | (addr as uint & 0x1fff))
        } else if addr < 0xc000 {
            // $A000-$BFFF is switchable.
            *self.rom.prg.get((self.prg_banks[1] as uint * 8192) | (addr as uint & 0x1fff))
        } else if addr < 0xe000 {
            // $C000-$DFFF might be switchable or fixed to the second to last bank.
            let bank = match self.regs.bank_select.prg_bank_mode() {
                Swappable8000 => self.prg_bank_count() - 2,
                SwappableC000 => self.prg_banks[0],
            };
            *self.rom.prg.get((bank as uint * 8192) | (addr as uint & 0x1fff))
        } else {
            // $E000-$FFFF is fixed to the last bank.
            let bank = self.prg_bank_count() - 1;
            *self.rom.prg.get((bank as uint * 8192) | (addr as uint & 0x1fff))
        }
    }

    fn prg_storeb(&mut self, addr: u16, val: u8) {
        if addr < 0x6000 {
            return;
        }

        if addr < 0x8000 {
            self.prg_ram[addr & 0x1fff] = val;
        } else if addr < 0xa000 {
            if (addr & 1) == 0 {
                // Bank select.
                self.regs.bank_select = TxBankSelect(val);
            } else {
                // Bank data.
                let bank_update_select = self.regs.bank_select.bank_update_select();
                match bank_update_select {
                    0..1 => self.chr_banks_2k[bank_update_select] = val,
                    2..5 => self.chr_banks_1k[bank_update_select - 2] = val,
                    6..7 => self.prg_banks[bank_update_select - 6] = val,
                    _ => fail!()
                }
            }
        } else if addr < 0xc000 {
            // TODO: Mirroring and PRG-RAM protect
        } else if addr < 0xe000 {
            if (addr & 1) == 0 {
                // IRQ latch.
                self.irq_reload = val;
            } else {
                // IRQ reload.
                self.scanline_counter = self.irq_reload;
            }
        } else {
            // IRQ enable.
            self.irq_enabled = (addr & 1) == 1;
        }
    }

    fn chr_loadb(&mut self, addr: u16) -> u8 {
        let (bank, two_kb) = match (addr, self.regs.bank_select.chr_a12_inversion()) {
            (0x0000..0x07ff, false) | (0x1000..0x17ff, true) => (self.chr_banks_2k[0], true),
            (0x0800..0x0fff, false) | (0x1800..0x1fff, true) => (self.chr_banks_2k[1], true),
            (0x1000..0x13ff, false) | (0x0000..0x03ff, true) => (self.chr_banks_1k[0], false),
            (0x1400..0x17ff, false) | (0x0400..0x07ff, true) => (self.chr_banks_1k[1], false),
            (0x1800..0x1bff, false) | (0x0800..0x0bff, true) => (self.chr_banks_1k[2], false),
            (0x1c00..0x1fff, false) | (0x0c00..0x0fff, true) => (self.chr_banks_1k[3], false),
            _ => return 0,
        };
        if two_kb {
            *self.rom.chr.get((bank as uint * 1024) + (addr as uint & 0x7ff))
        } else {
            *self.rom.chr.get((bank as uint * 1024) | (addr as uint & 0x3ff))
        }
    }

    fn chr_storeb(&mut self, _: u16, _: u8) {
        // TODO: CHR-RAM
    }

    fn next_scanline(&mut self) -> MapperResult {
        if self.scanline_counter != 0 {
            self.scanline_counter -= 1;
            if self.scanline_counter == 0 {
                self.scanline_counter = self.irq_reload;

                if self.irq_enabled {
                    util::debug_print("*** Generated IRQ! ***");
                    return Irq;
                }
            }
        }
        Continue
    }
}

<commit_msg>Update from single tuple struct for mapper.rs<commit_after>//
// sprocketnes/mapper.rs
//
// Author: Patrick Walton
//

use rom::Rom;
use util;

#[deriving(Eq)]
pub enum MapperResult {
    Continue,
    Irq,
}

pub trait Mapper {
    fn prg_loadb(&mut self, addr: u16) -> u8;
    fn prg_storeb(&mut self, addr: u16, val: u8);
    fn chr_loadb(&mut self, addr: u16) -> u8;
    fn chr_storeb(&mut self, addr: u16, val: u8);
    fn next_scanline(&mut self) -> MapperResult;
}

pub fn create_mapper(rom: ~Rom) -> ~Mapper:Send+Freeze {
    match rom.header.ines_mapper() {
        0 => {
            ~Nrom {
                rom: rom,
            } as ~Mapper:Freeze+Send
        },
        1 => ~SxRom::new(rom) as ~Mapper:Freeze+Send,
        4 => ~TxRom::new(rom) as ~Mapper:Freeze+Send,
        _ => fail!("unsupported mapper")
    }
}

//
// Mapper 0 (NROM)
//
// See http://wiki.nesdev.com/w/index.php/NROM
//

// TODO: RAM.
pub struct Nrom {
    rom: ~Rom,
}

impl Mapper for Nrom {
    fn prg_loadb(&mut self, addr: u16) -> u8 {
        if addr < 0x8000 {
            0u8
        } else if self.rom.prg.len() > 16384 {
            *self.rom.prg.get(addr as uint & 0x7fff)
        } else {
            *self.rom.prg.get(addr as uint & 0x3fff)
        }
    }
    fn prg_storeb(&mut self, _: u16, _: u8) {}  // Can't store to PRG-ROM.
    fn chr_loadb(&mut self, addr: u16) -> u8 { *self.rom.chr.get(addr as uint) }
    fn chr_storeb(&mut self, _: u16, _: u8) {}  // Can't store to CHR-ROM.
    fn next_scanline(&mut self) -> MapperResult { Continue }
}

//
// Mapper 1 (SxROM/MMC1)
//
// See http://wiki.nesdev.com/w/index.php/Nintendo_MMC1
//

struct SxCtrl{ val: u8 }

impl Deref<u8> for SxCtrl {
    fn deref<'a>(&'a self) -> &'a u8 {
        &self.val
    }
}

pub enum Mirroring {
    OneScreenLower,
    OneScreenUpper,
    Vertical,
    Horizontal,
}

enum SxPrgBankMode {
    Switch32K,      // Switch 32K at $8000, ignore low bit
    FixFirstBank,   // Fix first bank at $8000, switch 16K bank at $C000
    FixLastBank,    // Fix last bank at $C000, switch 16K bank at $8000
}

impl SxCtrl {
    fn prg_rom_mode(self) -> SxPrgBankMode {
        match (*self >> 2) & 3 {
            0 | 1 => Switch32K,
            2 => FixFirstBank,
            3 => FixLastBank,
            _ => fail!("can't happen")
        }
    }
}

pub struct SxRegs {
    ctrl: SxCtrl,   // $8000-$9FFF
    chr_bank_0: u8, // $A000-$BFFF
    chr_bank_1: u8, // $C000-$DFFF
    prg_bank: u8,   // $E000-$FFFF
}

pub struct SxRom {
    rom: ~Rom,
    regs: SxRegs,
    // The internal accumulator.
    accum: u8,
    // The write count. At the 5th write, we update the register.
    write_count: u8,
    prg_ram: ~([u8, ..8192]),
    chr_ram: ~([u8, ..8192]),
}

impl SxRom {
    fn new(rom: ~Rom) -> SxRom {
        SxRom {
            rom: rom,
            regs: SxRegs {
                ctrl: SxCtrl{val: 3 << 2},
                chr_bank_0: 0,
                chr_bank_1: 0,
                prg_bank: 0,
            },
            accum: 0,
            write_count: 0,
            prg_ram: ~([ 0, ..8192 ]),
            chr_ram: ~([ 0, ..8192 ]),
        }
    }
}

impl Mapper for SxRom {
    fn prg_loadb(&mut self, addr: u16) -> u8 {
        if addr < 0x8000 {
            0u8
        } else if addr < 0xc000 {
            let bank = match self.regs.ctrl.prg_rom_mode() {
                Switch32K => self.regs.prg_bank & 0xfe,
                FixFirstBank => 0,
                FixLastBank => self.regs.prg_bank,
            };
            *self.rom.prg.get((bank as uint * 16384) | ((addr & 0x3fff) as uint))
        } else {
            let bank = match self.regs.ctrl.prg_rom_mode() {
                Switch32K => (self.regs.prg_bank & 0xfe) | 1,
                FixFirstBank => self.regs.prg_bank,
                FixLastBank => (*self.rom).header.prg_rom_size - 1,
            };
            *self.rom.prg.get((bank as uint * 16384) | ((addr & 0x3fff) as uint))
        }
    }

    fn prg_storeb(&mut self, addr: u16, val: u8) {
        if addr < 0x8000 {
            return;
        }

        // Check the reset flag.
        if (val & 0x80) != 0 {
            self.write_count = 0;
            self.accum = 0;
            self.regs.ctrl = SxCtrl{val: *self.regs.ctrl | (3 << 2)};
            return;
        }

        // Write the lowest bit of the value into the right location of the accumulator.
        self.accum = self.accum | ((val & 1) << self.write_count);

        self.write_count += 1;
        if self.write_count == 5 {
            self.write_count = 0;

            // Write to the right internal register.
            if addr <= 0x9fff {
                self.regs.ctrl = SxCtrl{val: self.accum};
            } else if addr <= 0xbfff {
                self.regs.chr_bank_0 = self.accum;
            } else if addr <= 0xdfff {
                self.regs.chr_bank_1 = self.accum;
            } else {
                self.regs.prg_bank = self.accum;
            }

            self.accum = 0;
        }
    }

    // FIXME: Apparently this mapper can have CHR-ROM as well. Handle this case.
    fn chr_loadb(&mut self, addr: u16) -> u8     { self.chr_ram[addr]       }
    fn chr_storeb(&mut self, addr: u16, val: u8) { self.chr_ram[addr] = val }

    fn next_scanline(&mut self) -> MapperResult { Continue }
}

//
// Mapper 4 (TxROM/MMC3)
//
// See http://wiki.nesdev.com/w/index.php/MMC3
//

struct TxBankSelect{ val: u8 }

impl Deref<u8> for TxBankSelect {
    fn deref<'a>(&'a self) -> &'a u8 {
        &self.val
    }
}

enum TxPrgBankMode {
    Swappable8000,
    SwappableC000,
}

impl TxBankSelect {
    fn bank_update_select(self) -> u8 { *self & 0x7 }
    fn prg_bank_mode(self) -> TxPrgBankMode {
        if (*self & 0x40) == 0 { Swappable8000 } else { SwappableC000 }
    }
    fn chr_a12_inversion(self) -> bool { (*self & 0x80) != 0 }
}

struct TxRegs {
    bank_select: TxBankSelect,  // Bank select (0x8000-0x9ffe even)
}

struct TxRom {
    rom: ~Rom,
    regs: TxRegs,
    prg_ram: ~([u8, ..8192]),

    chr_banks_2k: [u8, ..2],    // 2KB CHR-ROM banks
    chr_banks_1k: [u8, ..4],    // 1KB CHR-ROM banks
    prg_banks:    [u8, ..2],    // 8KB PRG-ROM banks

    scanline_counter: u8,
    irq_reload: u8,             // Copied into the scanline counter when it hits zero.
    irq_enabled: bool,
}

impl TxRom {
    fn new(rom: ~Rom) -> TxRom {
        TxRom {
            rom: rom,
            regs: TxRegs { bank_select: TxBankSelect{val: 0} },
            prg_ram: ~([ 0, ..8192 ]),

            chr_banks_2k: [ 0, 0 ],
            chr_banks_1k: [ 0, 0, 0, 0 ],
            prg_banks: [ 0, 0 ],

            scanline_counter: 0,
            irq_reload: 0,
            irq_enabled: false,
        }
    }

    fn prg_bank_count(&self) -> u8 { self.rom.header.prg_rom_size * 2 }
}

impl Mapper for TxRom {
    fn prg_loadb(&mut self, addr: u16) -> u8 {
        if addr < 0x6000 {
            0u8
        } else if addr < 0x8000 {
            self.prg_ram[addr & 0x1fff]
        } else if addr < 0xa000 {
            // $8000-$9FFF might be switchable or fixed to the second to last bank.
            let bank = match self.regs.bank_select.prg_bank_mode() {
                Swappable8000 => self.prg_banks[0],
                SwappableC000 => self.prg_bank_count() - 2,
            };
            *self.rom.prg.get((bank as uint * 8192) | (addr as uint & 0x1fff))
        } else if addr < 0xc000 {
            // $A000-$BFFF is switchable.
            *self.rom.prg.get((self.prg_banks[1] as uint * 8192) | (addr as uint & 0x1fff))
        } else if addr < 0xe000 {
            // $C000-$DFFF might be switchable or fixed to the second to last bank.
            let bank = match self.regs.bank_select.prg_bank_mode() {
                Swappable8000 => self.prg_bank_count() - 2,
                SwappableC000 => self.prg_banks[0],
            };
            *self.rom.prg.get((bank as uint * 8192) | (addr as uint & 0x1fff))
        } else {
            // $E000-$FFFF is fixed to the last bank.
            let bank = self.prg_bank_count() - 1;
            *self.rom.prg.get((bank as uint * 8192) | (addr as uint & 0x1fff))
        }
    }

    fn prg_storeb(&mut self, addr: u16, val: u8) {
        if addr < 0x6000 {
            return;
        }

        if addr < 0x8000 {
            self.prg_ram[addr & 0x1fff] = val;
        } else if addr < 0xa000 {
            if (addr & 1) == 0 {
                // Bank select.
                self.regs.bank_select = TxBankSelect{val: val};
            } else {
                // Bank data.
                let bank_update_select = self.regs.bank_select.bank_update_select();
                match bank_update_select {
                    0..1 => self.chr_banks_2k[bank_update_select] = val,
                    2..5 => self.chr_banks_1k[bank_update_select - 2] = val,
                    6..7 => self.prg_banks[bank_update_select - 6] = val,
                    _ => fail!()
                }
            }
        } else if addr < 0xc000 {
            // TODO: Mirroring and PRG-RAM protect
        } else if addr < 0xe000 {
            if (addr & 1) == 0 {
                // IRQ latch.
                self.irq_reload = val;
            } else {
                // IRQ reload.
                self.scanline_counter = self.irq_reload;
            }
        } else {
            // IRQ enable.
            self.irq_enabled = (addr & 1) == 1;
        }
    }

    fn chr_loadb(&mut self, addr: u16) -> u8 {
        let (bank, two_kb) = match (addr, self.regs.bank_select.chr_a12_inversion()) {
            (0x0000..0x07ff, false) | (0x1000..0x17ff, true) => (self.chr_banks_2k[0], true),
            (0x0800..0x0fff, false) | (0x1800..0x1fff, true) => (self.chr_banks_2k[1], true),
            (0x1000..0x13ff, false) | (0x0000..0x03ff, true) => (self.chr_banks_1k[0], false),
            (0x1400..0x17ff, false) | (0x0400..0x07ff, true) => (self.chr_banks_1k[1], false),
            (0x1800..0x1bff, false) | (0x0800..0x0bff, true) => (self.chr_banks_1k[2], false),
            (0x1c00..0x1fff, false) | (0x0c00..0x0fff, true) => (self.chr_banks_1k[3], false),
            _ => return 0,
        };
        if two_kb {
            *self.rom.chr.get((bank as uint * 1024) + (addr as uint & 0x7ff))
        } else {
            *self.rom.chr.get((bank as uint * 1024) | (addr as uint & 0x3ff))
        }
    }

    fn chr_storeb(&mut self, _: u16, _: u8) {
        // TODO: CHR-RAM
    }

    fn next_scanline(&mut self) -> MapperResult {
        if self.scanline_counter != 0 {
            self.scanline_counter -= 1;
            if self.scanline_counter == 0 {
                self.scanline_counter = self.irq_reload;

                if self.irq_enabled {
                    util::debug_print("*** Generated IRQ! ***");
                    return Irq;
                }
            }
        }
        Continue
    }
}

<|endoftext|>


<commit_before>// Traits in Rust are a way of guaranteeing particular functionality for a type.
// They let the compiler know that a type is capable of necessary functions to
// help it ensure safety.
#[test]
fn implementing_traits() {
  struct Person {
    first_name: &'static str,
    last_name: &'static str
  }

  // Any type that implements the HasName trait is guaranteed to have a
  // function called full_name() that returns a String
  trait HasName {
    fn full_name(&self) -> String;
  }

  impl Person {
    fn full_name(&self) -> String {
      format!("{} {}", self.first_name, self.last_name)
    }
  }

  let person = Person {
    first_name: "Chris",
    last_name: "Cerami"
  };

  // The assert_full_name function needs to know that its argument can call
  // full_name(). In order to guarantee this, it is cast to receive any
  // argument type that has implemented the HasName trait.
  fn assert_full_name<T: HasName>(person: T) {
    assert_eq!(person.full_name(), "Chris Cerami");
  }

  assert_full_name(person);
}

// In order to implement a trait, a type must implement ALL of its functions.
// This is required in order to guarantee that any type that shares that trait
// will be able to respond to those functions.
#[test]
fn implementing_traits2() {
  struct Character {
    name: &'static str,
    level: u16
  }

  trait HasLevel {
    fn level_up(&mut self) -> u16;

    fn print_level(&self);
  }

  impl HasLevel for Character {
    fn level_up(&mut self) -> u16 {
      self.level += 1;
      self.level
    }
  }

  let mut durz = Character {
    name: "Durz",
    level: 2
  };

  fn test_level_up<T: HasLevel>(character: &mut T) {
    assert_eq!(character.level_up(), 3);
  }

  test_level_up(&mut durz);
}

// Now let's try creating a trait and implementing it for an existing type.
#[test]
fn creating_traits() {
  let num_one: u16 = 3;
  let num_two: u16 = 4;

  fn asserts<T: IsEvenOrOdd>(x: T, y: T) {
    assert!(!x.is_even());
    assert!(y.is_even());
  }

  asserts(num_one, num_two);
}

// We can also add trait constraints to structs that we create. Using this pattern,
// we can use generic types and still ensure type safety.
#[test]
fn trait_constraints_on_structs() {
  struct Language<T> {
    stable_version: T,
    latest_version: T
  }

  impl<__> Language<T> {
    fn is_stable(&self) -> bool {
      self.latest_version >= self.stable_version
    }
  }

  let rust = Language {
    stable_version: "1.3.0",
    latest_version: "1.5.0"
  };

  assert!(rust.is_stable());
}
<commit_msg>Add where clause and default function examples<commit_after>// Traits in Rust are a way of guaranteeing particular functionality for a type.
// They let the compiler know that a type is capable of necessary functions to
// help it ensure safety. For more information, check the book:
// https://doc.rust-lang.org/nightly/book/traits.html
#[test]
fn implementing_traits() {
  struct Person {
    first_name: &'static str,
    last_name: &'static str
  }

  // Any type that implements the HasName trait is guaranteed to have a
  // function called full_name() that returns a String
  trait HasName {
    fn full_name(&self) -> String;
  }

  impl Person {
    fn full_name(&self) -> String {
      format!("{} {}", self.first_name, self.last_name)
    }
  }

  let person = Person {
    first_name: "Chris",
    last_name: "Cerami"
  };

  // The assert_full_name function needs to know that its argument can call
  // full_name(). In order to guarantee this, it is cast to receive any
  // argument type that has implemented the HasName trait.
  fn assert_full_name<T: HasName>(person: T) {
    assert_eq!(person.full_name(), "Chris Cerami");
  }

  assert_full_name(person);
}

// In order to implement a trait, a type must implement ALL of its functions.
// This is required in order to guarantee that any type that shares that trait
// will be able to respond to those functions.
#[test]
fn implementing_traits2() {
  struct Character {
    name: &'static str,
    level: u16
  }

  trait HasLevel {
    fn level_up(&mut self) -> u16;

    fn print_level(&self);
  }

  impl HasLevel for Character {
    fn level_up(&mut self) -> u16 {
      self.level += 1;
      self.level
    }
  }

  let mut durz = Character {
    name: "Durz",
    level: 2
  };

  fn test_level_up<T: HasLevel>(character: &mut T) {
    assert_eq!(character.level_up(), 3);
  }

  test_level_up(&mut durz);
}

// Now let's try creating a trait and implementing it for an existing type.
#[test]
fn creating_traits() {
  let num_one: u16 = 3;
  let num_two: u16 = 4;

  fn asserts<T: IsEvenOrOdd>(x: T, y: T) {
    assert!(!x.is_even());
    assert!(y.is_even());
  }

  asserts(num_one, num_two);
}

// We can also add trait constraints, or "bounds", to structs that we create.
// Using this pattern, we can use generic types and still ensure type safety.
#[test]
fn trait_constraints_on_structs() {
  struct Language<T> {
    stable_version: T,
    latest_version: T
  }

  impl<__> Language<T> {
    fn is_stable(&self) -> bool {
      self.latest_version >= self.stable_version
    }
  }

  let rust = Language {
    stable_version: "1.3.0",
    latest_version: "1.5.0"
  };

  assert!(rust.is_stable());
}

// There is an alternate syntax for placing trait bounds on a function, the
// where clause. Let's revisit a previous example, this time using 'where'.
#[test]
fn where_clause() {
  let num_one: u16 = 3;
  let num_two: u16 = 4;

  trait IsEvenOrOdd {
    fn is_even(&self) -> bool;
  }

  impl IsEvenOrOdd for u16 {
    fn is_even(&self) -> bool {
      self % 2 == 0
    }
  }

  fn asserts<T>(x: T, y: T) {
    assert!(!x.is_even());
    assert!(y.is_even());
  }

  asserts(num_one, num_two);
}

While you can always allow the implementor of a trait declare its functions,
you can also supply default functionality. Let's revisit IsEvenOrOdd.
#[test]
fn default_functions() {
  let num_one: u16 = 3;
  let num_two: u16 = 4;

  trait IsEvenOrOdd {
    fn is_even(&self) -> bool;
    fn is_odd(&self) -> bool { __ }
  }

  impl IsEvenOrOdd for u16 {
    fn is_even(&self) -> bool {
      self % 2 == 0
    }
  }

  fn asserts<T: IsEvenOrOdd>(x: T, y: T) {
    assert!(x.is_odd());
    assert!(y.is_even());
  }

  asserts(num_one, num_two);
}
<|endoftext|>


<commit_before>//! Asynchronous streams.

use core::ops::DerefMut;
use core::pin::Pin;
use core::task::{Context, Poll};

/// An owned dynamically typed [`Stream`] for use in cases where you can't
/// statically type your result or need to add some indirection.
#[cfg(feature = "alloc")]
pub type BoxStream<'a, T> = Pin<alloc::boxed::Box<dyn Stream<Item = T> + Send + 'a>>;

/// `BoxStream`, but without the `Send` requirement.
#[cfg(feature = "alloc")]
pub type LocalBoxStream<'a, T> = Pin<alloc::boxed::Box<dyn Stream<Item = T> + 'a>>;

/// A stream of values produced asynchronously.
///
/// If `Future<Output = T>` is an asynchronous version of `T`, then `Stream<Item
/// = T>` is an asynchronous version of `Iterator<Item = T>`. A stream
/// represents a sequence of value-producing events that occur asynchronously to
/// the caller.
///
/// The trait is modeled after `Future`, but allows `poll_next` to be called
/// even after a value has been produced, yielding `None` once the stream has
/// been fully exhausted.
#[must_use = "streams do nothing unless polled"]
pub trait Stream {
    /// Values yielded by the stream.
    type Item;

    /// Attempt to pull out the next value of this stream, registering the
    /// current task for wakeup if the value is not yet available, and returning
    /// `None` if the stream is exhausted.
    ///
    /// # Return value
    ///
    /// There are several possible return values, each indicating a distinct
    /// stream state:
    ///
    /// - `Poll::Pending` means that this stream's next value is not ready
    /// yet. Implementations will ensure that the current task will be notified
    /// when the next value may be ready.
    ///
    /// - `Poll::Ready(Some(val))` means that the stream has successfully
    /// produced a value, `val`, and may produce further values on subsequent
    /// `poll_next` calls.
    ///
    /// - `Poll::Ready(None)` means that the stream has terminated, and
    /// `poll_next` should not be invoked again.
    ///
    /// # Panics
    ///
    /// Once a stream is finished, i.e. `Ready(None)` has been returned, further
    /// calls to `poll_next` may result in a panic or other "bad behavior".  If
    /// this is difficult to guard against then the `fuse` adapter can be used
    /// to ensure that `poll_next` always returns `Ready(None)` in subsequent
    /// calls.
    fn poll_next(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>>;

    /// Returns the bounds on the remaining length of the stream.
    ///
    /// Specifically, `size_hint()` returns a tuple where the first element
    /// is the lower bound, and the second element is the upper bound.
    ///
    /// The second half of the tuple that is returned is an [`Option`]`<`[`usize`]`>`.
    /// A [`None`] here means that either there is no known upper bound, or the
    /// upper bound is larger than [`usize`].
    ///
    /// # Implementation notes
    ///
    /// It is not enforced that a stream implementation yields the declared
    /// number of elements. A buggy stream may yield less than the lower bound
    /// or more than the upper bound of elements.
    ///
    /// `size_hint()` is primarily intended to be used for optimizations such as
    /// reserving space for the elements of the stream, but must not be
    /// trusted to e.g., omit bounds checks in unsafe code. An incorrect
    /// implementation of `size_hint()` should not lead to memory safety
    /// violations.
    ///
    /// That said, the implementation should provide a correct estimation,
    /// because otherwise it would be a violation of the trait's protocol.
    ///
    /// The default implementation returns `(0, `[`None`]`)` which is correct for any
    /// stream.
    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, None)
    }
}

impl<S: ?Sized + Stream + Unpin> Stream for &mut S {
    type Item = S::Item;

    fn poll_next(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        S::poll_next(Pin::new(&mut **self), cx)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (**self).size_hint()
    }
}

impl
 Stream for Pin

where
    P: DerefMut + Unpin,
    P::Target: Stream,
{
    type Item =
::Item;

    fn poll_next(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        self.get_mut().as_mut().poll_next(cx)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (**self).size_hint()
    }
}

/// A stream which tracks whether or not the underlying stream
/// should no longer be polled.
///
/// `is_terminated` will return `true` if a future should no longer be polled.
/// Usually, this state occurs after `poll_next` (or `try_poll_next`) returned
/// `Poll::Ready(None)`. However, `is_terminated` may also return `true` if a
/// stream has become inactive and can no longer make progress and should be
/// ignored or dropped rather than being polled again.
pub trait FusedStream: Stream {
    /// Returns `true` if the stream should no longer be polled.
    fn is_terminated(&self) -> bool;
}

impl<F: ?Sized + FusedStream + Unpin> FusedStream for &mut F {
    fn is_terminated(&self) -> bool {
        <F as FusedStream>::is_terminated(&**self)
    }
}

impl
 FusedStream for Pin

where
    P: DerefMut + Unpin,
    P::Target: FusedStream,
{
    fn is_terminated(&self) -> bool {

::is_terminated(&**self)
    }
}

mod private_try_stream {
    use super::Stream;

    pub trait Sealed {}

    impl<S, T, E> Sealed for S where S: ?Sized + Stream<Item = Result<T, E>> {}
}

/// A convenience for streams that return `Result` values that includes
/// a variety of adapters tailored to such futures.
pub trait TryStream: Stream + private_try_stream::Sealed {
    /// The type of successful values yielded by this future
    type Ok;

    /// The type of failures yielded by this future
    type Error;

    /// Poll this `TryStream` as if it were a `Stream`.
    ///
    /// This method is a stopgap for a compiler limitation that prevents us from
    /// directly inheriting from the `Stream` trait; in the future it won't be
    /// needed.
    fn try_poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>)
        -> Poll<Option<Result<Self::Ok, Self::Error>>>;
}

impl<S, T, E> TryStream for S
    where S: ?Sized + Stream<Item = Result<T, E>>
{
    type Ok = T;
    type Error = E;

    fn try_poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>)
        -> Poll<Option<Result<Self::Ok, Self::Error>>>
    {
        self.poll_next(cx)
    }
}

#[cfg(feature = "alloc")]
mod if_alloc {
    use alloc::boxed::Box;
    use super::*;

    impl<S: ?Sized + Stream + Unpin> Stream for Box<S> {
        type Item = S::Item;

        fn poll_next(
            mut self: Pin<&mut Self>,
            cx: &mut Context<'_>,
        ) -> Poll<Option<Self::Item>> {
            Pin::new(&mut **self).poll_next(cx)
        }

        fn size_hint(&self) -> (usize, Option<usize>) {
            (**self).size_hint()
        }
    }

    #[cfg(feature = "std")]
    impl<S: Stream> Stream for std::panic::AssertUnwindSafe<S> {
        type Item = S::Item;

        fn poll_next(
            self: Pin<&mut Self>,
            cx: &mut Context<'_>,
        ) -> Poll<Option<S::Item>> {
            unsafe { self.map_unchecked_mut(|x| &mut x.0) }.poll_next(cx)
        }

        fn size_hint(&self) -> (usize, Option<usize>) {
            self.0.size_hint()
        }
    }

    impl<S: ?Sized + FusedStream + Unpin> FusedStream for Box<S> {
        fn is_terminated(&self) -> bool {
            <S as FusedStream>::is_terminated(&**self)
        }
    }
}
<commit_msg>Clarify stream doc's "bad behavior"<commit_after>//! Asynchronous streams.

use core::ops::DerefMut;
use core::pin::Pin;
use core::task::{Context, Poll};

/// An owned dynamically typed [`Stream`] for use in cases where you can't
/// statically type your result or need to add some indirection.
#[cfg(feature = "alloc")]
pub type BoxStream<'a, T> = Pin<alloc::boxed::Box<dyn Stream<Item = T> + Send + 'a>>;

/// `BoxStream`, but without the `Send` requirement.
#[cfg(feature = "alloc")]
pub type LocalBoxStream<'a, T> = Pin<alloc::boxed::Box<dyn Stream<Item = T> + 'a>>;

/// A stream of values produced asynchronously.
///
/// If `Future<Output = T>` is an asynchronous version of `T`, then `Stream<Item
/// = T>` is an asynchronous version of `Iterator<Item = T>`. A stream
/// represents a sequence of value-producing events that occur asynchronously to
/// the caller.
///
/// The trait is modeled after `Future`, but allows `poll_next` to be called
/// even after a value has been produced, yielding `None` once the stream has
/// been fully exhausted.
#[must_use = "streams do nothing unless polled"]
pub trait Stream {
    /// Values yielded by the stream.
    type Item;

    /// Attempt to pull out the next value of this stream, registering the
    /// current task for wakeup if the value is not yet available, and returning
    /// `None` if the stream is exhausted.
    ///
    /// # Return value
    ///
    /// There are several possible return values, each indicating a distinct
    /// stream state:
    ///
    /// - `Poll::Pending` means that this stream's next value is not ready
    /// yet. Implementations will ensure that the current task will be notified
    /// when the next value may be ready.
    ///
    /// - `Poll::Ready(Some(val))` means that the stream has successfully
    /// produced a value, `val`, and may produce further values on subsequent
    /// `poll_next` calls.
    ///
    /// - `Poll::Ready(None)` means that the stream has terminated, and
    /// `poll_next` should not be invoked again.
    ///
    /// # Panics
    ///
    /// Once a stream has finished (returned `Ready(None)` from `poll_next`), calling its
    /// `poll_next` method again may panic, block forever, or cause other kinds of
    /// problems; the `Stream` trait places no requirements on the effects of
    /// such a call. However, as the `poll_next` method is not marked `unsafe`,
    /// Rust's usual rules apply: calls must never cause undefined behavior
    /// (memory corruption, incorrect use of `unsafe` functions, or the like),
    /// regardless of the stream's state.
    ///
    /// If this is difficult to guard against then the [`fuse`] adapter can be used
    /// to ensure that `poll_next` always returns `Ready(None)` in subsequent
    /// calls.
    ///
    /// [`fuse`]: https://docs.rs/futures/0.3/futures/stream/trait.StreamExt.html#method.fuse
    fn poll_next(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>>;

    /// Returns the bounds on the remaining length of the stream.
    ///
    /// Specifically, `size_hint()` returns a tuple where the first element
    /// is the lower bound, and the second element is the upper bound.
    ///
    /// The second half of the tuple that is returned is an [`Option`]`<`[`usize`]`>`.
    /// A [`None`] here means that either there is no known upper bound, or the
    /// upper bound is larger than [`usize`].
    ///
    /// # Implementation notes
    ///
    /// It is not enforced that a stream implementation yields the declared
    /// number of elements. A buggy stream may yield less than the lower bound
    /// or more than the upper bound of elements.
    ///
    /// `size_hint()` is primarily intended to be used for optimizations such as
    /// reserving space for the elements of the stream, but must not be
    /// trusted to e.g., omit bounds checks in unsafe code. An incorrect
    /// implementation of `size_hint()` should not lead to memory safety
    /// violations.
    ///
    /// That said, the implementation should provide a correct estimation,
    /// because otherwise it would be a violation of the trait's protocol.
    ///
    /// The default implementation returns `(0, `[`None`]`)` which is correct for any
    /// stream.
    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, None)
    }
}

impl<S: ?Sized + Stream + Unpin> Stream for &mut S {
    type Item = S::Item;

    fn poll_next(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        S::poll_next(Pin::new(&mut **self), cx)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (**self).size_hint()
    }
}

impl
 Stream for Pin

where
    P: DerefMut + Unpin,
    P::Target: Stream,
{
    type Item =
::Item;

    fn poll_next(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Self::Item>> {
        self.get_mut().as_mut().poll_next(cx)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (**self).size_hint()
    }
}

/// A stream which tracks whether or not the underlying stream
/// should no longer be polled.
///
/// `is_terminated` will return `true` if a future should no longer be polled.
/// Usually, this state occurs after `poll_next` (or `try_poll_next`) returned
/// `Poll::Ready(None)`. However, `is_terminated` may also return `true` if a
/// stream has become inactive and can no longer make progress and should be
/// ignored or dropped rather than being polled again.
pub trait FusedStream: Stream {
    /// Returns `true` if the stream should no longer be polled.
    fn is_terminated(&self) -> bool;
}

impl<F: ?Sized + FusedStream + Unpin> FusedStream for &mut F {
    fn is_terminated(&self) -> bool {
        <F as FusedStream>::is_terminated(&**self)
    }
}

impl
 FusedStream for Pin

where
    P: DerefMut + Unpin,
    P::Target: FusedStream,
{
    fn is_terminated(&self) -> bool {

::is_terminated(&**self)
    }
}

mod private_try_stream {
    use super::Stream;

    pub trait Sealed {}

    impl<S, T, E> Sealed for S where S: ?Sized + Stream<Item = Result<T, E>> {}
}

/// A convenience for streams that return `Result` values that includes
/// a variety of adapters tailored to such futures.
pub trait TryStream: Stream + private_try_stream::Sealed {
    /// The type of successful values yielded by this future
    type Ok;

    /// The type of failures yielded by this future
    type Error;

    /// Poll this `TryStream` as if it were a `Stream`.
    ///
    /// This method is a stopgap for a compiler limitation that prevents us from
    /// directly inheriting from the `Stream` trait; in the future it won't be
    /// needed.
    fn try_poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>)
        -> Poll<Option<Result<Self::Ok, Self::Error>>>;
}

impl<S, T, E> TryStream for S
    where S: ?Sized + Stream<Item = Result<T, E>>
{
    type Ok = T;
    type Error = E;

    fn try_poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>)
        -> Poll<Option<Result<Self::Ok, Self::Error>>>
    {
        self.poll_next(cx)
    }
}

#[cfg(feature = "alloc")]
mod if_alloc {
    use alloc::boxed::Box;
    use super::*;

    impl<S: ?Sized + Stream + Unpin> Stream for Box<S> {
        type Item = S::Item;

        fn poll_next(
            mut self: Pin<&mut Self>,
            cx: &mut Context<'_>,
        ) -> Poll<Option<Self::Item>> {
            Pin::new(&mut **self).poll_next(cx)
        }

        fn size_hint(&self) -> (usize, Option<usize>) {
            (**self).size_hint()
        }
    }

    #[cfg(feature = "std")]
    impl<S: Stream> Stream for std::panic::AssertUnwindSafe<S> {
        type Item = S::Item;

        fn poll_next(
            self: Pin<&mut Self>,
            cx: &mut Context<'_>,
        ) -> Poll<Option<S::Item>> {
            unsafe { self.map_unchecked_mut(|x| &mut x.0) }.poll_next(cx)
        }

        fn size_hint(&self) -> (usize, Option<usize>) {
            self.0.size_hint()
        }
    }

    impl<S: ?Sized + FusedStream + Unpin> FusedStream for Box<S> {
        fn is_terminated(&self) -> bool {
            <S as FusedStream>::is_terminated(&**self)
        }
    }
}
<|endoftext|>


<commit_before>extern crate lapin_futures as lapin;
extern crate futures;
extern crate tokio_core;
extern crate tokio_proto;
extern crate env_logger;

use futures::future::Future;
use futures::Stream;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;

fn main() {
      env_logger::init().unwrap();
      let mut core = Core::new().unwrap();

      let handle = core.handle();
      let addr = "127.0.0.1:5672".parse().unwrap();

      core.run(
        TcpStream::connect(&addr, &handle).and_then(|stream| {
          lapin::client::Client::connect(stream)
            .and_then(|client| {
              println!("client exists");
              client.create_channel().and_then(|channel| {
                let id = channel.id;
                println!("created channel with id: {}", id);
                channel.queue_declare("hello").and_then(move |_| {
                  println!("channel {} declared queue {}", id, "hello");
                  channel.basic_publish("hello", b"hello from tokio")
                })
              }).and_then(move |_| {
                client.create_channel().and_then(|channel| {
                  let id = channel.id;
                  println!("created channel with id: {}", id);
                  channel.queue_declare("hello").and_then(move |_| {
                    println!("channel {} declared queue {}", id, "hello");
                    channel.basic_consume("hello", "my_consumer").and_then(|stream| {
                      println!("got consumer stream");
                      stream.for_each(|message| {
                        println!("got message: {:?}", message);
                        println!("decoded message: {:?}", std::str::from_utf8(&message.data).unwrap());
                        Ok(())
                      })

                    })
                  })
                })
              })
            })
        })
      ).unwrap();
      panic!();
}
<commit_msg>flatten a bit the futures chaining<commit_after>extern crate lapin_futures as lapin;
extern crate futures;
extern crate tokio_core;
extern crate tokio_proto;
extern crate env_logger;

use futures::future::Future;
use futures::Stream;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;

fn main() {
  env_logger::init().unwrap();
  let mut core = Core::new().unwrap();

  let handle = core.handle();
  let addr = "127.0.0.1:5672".parse().unwrap();

  core.run(
    TcpStream::connect(&addr, &handle).and_then(|stream| {
      lapin::client::Client::connect(stream)
    }).and_then(|client| {

      client.create_channel().and_then(|channel| {
        let id = channel.id;
        println!("created channel with id: {}", id);

        channel.queue_declare("hello").and_then(move |_| {
          println!("channel {} declared queue {}", id, "hello");

          channel.basic_publish("hello", b"hello from tokio")
        })
      }).and_then(move |_| {
        client.create_channel()
      }).and_then(|channel| {
        let id = channel.id;
        println!("created channel with id: {}", id);

        channel.queue_declare("hello").and_then(move |_| {
          println!("channel {} declared queue {}", id, "hello");

          channel.basic_consume("hello", "my_consumer")
        }).and_then(|stream| {
          println!("got consumer stream");

          stream.for_each(|message| {
            println!("got message: {:?}", message);
            println!("decoded message: {:?}", std::str::from_utf8(&message.data).unwrap());
            Ok(())
          })
        })
      })
    })
  ).unwrap();
}
<|endoftext|>


<commit_before>extern crate whois;
extern crate rustc_serialize;

use whois::WhoIs;
use rustc_serialize::json::Json;

fn main() {
    let data = WhoIs::new("google.com".to_owned()).lookup();
    let foo = &Json::from_str(&data.unwrap()).unwrap();
    let object = foo.as_object().unwrap();
    for (key, value) in object {
        println!("{}: {}", key, match *value {
            Json::String(ref v) => format!("{}", v),
            _ => break
        });
    }
}
<commit_msg>Update test.rs<commit_after>extern crate whois;
extern crate rustc_serialize;

use whois::WhoIs;
use rustc_serialize::json::Json;

fn main() {
    let data = WhoIs::new("google.com").lookup();
    let foo = &Json::from_str(&data.unwrap()).unwrap();
    let object = foo.as_object().unwrap();
    for (key, value) in object {
        println!("{}: {}", key, match *value {
            Json::String(ref v) => format!("{}", v),
            _ => break
        });
    }
}
<|endoftext|>


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

//! Utilities for the implementation of JSAPI proxy handlers.

#![deny(missing_docs)]

use dom::bindings::conversions::is_dom_proxy;
use dom::bindings::utils::delete_property_by_id;
use js::jsapi::{JSContext, JSPropertyDescriptor, JSObject, JSString};
use js::jsapi::{JS_GetPropertyDescriptorById, JS_NewStringCopyN};
use js::jsapi::{JS_DefinePropertyById6, JS_NewObjectWithGivenProto};
use js::jsapi::{JS_StrictPropertyStub, JSErrNum};
use js::jsapi::{Handle, HandleObject, HandleId, MutableHandle, RootedObject, ObjectOpResult};
use js::jsapi::AutoIdVector;
use js::jsapi::GetObjectProto;
use js::jsval::ObjectValue;
use js::glue::GetProxyExtra;
use js::glue::{SetProxyExtra, GetProxyHandler};
use js::glue::InvokeGetOwnPropertyDescriptor;
use js::{JSPROP_GETTER, JSPROP_ENUMERATE, JSPROP_READONLY};
use js::{JSTrue, JSFalse};

use libc;
use std::mem;
use std::ptr;

static JSPROXYSLOT_EXPANDO: u32 = 0;

/// Invoke the [[GetOwnProperty]] trap (`getOwnPropertyDescriptor`) on `proxy`,
/// with argument `id` and return the result, if it is not `undefined`.
/// Otherwise, walk along the prototype chain to find a property with that
/// name.
pub unsafe extern fn get_property_descriptor(cx: *mut JSContext,
                                             proxy: HandleObject,
                                             id: HandleId,
                                             desc: MutableHandle<JSPropertyDescriptor>)
                                             -> u8 {
    let handler = GetProxyHandler(proxy.get());
    if InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, desc) == 0 {
        return JSFalse;
    }
    if !desc.get().obj.is_null() {
        return JSTrue;
    }

    let mut proto = RootedObject::new(cx, ptr::null_mut());
    if GetObjectProto(cx, proxy, proto.handle_mut()) == 0 {
        desc.get().obj = ptr::null_mut();
        return JSTrue;
    }

    JS_GetPropertyDescriptorById(cx, proto.handle(), id, desc)
}

/// Defines an expando on the given `proxy`.
pub unsafe extern fn define_property(cx: *mut JSContext, proxy: HandleObject,
                                     id: HandleId, desc: Handle<JSPropertyDescriptor>,
                                     result: *mut ObjectOpResult)
                                     -> u8 {
    //FIXME: Workaround for https://github.com/mozilla/rust/issues/13385
    let setter: *const libc::c_void = mem::transmute(desc.get().setter);
    let setter_stub: *const libc::c_void = mem::transmute(JS_StrictPropertyStub);
    if (desc.get().attrs & JSPROP_GETTER) != 0 && setter == setter_stub {
        (*result).code_ = JSErrNum::JSMSG_GETTER_ONLY as u32;
        return JSTrue;
    }

    let expando = RootedObject::new(cx, ensure_expando_object(cx, proxy));
    JS_DefinePropertyById6(cx, expando.handle(), id, desc, result)
}

/// Deletes an expando off the given `proxy`.
pub unsafe extern fn delete(cx: *mut JSContext, proxy: HandleObject, id: HandleId,
                            bp: *mut ObjectOpResult) -> u8 {
    let expando = RootedObject::new(cx, get_expando_object(proxy));
    if expando.ptr.is_null() {
        (*bp).code_ = 0 /* OkCode */;
        return JSTrue;
    }

    delete_property_by_id(cx, expando.handle(), id, bp)
}

/// Stub for ownPropertyKeys
pub unsafe extern fn own_property_keys(_cx: *mut JSContext,
                                       _proxy: HandleObject,
                                       _props: *mut AutoIdVector) -> u8 {
    // FIXME: implement this
    // https://github.com/servo/servo/issues/6390
    JSTrue
}

/// Controls whether the Extensible bit can be changed
pub unsafe extern fn prevent_extensions(_cx: *mut JSContext,
                                        _proxy: HandleObject,
                                        result: *mut ObjectOpResult) -> u8 {
    (*result).code_ = JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS as u32;
    return JSTrue;
}

/// Reports whether the object is Extensible
pub unsafe extern fn is_extensible(_cx: *mut JSContext, _proxy: HandleObject,
                                   succeeded: *mut u8) -> u8 {
    *succeeded = JSTrue;
    return JSTrue;
}

/// Returns the stringification of an object with class `name`.
pub fn object_to_string(cx: *mut JSContext, name: &str) -> *mut JSString {
    unsafe {
        let result = format!("[object {}]", name);

        let chars = result.as_ptr() as *const libc::c_char;
        let length = result.len() as libc::size_t;

        let string = JS_NewStringCopyN(cx, chars, length);
        assert!(!string.is_null());
        return string;
    }
}

/// Get the expando object, or null if there is none.
pub fn get_expando_object(obj: HandleObject) -> *mut JSObject {
    unsafe {
        assert!(is_dom_proxy(obj.get()));
        let val = GetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO);
        if val.is_undefined() {
            ptr::null_mut()
        } else {
            val.to_object()
        }
    }
}

/// Get the expando object, or create it if it doesn't exist yet.
/// Fails on JSAPI failure.
pub fn ensure_expando_object(cx: *mut JSContext, obj: HandleObject)
                             -> *mut JSObject {
    unsafe {
        assert!(is_dom_proxy(obj.get()));
        let mut expando = get_expando_object(obj);
        if expando.is_null() {
            expando = JS_NewObjectWithGivenProto(cx, ptr::null_mut(), HandleObject::null());
            assert!(!expando.is_null());

            SetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO, ObjectValue(&*expando));
        }
        return expando;
    }
}

/// Set the property descriptor's object to `obj` and set it to enumerable,
/// and writable if `readonly` is true.
pub fn fill_property_descriptor(desc: &mut JSPropertyDescriptor,
                                obj: *mut JSObject, readonly: bool) {
    desc.obj = obj;
    desc.attrs = if readonly { JSPROP_READONLY } else { 0 } | JSPROP_ENUMERATE;
    desc.getter = None;
    desc.setter = None;
}
<commit_msg>Auto merge of #7107 - AdrianArroyoCalle:master, r=Ms2ger<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Utilities for the implementation of JSAPI proxy handlers.

#![deny(missing_docs)]

use dom::bindings::conversions::is_dom_proxy;
use dom::bindings::utils::delete_property_by_id;
use js::jsapi::{JSContext, JSPropertyDescriptor, JSObject};
use js::jsapi::{JS_GetPropertyDescriptorById};
use js::jsapi::{JS_DefinePropertyById6, JS_NewObjectWithGivenProto};
use js::jsapi::{JS_StrictPropertyStub, JSErrNum};
use js::jsapi::{Handle, HandleObject, HandleId, MutableHandle, RootedObject, ObjectOpResult};
use js::jsapi::AutoIdVector;
use js::jsapi::GetObjectProto;
use js::jsval::ObjectValue;
use js::glue::GetProxyExtra;
use js::glue::{SetProxyExtra, GetProxyHandler};
use js::glue::InvokeGetOwnPropertyDescriptor;
use js::{JSPROP_GETTER, JSPROP_ENUMERATE, JSPROP_READONLY};
use js::{JSTrue, JSFalse};

use libc;
use std::mem;
use std::ptr;

static JSPROXYSLOT_EXPANDO: u32 = 0;

/// Invoke the [[GetOwnProperty]] trap (`getOwnPropertyDescriptor`) on `proxy`,
/// with argument `id` and return the result, if it is not `undefined`.
/// Otherwise, walk along the prototype chain to find a property with that
/// name.
pub unsafe extern fn get_property_descriptor(cx: *mut JSContext,
                                             proxy: HandleObject,
                                             id: HandleId,
                                             desc: MutableHandle<JSPropertyDescriptor>)
                                             -> u8 {
    let handler = GetProxyHandler(proxy.get());
    if InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, desc) == 0 {
        return JSFalse;
    }
    if !desc.get().obj.is_null() {
        return JSTrue;
    }

    let mut proto = RootedObject::new(cx, ptr::null_mut());
    if GetObjectProto(cx, proxy, proto.handle_mut()) == 0 {
        desc.get().obj = ptr::null_mut();
        return JSTrue;
    }

    JS_GetPropertyDescriptorById(cx, proto.handle(), id, desc)
}

/// Defines an expando on the given `proxy`.
pub unsafe extern fn define_property(cx: *mut JSContext, proxy: HandleObject,
                                     id: HandleId, desc: Handle<JSPropertyDescriptor>,
                                     result: *mut ObjectOpResult)
                                     -> u8 {
    //FIXME: Workaround for https://github.com/mozilla/rust/issues/13385
    let setter: *const libc::c_void = mem::transmute(desc.get().setter);
    let setter_stub: *const libc::c_void = mem::transmute(JS_StrictPropertyStub);
    if (desc.get().attrs & JSPROP_GETTER) != 0 && setter == setter_stub {
        (*result).code_ = JSErrNum::JSMSG_GETTER_ONLY as u32;
        return JSTrue;
    }

    let expando = RootedObject::new(cx, ensure_expando_object(cx, proxy));
    JS_DefinePropertyById6(cx, expando.handle(), id, desc, result)
}

/// Deletes an expando off the given `proxy`.
pub unsafe extern fn delete(cx: *mut JSContext, proxy: HandleObject, id: HandleId,
                            bp: *mut ObjectOpResult) -> u8 {
    let expando = RootedObject::new(cx, get_expando_object(proxy));
    if expando.ptr.is_null() {
        (*bp).code_ = 0 /* OkCode */;
        return JSTrue;
    }

    delete_property_by_id(cx, expando.handle(), id, bp)
}

/// Stub for ownPropertyKeys
pub unsafe extern fn own_property_keys(_cx: *mut JSContext,
                                       _proxy: HandleObject,
                                       _props: *mut AutoIdVector) -> u8 {
    // FIXME: implement this
    // https://github.com/servo/servo/issues/6390
    JSTrue
}

/// Controls whether the Extensible bit can be changed
pub unsafe extern fn prevent_extensions(_cx: *mut JSContext,
                                        _proxy: HandleObject,
                                        result: *mut ObjectOpResult) -> u8 {
    (*result).code_ = JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS as u32;
    return JSTrue;
}

/// Reports whether the object is Extensible
pub unsafe extern fn is_extensible(_cx: *mut JSContext, _proxy: HandleObject,
                                   succeeded: *mut u8) -> u8 {
    *succeeded = JSTrue;
    return JSTrue;
}

/// Get the expando object, or null if there is none.
pub fn get_expando_object(obj: HandleObject) -> *mut JSObject {
    unsafe {
        assert!(is_dom_proxy(obj.get()));
        let val = GetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO);
        if val.is_undefined() {
            ptr::null_mut()
        } else {
            val.to_object()
        }
    }
}

/// Get the expando object, or create it if it doesn't exist yet.
/// Fails on JSAPI failure.
pub fn ensure_expando_object(cx: *mut JSContext, obj: HandleObject)
                             -> *mut JSObject {
    unsafe {
        assert!(is_dom_proxy(obj.get()));
        let mut expando = get_expando_object(obj);
        if expando.is_null() {
            expando = JS_NewObjectWithGivenProto(cx, ptr::null_mut(), HandleObject::null());
            assert!(!expando.is_null());

            SetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO, ObjectValue(&*expando));
        }
        return expando;
    }
}

/// Set the property descriptor's object to `obj` and set it to enumerable,
/// and writable if `readonly` is true.
pub fn fill_property_descriptor(desc: &mut JSPropertyDescriptor,
                                obj: *mut JSObject, readonly: bool) {
    desc.obj = obj;
    desc.attrs = if readonly { JSPROP_READONLY } else { 0 } | JSPROP_ENUMERATE;
    desc.getter = None;
    desc.setter = None;
}
<|endoftext|>