<commit_before>use audio::ac97::AC97;
use audio::intelhda::IntelHDA;

use core::cell::UnsafeCell;

use common::debug;

use disk::ahci::Ahci;
use disk::ide::Ide;

use drivers::pci::config::PciConfig;

use env::Environment;

use network::intel8254x::Intel8254x;
use network::rtl8139::Rtl8139;

use schemes::file::FileScheme;

use usb::ehci::Ehci;
use usb::ohci::Ohci;
use usb::uhci::Uhci;
use usb::xhci::Xhci;

/// PCI device
pub unsafe fn pci_device(env: &mut Environment,
                         mut pci: PciConfig,
                         class_id: u32,
                         subclass_id: u32,
                         interface_id: u32,
                         vendor_code: u32,
                         device_code: u32) {
    if class_id == 0x01 {
        if subclass_id == 0x01 {
            if let Some(module) = FileScheme::new(Ide::disks(pci)) {
                env.schemes.push(UnsafeCell::new(module));
            }
        } else if subclass_id == 0x06 {
            if let Some(module) = FileScheme::new(Ahci::disks(pci)) {
                env.schemes.push(UnsafeCell::new(module));
            }
        }
    } else if class_id == 0x0C && subclass_id == 0x03 {
        if interface_id == 0x30 {
            let base = pci.read(0x10) as usize;

            let mut module = box Xhci {
                pci: pci,
                base: base & 0xFFFFFFF0,
                memory_mapped: base & 1 == 0,
                irq: pci.read(0x3C) as u8 & 0xF,
            };
            module.init();
            env.schemes.push(UnsafeCell::new(module));
        } else if interface_id == 0x20 {
            env.schemes.push(UnsafeCell::new(Ehci::new(pci)));
        } else if interface_id == 0x10 {
            env.schemes.push(UnsafeCell::new(Ohci::new(pci)));
        } else if interface_id == 0x00 {
            env.schemes.push(UnsafeCell::new(Uhci::new(pci)));
        } else {
            debug!("Unknown USB interface version {:X}\n", interface_id);
        }
    } else {
        match vendor_code {
            0x10EC => match device_code { // REALTEK
                0x8139 => env.schemes.push(UnsafeCell::new(Rtl8139::new(pci))),
                _ => (),
            },
            0x8086 => match device_code { // INTEL
                0x100E => env.schemes.push(UnsafeCell::new(Intel8254x::new(pci))),
                0x2415 => env.schemes.push(UnsafeCell::new(AC97::new(pci))),
                0x24C5 => env.schemes.push(UnsafeCell::new(AC97::new(pci))),
                0x2668 => {
                    let base = pci.read(0x10) as usize;
                    let mut module = box IntelHDA {
                        pci: pci,
                        base: base & 0xFFFFFFF0,
                        memory_mapped: base & 1 == 0,
                        irq: pci.read(0x3C) as u8 & 0xF,
                    };
                    module.init();
                    env.schemes.push(UnsafeCell::new(module));
                }
                _ => (),
            },
            _ => (),
        }
    }
}

/// Initialize PCI session
pub unsafe fn pci_init(env: &mut Environment) {
    for bus in 0..256 {
        for slot in 0..32 {
            for func in 0..8 {
                let mut pci = PciConfig::new(bus as u8, slot as u8, func as u8);
                let id = pci.read(0);

                if (id & 0xFFFF) != 0xFFFF {
                    let class_id = pci.read(8);

                    debug!(" * PCI {}, {}, {}: ID {:X} CL {:X}",
                           bus,
                           slot,
                           func,
                           id,
                           class_id);

                    for i in 0..6 {
                        let bar = pci.read(i * 4 + 0x10);
                        if bar > 0 {
                            debug!(" BAR{}: {:X}", i, bar);

                            pci.write(i * 4 + 0x10, 0xFFFFFFFF);
                            let size = (0xFFFFFFFF - (pci.read(i * 4 + 0x10) & 0xFFFFFFF0)) + 1;
                            pci.write(i * 4 + 0x10, bar);

                            if size > 0 {
                                debug!(" {}", size);
                            }
                        }
                    }

                    debug::dl();

                    pci_device(env,
                               pci,
                               (class_id >> 24) & 0xFF,
                               (class_id >> 16) & 0xFF,
                               (class_id >> 8) & 0xFF,
                               id & 0xFFFF,
                               (id >> 16) & 0xFFFF);
                }
            }
        }
    }
}
<commit_msg>[PCI refactor] Use constants instead of raw numbers<commit_after>use audio::ac97::AC97;
use audio::intelhda::IntelHDA;

use core::cell::UnsafeCell;

use common::debug;

use disk::ahci::Ahci;
use disk::ide::Ide;

use env::Environment;

use network::intel8254x::Intel8254x;
use network::rtl8139::Rtl8139;

use schemes::file::FileScheme;

use usb::ehci::Ehci;
use usb::ohci::Ohci;
use usb::uhci::Uhci;
use usb::xhci::Xhci;

use super::config::PciConfig;
use super::common::class::*;
use super::common::subclass::*;
use super::common::programming_interface::*;

/// PCI device
pub unsafe fn pci_device(env: &mut Environment,
                         mut pci: PciConfig,
                         class_id: u8,
                         subclass_id: u8,
                         interface_id: u8,
                         vendor_code: u16,
                         device_code: u16) {
    if class_id == MASS_STORAGE {
        if subclass_id == IDE {
            if let Some(module) = FileScheme::new(Ide::disks(pci)) {
                env.schemes.push(UnsafeCell::new(module));
            }
        } else if subclass_id == SATA && interface_id == AHCI {
            if let Some(module) = FileScheme::new(Ahci::disks(pci)) {
                env.schemes.push(UnsafeCell::new(module));
            }
        }
    } else if class_id == SERIAL_BUS && subclass_id == USB {
        if interface_id == XHCI {
            let base = pci.read(0x10) as usize;

            let mut module = box Xhci {
                pci: pci,
                base: base & 0xFFFFFFF0,
                memory_mapped: base & 1 == 0,
                irq: pci.read(0x3C) as u8 & 0xF,
            };
            module.init();
            env.schemes.push(UnsafeCell::new(module));
        } else if interface_id == EHCI {
            env.schemes.push(UnsafeCell::new(Ehci::new(pci)));
        } else if interface_id == OHCI {
            env.schemes.push(UnsafeCell::new(Ohci::new(pci)));
        } else if interface_id == UHCI {
            env.schemes.push(UnsafeCell::new(Uhci::new(pci)));
        } else {
            debug!("Unknown USB interface version {:X}\n", interface_id);
        }
    } else {
        match vendor_code {
            0x10EC => match device_code { // REALTEK
                0x8139 => env.schemes.push(UnsafeCell::new(Rtl8139::new(pci))),
                _ => (),
            },
            0x8086 => match device_code { // INTEL
                0x100E => env.schemes.push(UnsafeCell::new(Intel8254x::new(pci))),
                0x2415 => env.schemes.push(UnsafeCell::new(AC97::new(pci))),
                0x24C5 => env.schemes.push(UnsafeCell::new(AC97::new(pci))),
                0x2668 => {
                    let base = pci.read(0x10) as usize;
                    let mut module = box IntelHDA {
                        pci: pci,
                        base: base & 0xFFFFFFF0,
                        memory_mapped: base & 1 == 0,
                        irq: pci.read(0x3C) as u8 & 0xF,
                    };
                    module.init();
                    env.schemes.push(UnsafeCell::new(module));
                }
                _ => (),
            },
            _ => (),
        }
    }
}

/// Initialize PCI session
pub unsafe fn pci_init(env: &mut Environment) {
    for bus in 0..256 {
        for slot in 0..32 {
            for func in 0..8 {
                let mut pci = PciConfig::new(bus as u8, slot as u8, func as u8);
                let id = pci.read(0);

                if (id & 0xFFFF) != 0xFFFF {
                    let class_id = pci.read(8);

                    debug!(" * PCI {}, {}, {}: ID {:X} CL {:X}",
                           bus,
                           slot,
                           func,
                           id,
                           class_id);

                    for i in 0..6 {
                        let bar = pci.read(i * 4 + 0x10);
                        if bar > 0 {
                            debug!(" BAR{}: {:X}", i, bar);

                            pci.write(i * 4 + 0x10, 0xFFFFFFFF);
                            let size = (0xFFFFFFFF - (pci.read(i * 4 + 0x10) & 0xFFFFFFF0)) + 1;
                            pci.write(i * 4 + 0x10, bar);

                            if size > 0 {
                                debug!(" {}", size);
                            }
                        }
                    }

                    debug::dl();

                    pci_device(env,
                               pci,
                               ((class_id >> 24) & 0xFF) as u8,
                               ((class_id >> 16) & 0xFF) as u8,
                               ((class_id >> 8) & 0xFF) as u8,
                               (id & 0xFFFF) as u16,
                               ((id >> 16) & 0xFFFF) as u16);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016  ParadoxSpiral
//
// This file is part of mpv-rs.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use mpv;
use mpv::{MpvInstance, MpvError, Parent, PlaylistOp};
use mpv::utils;
use mpv::protocol::*;

use std::env;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::mem;
use std::path::Path;
use std::slice;
use std::time::Duration;
use std::thread;

unsafe fn open(cookie: *mut File, _: &mut (), uri: &str) -> Result<(), MpvError> {
    // Strip the `filereader://` part
    *cookie = File::open(&uri[13..]).unwrap();

    println!("Opened file, ready for orders o7");
    Ok(())
}

unsafe fn close(_: Box<File>) {
    println!("Closing file, bye bye~~");
}

unsafe fn read(cookie: &mut File, buf: *mut i8, nbytes: u64) -> i64 {
    let slice = slice::from_raw_parts_mut(buf, nbytes as _);
    let forbidden_magic = mem::transmute::<&mut [i8], &mut [u8]>(slice);

    cookie.read(forbidden_magic).unwrap() as _
}

unsafe fn seek(cookie: &mut File, offset: i64) -> i64 {
    cookie.seek(SeekFrom::Start(offset as u64)).unwrap() as _
}

unsafe fn size(cookie: &mut File) -> i64 {
    cookie.metadata().unwrap().len() as _
}

pub fn exec() {
    let path = format!("filereader://{}",
                       env::args()
                           .nth(1)
                           .expect("Expected local path, found nil."));

    let protocol = Protocol::new("filereader".into(),
                                 (),
                                 open as _,
                                 close as _,
                                 read as _,
                                 Some(seek as _),
                                 Some(size as _));

    let mpv = Parent::new(false).unwrap();
    mpv.register_protocol(protocol).unwrap();

    mpv.set_property("volume", 30).unwrap();

    mpv.playlist(&PlaylistOp::Loadfiles(&[utils::File::new(Path::new(&path),
                                                           utils::FileState::AppendPlay,
                                                           None)]))
       .unwrap();

    thread::sleep(Duration::from_secs(10));

    mpv.seek(&mpv::Seek::RelativeForward(Duration::from_secs(15))).unwrap();

    thread::sleep(Duration::from_secs(5));
}
<commit_msg>[example] Remove unnecessary cast<commit_after>// Copyright (C) 2016  ParadoxSpiral
//
// This file is part of mpv-rs.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use mpv;
use mpv::{MpvInstance, MpvError, Parent, PlaylistOp};
use mpv::utils;
use mpv::protocol::*;

use std::env;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::mem;
use std::path::Path;
use std::slice;
use std::time::Duration;
use std::thread;

unsafe fn open(cookie: *mut File, _: &mut (), uri: &str) -> Result<(), MpvError> {
    // Strip the `filereader://` part
    *cookie = File::open(&uri[13..]).unwrap();

    println!("Opened file, ready for orders o7");
    Ok(())
}

unsafe fn close(_: Box<File>) {
    println!("Closing file, bye bye~~");
}

unsafe fn read(cookie: &mut File, buf: *mut i8, nbytes: u64) -> i64 {
    let slice = slice::from_raw_parts_mut(buf, nbytes as _);
    let forbidden_magic = mem::transmute::<&mut [i8], &mut [u8]>(slice);

    cookie.read(forbidden_magic).unwrap() as _
}

unsafe fn seek(cookie: &mut File, offset: i64) -> i64 {
    cookie.seek(SeekFrom::Start(offset as u64)).unwrap() as _
}

unsafe fn size(cookie: &mut File) -> i64 {
    cookie.metadata().unwrap().len() as _
}

pub fn exec() {
    let path = format!("filereader://{}",
                       env::args()
                           .nth(1)
                           .expect("Expected local path, found nil."));

    let protocol = Protocol::new("filereader".into(),
                                 (),
                                 open,
                                 close,
                                 read,
                                 Some(seek),
                                 Some(size));

    let mpv = Parent::new(false).unwrap();
    mpv.register_protocol(protocol).unwrap();

    mpv.set_property("volume", 30).unwrap();

    mpv.playlist(&PlaylistOp::Loadfiles(&[utils::File::new(Path::new(&path),
                                                           utils::FileState::AppendPlay,
                                                           None)]))
       .unwrap();

    thread::sleep(Duration::from_secs(10));

    mpv.seek(&mpv::Seek::RelativeForward(Duration::from_secs(15))).unwrap();

    thread::sleep(Duration::from_secs(5));
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

use rand::{self, Rng, ThreadRng};
use slog::{self, Drain, OwnedKVList, Record};
use slog_async;
use std::env;
use std::fs::File;
use std::io::{self, Write};
use std::path::PathBuf;
use std::sync::Mutex;
use time;

use tikv::util;
use tikv::util::logger;
use tikv::util::security::SecurityConfig;

/// A random generator of kv.
/// Every iter should be taken in µs. See also `benches::bench_kv_iter`.
pub struct KvGenerator {
    key_len: usize,
    value_len: usize,
    rng: ThreadRng,
}

impl KvGenerator {
    pub fn new(key_len: usize, value_len: usize) -> KvGenerator {
        KvGenerator {
            key_len,
            value_len,
            rng: rand::thread_rng(),
        }
    }
}

impl Iterator for KvGenerator {
    type Item = (Vec<u8>, Vec<u8>);

    fn next(&mut self) -> Option<(Vec<u8>, Vec<u8>)> {
        let mut k = vec![0; self.key_len];
        self.rng.fill_bytes(&mut k);
        let mut v = vec![0; self.value_len];
        self.rng.fill_bytes(&mut v);

        Some((k, v))
    }
}

/// Generate n pair of kvs.
#[allow(dead_code)]
pub fn generate_random_kvs(n: usize, key_len: usize, value_len: usize) -> Vec<(Vec<u8>, Vec<u8>)> {
    let kv_generator = KvGenerator::new(key_len, value_len);
    kv_generator.take(n).collect()
}

/// A logger that add a test case tag before each line of log.
struct CaseTraceLogger {
    f: Option<Mutex<File>>,
}

impl Drain for CaseTraceLogger {
    type Ok = ();
    type Err = slog::Never;
    fn log(&self, record: &Record, values: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
        let tag = util::get_tag_from_thread_name().unwrap_or_else(|| "".into());

        let t = time::now();
        let time_str = time::strftime("%y/%m/%d %h:%m:%s.%f", &t).unwrap();
        // todo allow formatter to be configurable.
        let message = format!(
            "{} {} {}:{}: [{}] {} {:?}\n",
            tag,
            &time_str[..time_str.len() - 6],
            record.file().rsplit('/').nth(0).unwrap(),
            record.line(),
            record.level(),
            record.msg(),
            values,
        );

        if let Some(ref out) = self.f {
            let mut w = out.lock().unwrap();
            let _ = w.write(message.as_bytes());
        } else {
            let mut w = io::stderr();
            let _ = w.write(message.as_bytes());
        }
        Ok(())
    }
}

impl Drop for CaseTraceLogger {
    fn drop(&mut self) {
        if let Some(ref w) = self.f {
            w.lock().unwrap().flush().unwrap();
        }
    }
}

// A help function to initial logger.
fn init_log() {
    let output = env::var("LOG_FILE").ok();
    let level = logger::get_level_by_string(&env::var("LOG_LEVEL").unwrap_or_else(|_| "debug".to_owned()))
        .unwrap();
    let writer = output.map(|f| Mutex::new(File::create(f).unwrap()));
    // we don't mind set it multiple times.
    let drain = CaseTraceLogger { f: writer };
    let drain = slog_async::Async::new(drain).build().fuse();
    let logger = slog::Logger::root_typed(drain, slog_o!());
    let _ = logger::init_log_for_tikv_only(logger, level);
}

/// Set up ci test fail case log.
pub fn ci_setup() {
    if env::var("CI").is_ok() && env::var("LOG_FILE").is_ok() {
        init_log();
    }
    if env::var("PANIC_ABORT").is_ok() {
        // Panics as aborts, it's helpful for debugging,
        // but also stops tests immediately.
        util::panic_hook::set_exit_hook(true);
    }
}

pub fn new_security_cfg() -> SecurityConfig {
    let p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    SecurityConfig {
        ca_path: format!("{}", p.join("tests/data/ca.crt").display()),
        cert_path: format!("{}", p.join("tests/data/server.crt").display()),
        key_path: format!("{}", p.join("tests/data/server.pem").display()),
        override_ssl_target: "example.com".to_owned(),
    }
}
<commit_msg>fix test log time format and tag prefix. (#3096)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

use rand::{self, Rng, ThreadRng};
use slog::{self, Drain, OwnedKVList, Record};
use slog_async;
use std::env;
use std::fs::File;
use std::io::{self, Write};
use std::path::PathBuf;
use std::sync::Mutex;
use time;

use tikv::util;
use tikv::util::logger;
use tikv::util::security::SecurityConfig;

/// A random generator of kv.
/// Every iter should be taken in µs. See also `benches::bench_kv_iter`.
pub struct KvGenerator {
    key_len: usize,
    value_len: usize,
    rng: ThreadRng,
}

impl KvGenerator {
    pub fn new(key_len: usize, value_len: usize) -> KvGenerator {
        KvGenerator {
            key_len,
            value_len,
            rng: rand::thread_rng(),
        }
    }
}

impl Iterator for KvGenerator {
    type Item = (Vec<u8>, Vec<u8>);

    fn next(&mut self) -> Option<(Vec<u8>, Vec<u8>)> {
        let mut k = vec![0; self.key_len];
        self.rng.fill_bytes(&mut k);
        let mut v = vec![0; self.value_len];
        self.rng.fill_bytes(&mut v);

        Some((k, v))
    }
}

/// Generate n pair of kvs.
#[allow(dead_code)]
pub fn generate_random_kvs(n: usize, key_len: usize, value_len: usize) -> Vec<(Vec<u8>, Vec<u8>)> {
    let kv_generator = KvGenerator::new(key_len, value_len);
    kv_generator.take(n).collect()
}

/// A logger that add a test case tag before each line of log.
struct CaseTraceLogger {
    f: Option<Mutex<File>>,
}

impl Drain for CaseTraceLogger {
    type Ok = ();
    type Err = slog::Never;
    fn log(&self, record: &Record, _: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
        let tag = util::get_tag_from_thread_name().map_or_else(|| "".into(), |s| s + " ");

        let t = time::now();
        let time_str = time::strftime("%Y/%m/%d %H:%M:%S.%f", &t).unwrap();
        // todo allow formatter to be configurable.
        let message = format!(
            "{}{} {}:{}: [{}] {}\n",
            tag,
            &time_str[..time_str.len() - 6],
            record.file().rsplit('/').nth(0).unwrap(),
            record.line(),
            record.level(),
            record.msg(),
        );

        if let Some(ref out) = self.f {
            let mut w = out.lock().unwrap();
            let _ = w.write(message.as_bytes());
        } else {
            let mut w = io::stderr();
            let _ = w.write(message.as_bytes());
        }
        Ok(())
    }
}

impl Drop for CaseTraceLogger {
    fn drop(&mut self) {
        if let Some(ref w) = self.f {
            w.lock().unwrap().flush().unwrap();
        }
    }
}

// A help function to initial logger.
fn init_log() {
    let output = env::var("LOG_FILE").ok();
    let level = logger::get_level_by_string(&env::var("LOG_LEVEL").unwrap_or_else(|_| "debug".to_owned()))
        .unwrap();
    let writer = output.map(|f| Mutex::new(File::create(f).unwrap()));
    // we don't mind set it multiple times.
    let drain = CaseTraceLogger { f: writer };
    let drain = slog_async::Async::new(drain).build().fuse();
    let logger = slog::Logger::root_typed(drain, slog_o!());
    let _ = logger::init_log_for_tikv_only(logger, level);
}

/// Set up ci test fail case log.
pub fn ci_setup() {
    if env::var("CI").is_ok() && env::var("LOG_FILE").is_ok() {
        init_log();
    }
    if env::var("PANIC_ABORT").is_ok() {
        // Panics as aborts, it's helpful for debugging,
        // but also stops tests immediately.
        util::panic_hook::set_exit_hook(true);
    }
}

pub fn new_security_cfg() -> SecurityConfig {
    let p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    SecurityConfig {
        ca_path: format!("{}", p.join("tests/data/ca.crt").display()),
        cert_path: format!("{}", p.join("tests/data/server.crt").display()),
        key_path: format!("{}", p.join("tests/data/server.pem").display()),
        override_ssl_target: "example.com".to_owned(),
    }
}
<|endoftext|>


<commit_before>mod macros;

const NUM_BYTES: usize = 4096;
const NUM_REGISTERS: usize = 16;
const STACK_SIZE: usize = 48;

const VALUE_MASK: u16 = 0b0000_0000_1111_1111;
const REGISTER_ADDRESS_MASK: u16 = 0b0000_1111_0000_0000;

#[allow(dead_code)]
pub struct System {
    memory: [u8; NUM_BYTES],
    registers: [u8; NUM_REGISTERS],
    pc: u16,
    index: u16,
    stack: [u8; STACK_SIZE],
    sp: u8
}

#[allow(dead_code)]
impl System{
    pub fn new() -> Self {
        System {
            memory: [0; NUM_BYTES],
            registers: [0; NUM_REGISTERS],
            pc: 0,
            index: 0,
            stack: [0; STACK_SIZE],
            sp: 0
        }
    }

    /** Index into system memory at address and return word located there. */
    pub fn read_word(&self, address: usize) -> u16 {
        let left = self.memory[address] as u16;
        let right = self.memory[address + 1] as u16;
        (left << 8) | right
    }

    /** Execute the instruction. */
    pub fn execute(&mut self, opcode: u16) {
        match opcode {
            0x6000...0x7000 => {
                self.registers[((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize] =
                    (opcode & VALUE_MASK) as u8;
            },
            _ => {
                eprintln!("Unrecognized instruction!");
            }
        }
    }
}

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

    /** Load some test data into the system memory for the purposes of testing. */
    fn load_test_data(system: &mut System) {
        system.memory[0] = 0xAF;
        system.memory[1] = 0x7F;
        system.memory[NUM_BYTES / 2] = 0x77;
        system.memory[NUM_BYTES / 2 + 1] = 0x88;
        system.memory[NUM_BYTES - 2] = 0x3A;
        system.memory[NUM_BYTES - 1] = 0x01;
    }

    /** Read a word (two bytes) from the system memory. */
    #[test]
    fn read_word() {
        let mut system = System::new();
        load_test_data(&mut system);
        assert_eq!(0xAF7F, system.read_word(0));
        assert_eq!(0x7788, system.read_word(NUM_BYTES / 2));
        assert_eq!(0x3A01, system.read_word(NUM_BYTES - 2));
    }

    /** The opcode 0x6XNN should store the constant NN into register VX. */
    #[test]
    fn load_constant() {
        let mut system = System::new();
        system.execute(0x6015);
        assert_eq!(0x15, system.registers[0]);
        system.execute(0x6120);
        assert_eq!(0x20, system.registers[1]);
        system.execute(0x6225);
        assert_eq!(0x25, system.registers[2]);
        system.execute(0x6330);
        assert_eq!(0x30, system.registers[3]);
        system.execute(0x6435);
        assert_eq!(0x35, system.registers[4]);
        system.execute(0x6540);
        assert_eq!(0x40, system.registers[5]);
        system.execute(0x6645);
        assert_eq!(0x45, system.registers[6]);
        system.execute(0x6750);
        assert_eq!(0x50, system.registers[7]);
        system.execute(0x6855);
        assert_eq!(0x55, system.registers[8]);
        system.execute(0x6960);
        assert_eq!(0x60, system.registers[9]);
        system.execute(0x6A65);
        assert_eq!(0x65, system.registers[0xA]);
        system.execute(0x6B70);
        assert_eq!(0x70, system.registers[0xB]);
        system.execute(0x6C75);
        assert_eq!(0x75, system.registers[0xC]);
        system.execute(0x6D80);
        assert_eq!(0x80, system.registers[0xD]);
        system.execute(0x6E85);
        assert_eq!(0x85, system.registers[0xE]);
        system.execute(0x6F90);
        assert_eq!(0x90, system.registers[0xF]);
    }
}
<commit_msg>opcode 0x7XNN implemented<commit_after>mod macros;

const NUM_BYTES: usize = 4096;
const NUM_REGISTERS: usize = 16;
const STACK_SIZE: usize = 48;

const VALUE_MASK: u16 = 0b0000_0000_1111_1111;
const REGISTER_ADDRESS_MASK: u16 = 0b0000_1111_0000_0000;

#[allow(dead_code)]
pub struct System {
    memory: [u8; NUM_BYTES],
    registers: [u8; NUM_REGISTERS],
    pc: u16,
    index: u16,
    stack: [u8; STACK_SIZE],
    sp: u8
}

#[allow(dead_code)]
impl System{
    pub fn new() -> Self {
        System {
            memory: [0; NUM_BYTES],
            registers: [0; NUM_REGISTERS],
            pc: 0,
            index: 0,
            stack: [0; STACK_SIZE],
            sp: 0
        }
    }

    /** Index into system memory at address and return word located there. */
    pub fn read_word(&self, address: usize) -> u16 {
        let left = self.memory[address] as u16;
        let right = self.memory[address + 1] as u16;
        (left << 8) | right
    }

    /** Execute the instruction. */
    pub fn execute(&mut self, opcode: u16) {
        match opcode {
            0x6000...0x7000 => {    // 0x6XNN : VX = NN
                let register = ((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize;
                let value = (opcode & VALUE_MASK) as u8;
                self.registers[register] = value;
            },
            0x7000...0x8000 => {    // 0x7XNN : VX = VX + NN
                let register = ((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize;
                let value = (opcode & VALUE_MASK) as u8;
                self.registers[register] = self.registers[register].wrapping_add(value);
            },
            _ => {
                eprintln!("Unrecognized instruction!");
            }
        }
    }
}

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

    /** Load some test data into the system memory for the purposes of testing. */
    fn load_test_data(system: &mut System) {
        system.memory[0] = 0xAF;
        system.memory[1] = 0x7F;
        system.memory[NUM_BYTES / 2] = 0x77;
        system.memory[NUM_BYTES / 2 + 1] = 0x88;
        system.memory[NUM_BYTES - 2] = 0x3A;
        system.memory[NUM_BYTES - 1] = 0x01;
    }

    /** Read a word (two bytes) from the system memory. */
    #[test]
    fn read_word() {
        let mut system = System::new();
        load_test_data(&mut system);
        assert_eq!(0xAF7F, system.read_word(0));
        assert_eq!(0x7788, system.read_word(NUM_BYTES / 2));
        assert_eq!(0x3A01, system.read_word(NUM_BYTES - 2));
    }

    /** The opcode 0x6XNN should store the constant NN into register VX. */
    #[test]
    fn load_constant() {
        let mut system = System::new();
        system.execute(0x6015);
        assert_eq!(0x15, system.registers[0]);
        system.execute(0x6120);
        assert_eq!(0x20, system.registers[1]);
        system.execute(0x6225);
        assert_eq!(0x25, system.registers[2]);
        system.execute(0x6330);
        assert_eq!(0x30, system.registers[3]);
        system.execute(0x6435);
        assert_eq!(0x35, system.registers[4]);
        system.execute(0x6540);
        assert_eq!(0x40, system.registers[5]);
        system.execute(0x6645);
        assert_eq!(0x45, system.registers[6]);
        system.execute(0x6750);
        assert_eq!(0x50, system.registers[7]);
        system.execute(0x6855);
        assert_eq!(0x55, system.registers[8]);
        system.execute(0x6960);
        assert_eq!(0x60, system.registers[9]);
        system.execute(0x6A65);
        assert_eq!(0x65, system.registers[0xA]);
        system.execute(0x6B70);
        assert_eq!(0x70, system.registers[0xB]);
        system.execute(0x6C75);
        assert_eq!(0x75, system.registers[0xC]);
        system.execute(0x6D80);
        assert_eq!(0x80, system.registers[0xD]);
        system.execute(0x6E85);
        assert_eq!(0x85, system.registers[0xE]);
        system.execute(0x6F90);
        assert_eq!(0x90, system.registers[0xF]);
    }

    /** The opcode 0x7XNN should add the constant NN into register VX. */
    #[test]
    fn add_constant() {
        let mut system = System::new();
        system.execute(0x6015);
        system.execute(0x7015);
        assert_eq!(0x2A, system.registers[0]);
        system.execute(0x6A42);
        system.execute(0x7A42);
        assert_eq!(0x84, system.registers[0xA]);
        system.execute(0x6EFF);
        system.execute(0x7E01);
        // registers should overlow appropriately
        assert_eq!(0x00, system.registers[0xE]);
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

use anyhow::Result;
use async_std::task;
use portpicker::pick_unused_port;
use serde_cbor::de::from_slice;
use serde_cbor::ser::to_vec;
use tempdir::TempDir;

use pueue_lib::network::certificate::create_certificates;
use pueue_lib::network::message::*;
use pueue_lib::network::protocol::*;
use pueue_lib::settings::Shared;

#[cfg(not(target_os = "windows"))]
#[async_std::test]
/// This tests whether we can create a listener and client, that communicate via unix sockets.
/// This includes the handshake between both parties.
async fn test_tls_socket() -> Result<()> {
    // Create a temporary directory used for testing.
    let temp_dir = TempDir::new("pueue_lib")?;
    let temp_dir_path = temp_dir.path().to_path_buf();

    let shared_settings = Shared {
        pueue_directory: temp_dir_path.clone(),
        use_unix_socket: false,
        unix_socket_path: PathBuf::new(),
        host: "localhost".to_string(),
        port: pick_unused_port()
            .expect("There should be a free port")
            .to_string(),
        daemon_cert: temp_dir_path.clone().join("certs").join("daemon.cert"),
        daemon_key: temp_dir_path.clone().join("certs").join("daemon.key"),
        shared_secret_path: temp_dir.path().to_path_buf().join("secret"),
    };

    // Create new stub tls certificates/keys in our temp directory
    create_certificates(&shared_settings)?;

    let listener = get_listener(&shared_settings).await?;
    let message = create_success_message("This is a test");
    let original_bytes = to_vec(&message).expect("Failed to serialize message.");

    // Spawn a sub thread that:
    // 1. Accepts a new connection
    // 2. Reads a message
    // 3. Sends the same message back
    task::spawn(async move {
        let mut stream = listener.accept().await.unwrap();
        let message_bytes = receive_bytes(&mut stream).await.unwrap();

        let message: Message = from_slice(&message_bytes).unwrap();

        send_message(message, &mut stream).await.unwrap();
    });

    let mut client = get_client_stream(&shared_settings).await?;

    // Create a client that sends a message and instantly receives it
    send_message(message, &mut client).await?;
    let response_bytes = receive_bytes(&mut client).await?;
    let _message: Message = from_slice(&response_bytes)?;

    assert_eq!(response_bytes, original_bytes);

    Ok(())
}
<commit_msg>Run tls socket tests on all platforms<commit_after>use std::path::PathBuf;

use anyhow::Result;
use async_std::task;
use portpicker::pick_unused_port;
use serde_cbor::de::from_slice;
use serde_cbor::ser::to_vec;
use tempdir::TempDir;

use pueue_lib::network::certificate::create_certificates;
use pueue_lib::network::message::*;
use pueue_lib::network::protocol::*;
use pueue_lib::settings::Shared;

#[async_std::test]
/// This tests whether we can create a listener and client, that communicate via unix sockets.
/// This includes the handshake between both parties.
async fn test_tls_socket() -> Result<()> {
    // Create a temporary directory used for testing.
    let temp_dir = TempDir::new("pueue_lib")?;
    let temp_dir_path = temp_dir.path().to_path_buf();

    let shared_settings = Shared {
        pueue_directory: temp_dir_path.clone(),
        use_unix_socket: false,
        unix_socket_path: PathBuf::new(),
        host: "localhost".to_string(),
        port: pick_unused_port()
            .expect("There should be a free port")
            .to_string(),
        daemon_cert: temp_dir_path.clone().join("certs").join("daemon.cert"),
        daemon_key: temp_dir_path.clone().join("certs").join("daemon.key"),
        shared_secret_path: temp_dir.path().to_path_buf().join("secret"),
    };

    // Create new stub tls certificates/keys in our temp directory
    create_certificates(&shared_settings)?;

    let listener = get_listener(&shared_settings).await?;
    let message = create_success_message("This is a test");
    let original_bytes = to_vec(&message).expect("Failed to serialize message.");

    // Spawn a sub thread that:
    // 1. Accepts a new connection
    // 2. Reads a message
    // 3. Sends the same message back
    task::spawn(async move {
        let mut stream = listener.accept().await.unwrap();
        let message_bytes = receive_bytes(&mut stream).await.unwrap();

        let message: Message = from_slice(&message_bytes).unwrap();

        send_message(message, &mut stream).await.unwrap();
    });

    let mut client = get_client_stream(&shared_settings).await?;

    // Create a client that sends a message and instantly receives it
    send_message(message, &mut client).await?;
    let response_bytes = receive_bytes(&mut client).await?;
    let _message: Message = from_slice(&response_bytes)?;

    assert_eq!(response_bytes, original_bytes);

    Ok(())
}
<|endoftext|>


<commit_before>//! Execute tasks on the current thread
//!
//! This module implements an executor that keeps futures on the same thread
//! that they are submitted on. This allows it to execute futures that are
//! not `Send`.
//!
//! Before being able to spawn futures with this module, an executor
//! context must be setup by calling [`run`]. From within that context [`spawn`]
//! may be called with the future to run in the background.
//!
//! ```
//! # extern crate tokio;
//! # extern crate futures;
//! # use tokio::executor::current_thread;
//! use futures::future::lazy;
//!
//! // Calling execute here results in a panic
//! // current_thread::spawn(my_future);
//!
//! # pub fn main() {
//! current_thread::run(|_| {
//!     // The execution context is setup, futures may be executed.
//!     current_thread::spawn(lazy(|| {
//!         println!("called from the current thread executor");
//!         Ok(())
//!     }));
//! });
//! # }
//! ```
//!
//! # Execution model
//!
//! When an execution context is setup with `run` the current thread will block
//! and all the futures managed by the executor are driven to completion.
//! Whenever a future receives a notification, it is pushed to the end of a
//! scheduled list. The executor will drain this list, advancing the state of
//! each future.
//!
//! All futures managed by this module will remain on the current thread,
//! as such, this module is able to safely execute futures that are not `Send`.
//!
//! Once a future is complete, it is dropped. Once all futures are completed,
//! [`run`] will unblock and return.
//!
//! This module makes a best effort to fairly schedule futures that it manages.
//!
//! [`spawn`]: fn.spawn.html
//! [`run`]: fn.run.html

use super::{scheduler};
use super::sleep::{self, Sleep, Wakeup};

use futures::Async;
use futures::executor::{self, Spawn};
use futures::future::{Future, Executor, ExecuteError, ExecuteErrorKind};

use std::{fmt, thread};
use std::cell::Cell;
use std::rc::Rc;

/// Executes futures on the current thread.
///
/// All futures executed using this executor will be executed on the current
/// thread. As such, `run` will wait for these futures to complete before
/// returning.
///
/// For more details, see the [module level](index.html) documentation.
#[derive(Debug, Clone)]
pub struct TaskExecutor {
    // Prevent the handle from moving across threads.
    _p: ::std::marker::PhantomData<Rc<()>>,
}

/// A context yielded to the closure provided to `run`.
///
/// This context is mostly a future-proofing of the library to add future
/// contextual information into it. Currently it only contains the `Enter`
/// instance used to reserve the current thread for blocking on futures.
#[derive(Debug)]
pub struct Context<'a> {
    cancel: &'a Cell<bool>,
}

/// Implements the "blocking" logic for the current thread executor. A
/// `TaskRunner` will be created during `run` and will sit on the stack until
/// execution is complete.
#[derive(Debug)]
struct TaskRunner<T> {
    /// Executes futures.
    scheduler: Scheduler<T>,
}

struct CurrentRunner {
    /// When set to true, the executor should return immediately, even if there
    /// still futures to run.
    cancel: Cell<bool>,

    /// Number of futures currently being executed by the runner.
    num_futures: Cell<usize>,

    /// Raw pointer to the current scheduler pusher.
    ///
    /// The raw pointer is required in order to store it in a thread-local slot.
    schedule: Cell<Option<*mut Schedule>>,
}

type Scheduler<T> = scheduler::Scheduler<Task, T>;
type Schedule = scheduler::Schedule<Task>;

struct Task(Spawn<Box<Future<Item = (), Error = ()>>>);

/// Current thread's task runner. This is set in `TaskRunner::with`
thread_local!(static CURRENT: CurrentRunner = CurrentRunner {
    cancel: Cell::new(false),
    num_futures: Cell::new(0),
    schedule: Cell::new(None),
});

/// Calls the given closure, then block until all futures submitted for
/// execution complete.
///
/// In more detail, this function will block until:
/// - All executing futures are complete, or
/// - `cancel_all_spawned` is invoked.
pub fn run<F, R>(f: F) -> R
where F: FnOnce(&mut Context) -> R
{
    sleep::BlockThread::with_current(|mut sleep| {
        TaskRunner::enter(&mut sleep, f)
    })
}

/// Calls the given closure with a custom sleep strategy.
///
/// This function is the same as `run` except that it allows customizing the
/// sleep strategy.
pub fn run_with_sleep<S, F, R>(sleep: &mut S, f: F) -> R
where F: FnOnce(&mut Context) -> R,
      S: Sleep,
{
    TaskRunner::enter(sleep, f)
}

/// Executes a future on the current thread.
///
/// The provided future must complete or be canceled before `run` will return.
///
/// # Panics
///
/// This function can only be invoked from the context of a `run` call; any
/// other use will result in a panic.
pub fn spawn<F>(future: F)
where F: Future<Item = (), Error = ()> + 'static
{
    execute(future).unwrap_or_else(|_| {
        panic!("cannot call `execute` unless the thread is already \
                in the context of a call to `run`")
    })
}

/// Returns an executor that executes futures on the current thread.
///
/// The user of `TaskExecutor` must ensure that when a future is submitted,
/// that it is done within the context of a call to `run`.
///
/// For more details, see the [module level](index.html) documentation.
pub fn task_executor() -> TaskExecutor {
    TaskExecutor {
        _p: ::std::marker::PhantomData,
    }
}

impl<F> Executor<F> for TaskExecutor
where F: Future<Item = (), Error = ()> + 'static
{
    fn execute(&self, future: F) -> Result<(), ExecuteError<F>> {
        execute(future)
    }
}

impl<'a> Context<'a> {
    /// Cancels *all* executing futures.
    pub fn cancel_all_spawned(&self) {
        self.cancel.set(true);
    }
}

/// Submits a future to the current executor. This is done by
/// checking the thread-local variable tracking the current executor.
///
/// If this function is not called in context of an executor, i.e. outside of
/// `run`, then `Err` is returned.
///
/// This function does not panic.
fn execute<F>(future: F) -> Result<(), ExecuteError<F>>
where F: Future<Item = (), Error = ()> + 'static,
{
    CURRENT.with(|current| {
        match current.schedule.get() {
            Some(schedule) => {
                let spawned = Task::new(future);

                let num_futures = current.num_futures.get();
                current.num_futures.set(num_futures + 1);

                unsafe { (*schedule).schedule(spawned); }

                Ok(())
            }
            None => {
                Err(ExecuteError::new(ExecuteErrorKind::Shutdown, future))
            }
        }
    })
}

impl<T> TaskRunner<T>
where T: Wakeup,
{
    /// Return a new `TaskRunner`
    fn new(wakeup: T) -> TaskRunner<T> {
        let scheduler = scheduler::Scheduler::new(wakeup);

        TaskRunner {
            scheduler: scheduler,
        }
    }

    /// Enter a new `TaskRunner` context
    ///
    /// This function handles advancing the scheduler state and blocking while
    /// listening for notified futures.
    ///
    /// First, a new task runner is created backed by the current
    /// `sleep::BlockThread` handle. Passing `sleep::BlockThread` into the
    /// scheduler is how scheduled futures unblock the thread, signalling that
    /// there is more work to do.
    ///
    /// Before any future is polled, the scheduler must be set to a thread-local
    /// variable so that `execute` is able to submit new futures to the current
    /// executor. Because `Scheduler::schedule` requires `&mut self`, this
    /// introduces a mutability hazard. This hazard is minimized with some
    /// indirection. See `set_schedule` for more details.
    ///
    /// Once all context is setup, the init closure is invoked. This is the
    /// "boostrapping" process that executes the initial futures into the
    /// scheduler. After this, the function loops and advances the scheduler
    /// state until all futures complete. When no scheduled futures are ready to
    /// be advanced, the thread is blocked using `S: Sleep`.
    fn enter<S, F, R>(sleep: &mut S, f: F) -> R
    where F: FnOnce(&mut Context) -> R,
          S: Sleep<Wakeup = T>,
    {
        let mut runner = TaskRunner::new(sleep.wakeup());

        CURRENT.with(|current| {
            // Make sure that another task runner is not set.
            //
            // This should not be ever possible due to how `set_schedule`
            // is setup, but better safe than sorry!
            assert!(current.schedule.get().is_none());

            // Enter an execution scope
            let mut ctx = Context {
                cancel: &current.cancel,
            };

            // Set the scheduler to the TLS and perform setup work,
            // returning a future to execute.
            //
            // This could possibly suubmit other futures for execution.
            let ret = current.set_schedule(&mut runner.scheduler as &mut Schedule, || {
                f(&mut ctx)
            });

            // Execute the runner.
            //
            // This function will not return until either
            //
            // a) All futures have completed execution
            // b) `cancel_all_spawned` is called, forcing the executor to
            // return.
            runner.run(sleep, current);

            // Not technically required, but this makes the fact that `ctx`
            // needs to live until this point explicit.
            drop(ctx);

            ret
        })
    }

    fn run<S>(&mut self, sleep: &mut S, current: &CurrentRunner)
    where S: Sleep<Wakeup = T>,
    {
        use super::scheduler::Tick;

        while current.is_running() {
            // Try to advance the scheduler state
            let res = self.scheduler.tick(|scheduler, spawned, notify| {
                // `scheduler` is a `&mut Scheduler` reference returned back
                // from the scheduler to us, but only within the context of this
                // closure.
                //
                // This lets us push new futures into the scheduler. It also
                // lets us pass the scheduler mutable reference into
                // `set_schedule`, which sets the thread-local variable that
                // `spawn` uses for submitting new futures to the
                // "current" executor.
                //
                // See `set_schedule` documentation for more details on how we
                // guard against mutable pointer aliasing.
                current.set_schedule(scheduler as &mut Schedule, || {
                    match spawned.0.poll_future_notify(notify, 0) {
                        Ok(Async::Ready(_)) | Err(_) => {
                            Async::Ready(())
                        }
                        Ok(Async::NotReady) => Async::NotReady,
                    }
                })
            });

            // Process the result of ticking the scheduler
            match res {
                // A future completed. `is_daemon` is true when the future was
                // submitted as a daemon future.
                Tick::Data(_) => {
                    let num_futures = current.num_futures.get();
                    debug_assert!(num_futures > 0);
                    current.num_futures.set(num_futures - 1);
                },
                Tick::Empty => {
                    // The scheduler did not have any work to process.
                    //
                    // At this point, the scheduler is currently running given
                    // that the `while` condition was true and no user code has
                    // been executed.

                    debug_assert!(current.is_running());

                    // Block the current thread until a future managed by the scheduler
                    // receives a readiness notification.
                    sleep.sleep();
                }
                Tick::Inconsistent => {
                    // Yield the thread and loop
                    thread::yield_now();
                }
            }
        }
    }
}

impl CurrentRunner {
    /// Set the provided schedule handle to the TLS slot for the duration of the
    /// closure.
    ///
    /// `spawn` will access the CURRENT thread-local variable in
    /// order to push a future into the scheduler. This requires a `&mut`
    /// reference, introducing mutability hazards.
    ///
    /// Rust requires that `&mut` references are not aliases, i.e. there are
    /// never two "live" mutable references to the same piece of data. In order
    /// to store a `&mut` reference in a thread-local variable, we must ensure
    /// that one can not access the scheduler anywhere else.
    ///
    /// To do this, we only allow access to the thread local variable from
    /// within the closure passed to `set_schedule`. This function also takes a
    /// &mut reference to the scheduler, which is essentially holding a "lock"
    /// on that reference, preventing any other location in the code from
    /// also getting that &mut reference.
    ///
    /// When `set_schedule` returns, the thread-local variable containing the
    /// mut reference is set to null. This is done even if the closure panics.
    ///
    /// This reduces the odds of introducing pointer aliasing.
    fn set_schedule<F, R>(&self, schedule: &mut Schedule, f: F) -> R
    where F: FnOnce() -> R
    {
        // Ensure that the runner is removed from the thread-local context
        // when leaving the scope. This handles cases that involve panicking.
        struct Reset<'a>(&'a CurrentRunner);

        impl<'a> Drop for Reset<'a> {
            fn drop(&mut self) {
                self.0.schedule.set(None);
            }
        }

        let _reset = Reset(self);

        self.schedule.set(Some(schedule as *mut Schedule));

        f()
    }

    fn is_running(&self) -> bool {
        self.num_futures.get() > 0 && !self.cancel.get()
    }
}

impl Task {
    fn new<T: Future<Item = (), Error = ()> + 'static>(f: T) -> Self {
        Task(executor::spawn(Box::new(f)))
    }
}

impl fmt::Debug for Task {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Task")
            .finish()
    }
}
<commit_msg>Remove fn that was never intended to be pub (#130)<commit_after>//! Execute tasks on the current thread
//!
//! This module implements an executor that keeps futures on the same thread
//! that they are submitted on. This allows it to execute futures that are
//! not `Send`.
//!
//! Before being able to spawn futures with this module, an executor
//! context must be setup by calling [`run`]. From within that context [`spawn`]
//! may be called with the future to run in the background.
//!
//! ```
//! # extern crate tokio;
//! # extern crate futures;
//! # use tokio::executor::current_thread;
//! use futures::future::lazy;
//!
//! // Calling execute here results in a panic
//! // current_thread::spawn(my_future);
//!
//! # pub fn main() {
//! current_thread::run(|_| {
//!     // The execution context is setup, futures may be executed.
//!     current_thread::spawn(lazy(|| {
//!         println!("called from the current thread executor");
//!         Ok(())
//!     }));
//! });
//! # }
//! ```
//!
//! # Execution model
//!
//! When an execution context is setup with `run` the current thread will block
//! and all the futures managed by the executor are driven to completion.
//! Whenever a future receives a notification, it is pushed to the end of a
//! scheduled list. The executor will drain this list, advancing the state of
//! each future.
//!
//! All futures managed by this module will remain on the current thread,
//! as such, this module is able to safely execute futures that are not `Send`.
//!
//! Once a future is complete, it is dropped. Once all futures are completed,
//! [`run`] will unblock and return.
//!
//! This module makes a best effort to fairly schedule futures that it manages.
//!
//! [`spawn`]: fn.spawn.html
//! [`run`]: fn.run.html

use super::{scheduler};
use super::sleep::{self, Sleep, Wakeup};

use futures::Async;
use futures::executor::{self, Spawn};
use futures::future::{Future, Executor, ExecuteError, ExecuteErrorKind};

use std::{fmt, thread};
use std::cell::Cell;
use std::rc::Rc;

/// Executes futures on the current thread.
///
/// All futures executed using this executor will be executed on the current
/// thread. As such, `run` will wait for these futures to complete before
/// returning.
///
/// For more details, see the [module level](index.html) documentation.
#[derive(Debug, Clone)]
pub struct TaskExecutor {
    // Prevent the handle from moving across threads.
    _p: ::std::marker::PhantomData<Rc<()>>,
}

/// A context yielded to the closure provided to `run`.
///
/// This context is mostly a future-proofing of the library to add future
/// contextual information into it. Currently it only contains the `Enter`
/// instance used to reserve the current thread for blocking on futures.
#[derive(Debug)]
pub struct Context<'a> {
    cancel: &'a Cell<bool>,
}

/// Implements the "blocking" logic for the current thread executor. A
/// `TaskRunner` will be created during `run` and will sit on the stack until
/// execution is complete.
#[derive(Debug)]
struct TaskRunner<T> {
    /// Executes futures.
    scheduler: Scheduler<T>,
}

struct CurrentRunner {
    /// When set to true, the executor should return immediately, even if there
    /// still futures to run.
    cancel: Cell<bool>,

    /// Number of futures currently being executed by the runner.
    num_futures: Cell<usize>,

    /// Raw pointer to the current scheduler pusher.
    ///
    /// The raw pointer is required in order to store it in a thread-local slot.
    schedule: Cell<Option<*mut Schedule>>,
}

type Scheduler<T> = scheduler::Scheduler<Task, T>;
type Schedule = scheduler::Schedule<Task>;

struct Task(Spawn<Box<Future<Item = (), Error = ()>>>);

/// Current thread's task runner. This is set in `TaskRunner::with`
thread_local!(static CURRENT: CurrentRunner = CurrentRunner {
    cancel: Cell::new(false),
    num_futures: Cell::new(0),
    schedule: Cell::new(None),
});

/// Calls the given closure, then block until all futures submitted for
/// execution complete.
///
/// In more detail, this function will block until:
/// - All executing futures are complete, or
/// - `cancel_all_spawned` is invoked.
pub fn run<F, R>(f: F) -> R
where F: FnOnce(&mut Context) -> R
{
    sleep::BlockThread::with_current(|mut sleep| {
        TaskRunner::enter(&mut sleep, f)
    })
}

#[deprecated(since = "0.1.1", note = "this was never supposed to be public")]
#[doc(hidden)]
pub fn run_with_sleep<S, F, R>(_: &mut S, _: F) -> R
where F: FnOnce(&mut Context) -> R,
      S: Sleep,
{
    // This could never be called publically because `Sleep` is not public.
    unimplemented!();
}

/// Executes a future on the current thread.
///
/// The provided future must complete or be canceled before `run` will return.
///
/// # Panics
///
/// This function can only be invoked from the context of a `run` call; any
/// other use will result in a panic.
pub fn spawn<F>(future: F)
where F: Future<Item = (), Error = ()> + 'static
{
    execute(future).unwrap_or_else(|_| {
        panic!("cannot call `execute` unless the thread is already \
                in the context of a call to `run`")
    })
}

/// Returns an executor that executes futures on the current thread.
///
/// The user of `TaskExecutor` must ensure that when a future is submitted,
/// that it is done within the context of a call to `run`.
///
/// For more details, see the [module level](index.html) documentation.
pub fn task_executor() -> TaskExecutor {
    TaskExecutor {
        _p: ::std::marker::PhantomData,
    }
}

impl<F> Executor<F> for TaskExecutor
where F: Future<Item = (), Error = ()> + 'static
{
    fn execute(&self, future: F) -> Result<(), ExecuteError<F>> {
        execute(future)
    }
}

impl<'a> Context<'a> {
    /// Cancels *all* executing futures.
    pub fn cancel_all_spawned(&self) {
        self.cancel.set(true);
    }
}

/// Submits a future to the current executor. This is done by
/// checking the thread-local variable tracking the current executor.
///
/// If this function is not called in context of an executor, i.e. outside of
/// `run`, then `Err` is returned.
///
/// This function does not panic.
fn execute<F>(future: F) -> Result<(), ExecuteError<F>>
where F: Future<Item = (), Error = ()> + 'static,
{
    CURRENT.with(|current| {
        match current.schedule.get() {
            Some(schedule) => {
                let spawned = Task::new(future);

                let num_futures = current.num_futures.get();
                current.num_futures.set(num_futures + 1);

                unsafe { (*schedule).schedule(spawned); }

                Ok(())
            }
            None => {
                Err(ExecuteError::new(ExecuteErrorKind::Shutdown, future))
            }
        }
    })
}

impl<T> TaskRunner<T>
where T: Wakeup,
{
    /// Return a new `TaskRunner`
    fn new(wakeup: T) -> TaskRunner<T> {
        let scheduler = scheduler::Scheduler::new(wakeup);

        TaskRunner {
            scheduler: scheduler,
        }
    }

    /// Enter a new `TaskRunner` context
    ///
    /// This function handles advancing the scheduler state and blocking while
    /// listening for notified futures.
    ///
    /// First, a new task runner is created backed by the current
    /// `sleep::BlockThread` handle. Passing `sleep::BlockThread` into the
    /// scheduler is how scheduled futures unblock the thread, signalling that
    /// there is more work to do.
    ///
    /// Before any future is polled, the scheduler must be set to a thread-local
    /// variable so that `execute` is able to submit new futures to the current
    /// executor. Because `Scheduler::schedule` requires `&mut self`, this
    /// introduces a mutability hazard. This hazard is minimized with some
    /// indirection. See `set_schedule` for more details.
    ///
    /// Once all context is setup, the init closure is invoked. This is the
    /// "boostrapping" process that executes the initial futures into the
    /// scheduler. After this, the function loops and advances the scheduler
    /// state until all futures complete. When no scheduled futures are ready to
    /// be advanced, the thread is blocked using `S: Sleep`.
    fn enter<S, F, R>(sleep: &mut S, f: F) -> R
    where F: FnOnce(&mut Context) -> R,
          S: Sleep<Wakeup = T>,
    {
        let mut runner = TaskRunner::new(sleep.wakeup());

        CURRENT.with(|current| {
            // Make sure that another task runner is not set.
            //
            // This should not be ever possible due to how `set_schedule`
            // is setup, but better safe than sorry!
            assert!(current.schedule.get().is_none());

            // Enter an execution scope
            let mut ctx = Context {
                cancel: &current.cancel,
            };

            // Set the scheduler to the TLS and perform setup work,
            // returning a future to execute.
            //
            // This could possibly suubmit other futures for execution.
            let ret = current.set_schedule(&mut runner.scheduler as &mut Schedule, || {
                f(&mut ctx)
            });

            // Execute the runner.
            //
            // This function will not return until either
            //
            // a) All futures have completed execution
            // b) `cancel_all_spawned` is called, forcing the executor to
            // return.
            runner.run(sleep, current);

            // Not technically required, but this makes the fact that `ctx`
            // needs to live until this point explicit.
            drop(ctx);

            ret
        })
    }

    fn run<S>(&mut self, sleep: &mut S, current: &CurrentRunner)
    where S: Sleep<Wakeup = T>,
    {
        use super::scheduler::Tick;

        while current.is_running() {
            // Try to advance the scheduler state
            let res = self.scheduler.tick(|scheduler, spawned, notify| {
                // `scheduler` is a `&mut Scheduler` reference returned back
                // from the scheduler to us, but only within the context of this
                // closure.
                //
                // This lets us push new futures into the scheduler. It also
                // lets us pass the scheduler mutable reference into
                // `set_schedule`, which sets the thread-local variable that
                // `spawn` uses for submitting new futures to the
                // "current" executor.
                //
                // See `set_schedule` documentation for more details on how we
                // guard against mutable pointer aliasing.
                current.set_schedule(scheduler as &mut Schedule, || {
                    match spawned.0.poll_future_notify(notify, 0) {
                        Ok(Async::Ready(_)) | Err(_) => {
                            Async::Ready(())
                        }
                        Ok(Async::NotReady) => Async::NotReady,
                    }
                })
            });

            // Process the result of ticking the scheduler
            match res {
                // A future completed. `is_daemon` is true when the future was
                // submitted as a daemon future.
                Tick::Data(_) => {
                    let num_futures = current.num_futures.get();
                    debug_assert!(num_futures > 0);
                    current.num_futures.set(num_futures - 1);
                },
                Tick::Empty => {
                    // The scheduler did not have any work to process.
                    //
                    // At this point, the scheduler is currently running given
                    // that the `while` condition was true and no user code has
                    // been executed.

                    debug_assert!(current.is_running());

                    // Block the current thread until a future managed by the scheduler
                    // receives a readiness notification.
                    sleep.sleep();
                }
                Tick::Inconsistent => {
                    // Yield the thread and loop
                    thread::yield_now();
                }
            }
        }
    }
}

impl CurrentRunner {
    /// Set the provided schedule handle to the TLS slot for the duration of the
    /// closure.
    ///
    /// `spawn` will access the CURRENT thread-local variable in
    /// order to push a future into the scheduler. This requires a `&mut`
    /// reference, introducing mutability hazards.
    ///
    /// Rust requires that `&mut` references are not aliases, i.e. there are
    /// never two "live" mutable references to the same piece of data. In order
    /// to store a `&mut` reference in a thread-local variable, we must ensure
    /// that one can not access the scheduler anywhere else.
    ///
    /// To do this, we only allow access to the thread local variable from
    /// within the closure passed to `set_schedule`. This function also takes a
    /// &mut reference to the scheduler, which is essentially holding a "lock"
    /// on that reference, preventing any other location in the code from
    /// also getting that &mut reference.
    ///
    /// When `set_schedule` returns, the thread-local variable containing the
    /// mut reference is set to null. This is done even if the closure panics.
    ///
    /// This reduces the odds of introducing pointer aliasing.
    fn set_schedule<F, R>(&self, schedule: &mut Schedule, f: F) -> R
    where F: FnOnce() -> R
    {
        // Ensure that the runner is removed from the thread-local context
        // when leaving the scope. This handles cases that involve panicking.
        struct Reset<'a>(&'a CurrentRunner);

        impl<'a> Drop for Reset<'a> {
            fn drop(&mut self) {
                self.0.schedule.set(None);
            }
        }

        let _reset = Reset(self);

        self.schedule.set(Some(schedule as *mut Schedule));

        f()
    }

    fn is_running(&self) -> bool {
        self.num_futures.get() > 0 && !self.cancel.get()
    }
}

impl Task {
    fn new<T: Future<Item = (), Error = ()> + 'static>(f: T) -> Self {
        Task(executor::spawn(Box::new(f)))
    }
}

impl fmt::Debug for Task {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Task")
            .finish()
    }
}
<|endoftext|>


<commit_before><commit_msg>Add more context in error messages<commit_after><|endoftext|>


<commit_before><commit_msg>Documentation for evaluate_expression<commit_after><|endoftext|>


<commit_before>#![allow(unused_imports)]
use rustc_serialize::json;

#[test]
fn reply_keyboard_markup() {
    use ReplyKeyboardMarkup as RKM;

    // Test default values
    assert_eq!(RKM::default(), RKM {
        keyboard: Vec::new(),
        resize_keyboard: None,
        one_time_keyboard: None,
        selective: None,
    });

    // Test encoding
    let x = RKM::default();
    assert_eq!(json::encode(&x).unwrap(), r#"{"keyboard":[]}"#.to_string());

    let x = RKM { resize_keyboard: Some(true), ..Default::default() };
    assert_eq!(json::encode(&x).unwrap(),
        r#"{"keyboard":[],"resize_keyboard":true}"#.to_string());

    let x = RKM {
        keyboard: vec![vec!["ABC".into()], vec!["X".into(), "Y".into()]],
        resize_keyboard: Some(false),
        ..Default::default()
    };
    assert_eq!(json::encode(&x).unwrap(),
        r#"{"keyboard":[["ABC"],["X","Y"]],"resize_keyboard":false}"#.to_string());
}

#[test]
fn keyboard_markup() {
    use ReplyKeyboardMarkup as RKM;
    use ReplyMarkup as RM;

    // Test encoding
    let x = RM::Keyboard(RKM::default());
    assert_eq!(json::encode(&x).unwrap(), r#"{"keyboard":[]}"#.to_string());

    let x = RM::KeyboardHide(false);
    assert_eq!(json::encode(&x).unwrap(),
        r#"{"hide_keyboard":true,"selective":false}"#.to_string());

    let x = RM::ForceReply(true);
    assert_eq!(json::encode(&x).unwrap(),
        r#"{"force_reply":true,"selective":true}"#.to_string());
}

// #[test]
// fn decode_group_chat() {
//     use Chat;
//     use GroupChat;

//     let blob = r#"{"title":"This is a group chat","id":-12345678,"type":"group"}"#;
//     let groupchat: GroupChat = json::decode(&blob).unwrap();
//     let chat: Chat = json::decode(&blob).unwrap();

//     assert!(chat.is_group());
//     assert_eq!(Chat::Group(groupchat), chat);
// }

#[test]
fn decode_user_chat() {
    use Chat;
    use User;

    let blob = r#"{"first_name":"test","id":123456789,"username":"test","type":"private"}"#;
    let chat: Chat = json::decode(&blob).unwrap();
    let user: User = json::decode(&blob).unwrap();

    assert!(chat.is_user());
    assert_eq!(Chat::Private(user), chat);
}

#[test]
fn decode_update() {
    use Update;
    let blob = r#"{
        "message" : {
            "text" : "The quick brown fox jumps over the lazy dog",
            "from" : {
                "first_name" : "test",
                "id" : 123456789,
                "username" : "test"
            },
            "date" : 1437821492,
            "message_id" : 74,
            "chat" : {
                "title" : "This is a group chat",
                "id" : -12345678,
                "type": "group"
            }
        },
        "update_id" : 123456789
    }"#;
    let _: Update = json::decode(&blob).unwrap();
}

#[test]
fn decode_get_updates_response() {
    use Response;
    use Update;

    let blob = r#"{
        "result" : [
            {
                "message" : {
                    "text" : "This is the first message",
                    "from" : {
                        "username" : "test",
                        "id" : 123456789,
                        "first_name" : "Test"
                    },
                    "date" : 1437821579,
                    "message_id" : 78,
                    "chat" : {
                        "username" : "test",
                        "id" : 123456789,
                        "first_name" : "Test",
                        "type": "private"
                    }
                },
                "update_id" : 123456789
            },
            {
                "message" : {
                    "text" : "This is the second message",
                    "from" : {
                        "username" : "test",
                        "id" : 123456789,
                        "first_name" : "Test"
                    },
                    "date" : 1437821579,
                    "message_id" : 79,
                    "chat" : {
                        "username" : "test",
                        "id" : 123456789,
                        "first_name" : "Test",
                        "type": "private"
                    }
                },
                "update_id" : 123456790
            }
        ],
        "ok" : true
    }"#;

    let _: Response<Vec<Update>> = json::decode(&blob).unwrap();
}
<commit_msg>Reenable decode_group_chat test<commit_after>#![allow(unused_imports)]
use rustc_serialize::json;

#[test]
fn reply_keyboard_markup() {
    use ReplyKeyboardMarkup as RKM;

    // Test default values
    assert_eq!(RKM::default(), RKM {
        keyboard: Vec::new(),
        resize_keyboard: None,
        one_time_keyboard: None,
        selective: None,
    });

    // Test encoding
    let x = RKM::default();
    assert_eq!(json::encode(&x).unwrap(), r#"{"keyboard":[]}"#.to_string());

    let x = RKM { resize_keyboard: Some(true), ..Default::default() };
    assert_eq!(json::encode(&x).unwrap(),
        r#"{"keyboard":[],"resize_keyboard":true}"#.to_string());

    let x = RKM {
        keyboard: vec![vec!["ABC".into()], vec!["X".into(), "Y".into()]],
        resize_keyboard: Some(false),
        ..Default::default()
    };
    assert_eq!(json::encode(&x).unwrap(),
        r#"{"keyboard":[["ABC"],["X","Y"]],"resize_keyboard":false}"#.to_string());
}

#[test]
fn keyboard_markup() {
    use ReplyKeyboardMarkup as RKM;
    use ReplyMarkup as RM;

    // Test encoding
    let x = RM::Keyboard(RKM::default());
    assert_eq!(json::encode(&x).unwrap(), r#"{"keyboard":[]}"#.to_string());

    let x = RM::KeyboardHide(false);
    assert_eq!(json::encode(&x).unwrap(),
        r#"{"hide_keyboard":true,"selective":false}"#.to_string());

    let x = RM::ForceReply(true);
    assert_eq!(json::encode(&x).unwrap(),
        r#"{"force_reply":true,"selective":true}"#.to_string());
}

#[test]
fn decode_group_chat() {
    use Chat;

    let blob = r#"{"title":"This is a group chat","id":-12345678,"type":"group"}"#;
    let chat: Chat = json::decode(&blob).unwrap();
    assert!(chat.is_group());
}

#[test]
fn decode_user_chat() {
    use Chat;
    use User;

    let blob = r#"{"first_name":"test","id":123456789,"username":"test","type":"private"}"#;
    let chat: Chat = json::decode(&blob).unwrap();
    let user: User = json::decode(&blob).unwrap();

    assert!(chat.is_user());
    assert_eq!(Chat::Private(user), chat);
}

#[test]
fn decode_update() {
    use Update;
    let blob = r#"{
        "message" : {
            "text" : "The quick brown fox jumps over the lazy dog",
            "from" : {
                "first_name" : "test",
                "id" : 123456789,
                "username" : "test"
            },
            "date" : 1437821492,
            "message_id" : 74,
            "chat" : {
                "title" : "This is a group chat",
                "id" : -12345678,
                "type": "group"
            }
        },
        "update_id" : 123456789
    }"#;
    let _: Update = json::decode(&blob).unwrap();
}

#[test]
fn decode_get_updates_response() {
    use Response;
    use Update;

    let blob = r#"{
        "result" : [
            {
                "message" : {
                    "text" : "This is the first message",
                    "from" : {
                        "username" : "test",
                        "id" : 123456789,
                        "first_name" : "Test"
                    },
                    "date" : 1437821579,
                    "message_id" : 78,
                    "chat" : {
                        "username" : "test",
                        "id" : 123456789,
                        "first_name" : "Test",
                        "type": "private"
                    }
                },
                "update_id" : 123456789
            },
            {
                "message" : {
                    "text" : "This is the second message",
                    "from" : {
                        "username" : "test",
                        "id" : 123456789,
                        "first_name" : "Test"
                    },
                    "date" : 1437821579,
                    "message_id" : 79,
                    "chat" : {
                        "username" : "test",
                        "id" : 123456789,
                        "first_name" : "Test",
                        "type": "private"
                    }
                },
                "update_id" : 123456790
            }
        ],
        "ok" : true
    }"#;

    let _: Response<Vec<Update>> = json::decode(&blob).unwrap();
}
<|endoftext|>


<commit_before>#![allow(clippy::needless_pass_by_value)]

use std::str::FromStr;

use chrono::{DateTime, TimeZone, Utc};
use failure::{bail, Error};
use symbolic::common::DebugId;
use uuid::Uuid;

fn validate_org(v: String) -> Result<(), String> {
    if v.contains('/') || v == "." || v == ".." || v.contains(' ') {
        Err("invalid value for organization. Use the URL slug and not the name!".to_string())
    } else {
        Ok(())
    }
}

pub fn validate_project(v: String) -> Result<(), String> {
    if v.contains('/')
        || v == "."
        || v == ".."
        || v.contains(' ')
        || v.contains('\n')
        || v.contains('\t')
        || v.contains('\r')
    {
        Err("invalid value for project. Use the URL slug and not the name!".to_string())
    } else {
        Ok(())
    }
}

fn validate_version(v: String) -> Result<(), String> {
    if v.trim() != v {
        Err(
            "Invalid release version. Releases must not contain leading or trailing spaces."
                .to_string(),
        )
    } else if v.is_empty()
        || v == "."
        || v == ".."
        || v.find(&['\n', '\t', '\x0b', '\x0c', '\t', '/'][..])
            .is_some()
    {
        Err(
            "Invalid release version. Slashes and certain whitespace characters are not permitted."
                .to_string(),
        )
    } else {
        Ok(())
    }
}

pub fn validate_seconds(v: String) -> Result<(), String> {
    if v.parse::<i64>().is_ok() {
        Ok(())
    } else {
        Err("Invalid value (seconds as integer required)".to_string())
    }
}

pub fn validate_timestamp(v: String) -> Result<(), String> {
    if let Err(err) = get_timestamp(&v) {
        Err(err.to_string())
    } else {
        Ok(())
    }
}

pub fn validate_uuid(s: String) -> Result<(), String> {
    if Uuid::parse_str(&s).is_err() {
        Err("Invalid UUID".to_string())
    } else {
        Ok(())
    }
}

pub fn validate_id(s: String) -> Result<(), String> {
    if DebugId::from_str(&s).is_err() {
        Err("Invalid ID".to_string())
    } else {
        Ok(())
    }
}

pub fn get_timestamp(value: &str) -> Result<DateTime<Utc>, Error> {
    if let Ok(int) = value.parse::<i64>() {
        Ok(Utc.timestamp(int, 0))
    } else if let Ok(dt) = DateTime::parse_from_rfc3339(value) {
        Ok(dt.with_timezone(&Utc))
    } else if let Ok(dt) = DateTime::parse_from_rfc2822(value) {
        Ok(dt.with_timezone(&Utc))
    } else {
        bail!("not in valid format. Unix timestamp or ISO 8601 date expected.");
    }
}

pub trait ArgExt: Sized {
    fn org_arg(self) -> Self;
    fn project_arg(self) -> Self;
    fn projects_arg(self) -> Self;
    fn org_project_args(self) -> Self {
        self.org_arg().project_arg()
    }
    fn version_arg(self, index: u64) -> Self;
}

impl<'a: 'b, 'b> ArgExt for clap::App<'a, 'b> {
    fn org_arg(self) -> clap::App<'a, 'b> {
        self.arg(
            clap::Arg::with_name("org")
                .value_name("ORG")
                .long("org")
                .short("o")
                .validator(validate_org)
                .help("The organization slug"),
        )
    }

    fn project_arg(self) -> clap::App<'a, 'b> {
        self.arg(
            clap::Arg::with_name("project")
                .value_name("PROJECT")
                .long("project")
                .short("p")
                .validator(validate_project)
                .help("The project slug"),
        )
    }

    fn projects_arg(self) -> clap::App<'a, 'b> {
        self.arg(
            clap::Arg::with_name("projects")
                .value_name("PROJECT")
                .long("project")
                .short("p")
                .multiple(true)
                .number_of_values(1)
                .required(false)
                .validator(validate_project)
                .help("The project slug.  This can be supplied multiple times."),
        )
    }

    fn version_arg(self, index: u64) -> clap::App<'a, 'b> {
        self.arg(
            clap::Arg::with_name("version")
                .value_name("VERSION")
                .required(true)
                .index(index)
                .validator(validate_version)
                .help("The version of the release"),
        )
    }
}
<commit_msg>fix: Allow for release names with leading hyphen (#770)<commit_after>#![allow(clippy::needless_pass_by_value)]

use std::str::FromStr;

use chrono::{DateTime, TimeZone, Utc};
use clap::AppSettings;
use failure::{bail, Error};
use symbolic::common::DebugId;
use uuid::Uuid;

fn validate_org(v: String) -> Result<(), String> {
    if v.contains('/') || v == "." || v == ".." || v.contains(' ') {
        Err("invalid value for organization. Use the URL slug and not the name!".to_string())
    } else {
        Ok(())
    }
}

pub fn validate_project(v: String) -> Result<(), String> {
    if v.contains('/')
        || v == "."
        || v == ".."
        || v.contains(' ')
        || v.contains('\n')
        || v.contains('\t')
        || v.contains('\r')
    {
        Err("invalid value for project. Use the URL slug and not the name!".to_string())
    } else {
        Ok(())
    }
}

fn validate_version(v: String) -> Result<(), String> {
    if v.trim() != v {
        Err(
            "Invalid release version. Releases must not contain leading or trailing spaces."
                .to_string(),
        )
    } else if v.is_empty()
        || v == "."
        || v == ".."
        || v.find(&['\n', '\t', '\x0b', '\x0c', '\t', '/'][..])
            .is_some()
    {
        Err(
            "Invalid release version. Slashes and certain whitespace characters are not permitted."
                .to_string(),
        )
    } else {
        Ok(())
    }
}

pub fn validate_seconds(v: String) -> Result<(), String> {
    if v.parse::<i64>().is_ok() {
        Ok(())
    } else {
        Err("Invalid value (seconds as integer required)".to_string())
    }
}

pub fn validate_timestamp(v: String) -> Result<(), String> {
    if let Err(err) = get_timestamp(&v) {
        Err(err.to_string())
    } else {
        Ok(())
    }
}

pub fn validate_uuid(s: String) -> Result<(), String> {
    if Uuid::parse_str(&s).is_err() {
        Err("Invalid UUID".to_string())
    } else {
        Ok(())
    }
}

pub fn validate_id(s: String) -> Result<(), String> {
    if DebugId::from_str(&s).is_err() {
        Err("Invalid ID".to_string())
    } else {
        Ok(())
    }
}

pub fn get_timestamp(value: &str) -> Result<DateTime<Utc>, Error> {
    if let Ok(int) = value.parse::<i64>() {
        Ok(Utc.timestamp(int, 0))
    } else if let Ok(dt) = DateTime::parse_from_rfc3339(value) {
        Ok(dt.with_timezone(&Utc))
    } else if let Ok(dt) = DateTime::parse_from_rfc2822(value) {
        Ok(dt.with_timezone(&Utc))
    } else {
        bail!("not in valid format. Unix timestamp or ISO 8601 date expected.");
    }
}

pub trait ArgExt: Sized {
    fn org_arg(self) -> Self;
    fn project_arg(self) -> Self;
    fn projects_arg(self) -> Self;
    fn org_project_args(self) -> Self {
        self.org_arg().project_arg()
    }
    fn version_arg(self, index: u64) -> Self;
}

impl<'a: 'b, 'b> ArgExt for clap::App<'a, 'b> {
    fn org_arg(self) -> clap::App<'a, 'b> {
        self.arg(
            clap::Arg::with_name("org")
                .value_name("ORG")
                .long("org")
                .short("o")
                .validator(validate_org)
                .help("The organization slug"),
        )
    }

    fn project_arg(self) -> clap::App<'a, 'b> {
        self.arg(
            clap::Arg::with_name("project")
                .value_name("PROJECT")
                .long("project")
                .short("p")
                .validator(validate_project)
                .help("The project slug"),
        )
    }

    fn projects_arg(self) -> clap::App<'a, 'b> {
        self.arg(
            clap::Arg::with_name("projects")
                .value_name("PROJECT")
                .long("project")
                .short("p")
                .multiple(true)
                .number_of_values(1)
                .required(false)
                .validator(validate_project)
                .help("The project slug.  This can be supplied multiple times."),
        )
    }

    fn version_arg(self, index: u64) -> clap::App<'a, 'b> {
        self.setting(AppSettings::AllowLeadingHyphen).arg(
            clap::Arg::with_name("version")
                .value_name("VERSION")
                .required(true)
                .index(index)
                .validator(validate_version)
                .help("The version of the release"),
        )
    }
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use crate::completion::{CompletionContext, Completions};

/// Complete fields in fields literals.
pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionContext) {
    let (ty, variant) = match ctx.record_lit_syntax.as_ref().and_then(|it| {
        Some((ctx.sema.type_of_expr(&it.clone().into())?, ctx.sema.resolve_record_literal(it)?))
    }) {
        Some(it) => it,
        _ => return,
    };

    for (field, field_ty) in ty.variant_fields(ctx.db, variant) {
        acc.add_field(ctx, field, &field_ty);
    }
}

#[cfg(test)]
mod tests {
    use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
    use insta::assert_debug_snapshot;

    fn complete(code: &str) -> Vec<CompletionItem> {
        do_completion(code, CompletionKind::Reference)
    }

    #[test]
    fn test_record_literal_deprecated_field() {
        let completions = complete(
            r"
            struct A {
                #[deprecated]
                the_field: u32,
            }
            fn foo() {
               A { the<|> }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [142; 145),
                delete: [142; 145),
                insert: "the_field",
                kind: Field,
                detail: "u32",
                deprecated: true,
            },
        ]
        "###);
    }

    #[test]
    fn test_record_literal_field() {
        let completions = complete(
            r"
            struct A { the_field: u32 }
            fn foo() {
               A { the<|> }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [83; 86),
                delete: [83; 86),
                insert: "the_field",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }

    #[test]
    fn test_record_literal_enum_variant() {
        let completions = complete(
            r"
            enum E {
                A { a: u32 }
            }
            fn foo() {
                let _ = E::A { <|> }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "a",
                source_range: [119; 119),
                delete: [119; 119),
                insert: "a",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }

    #[test]
    fn test_record_literal_two_structs() {
        let completions = complete(
            r"
            struct A { a: u32 }
            struct B { b: u32 }

            fn foo() {
               let _: A = B { <|> }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "b",
                source_range: [119; 119),
                delete: [119; 119),
                insert: "b",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }

    #[test]
    fn test_record_literal_generic_struct() {
        let completions = complete(
            r"
            struct A<T> { a: T }

            fn foo() {
               let _: A<u32> = A { <|> }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "a",
                source_range: [93; 93),
                delete: [93; 93),
                insert: "a",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }

    #[test]
    fn test_record_literal_field_in_simple_macro() {
        let completions = complete(
            r"
            macro_rules! m { ($e:expr) => { $e } }
            struct A { the_field: u32 }
            fn foo() {
               m!(A { the<|> })
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [137; 140),
                delete: [137; 140),
                insert: "the_field",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }
}
<commit_msg>Complete only missing fields<commit_after>//! FIXME: write short doc here

use crate::completion::{CompletionContext, Completions};

/// Complete fields in fields literals.
pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionContext) {
    let (ty, variant) = match ctx.record_lit_syntax.as_ref().and_then(|it| {
        Some((ctx.sema.type_of_expr(&it.clone().into())?, ctx.sema.resolve_record_literal(it)?))
    }) {
        Some(it) => it,
        _ => return,
    };

    let already_present_names: Vec<String> = ctx
        .record_lit_syntax
        .as_ref()
        .and_then(|record_literal| record_literal.record_field_list())
        .map(|field_list| field_list.fields())
        .map(|fields| {
            fields
                .into_iter()
                .filter_map(|field| field.name_ref())
                .map(|name_ref| name_ref.to_string())
                .collect()
        })
        .unwrap_or_default();

    for (field, field_ty) in ty.variant_fields(ctx.db, variant) {
        if !already_present_names.contains(&field.name(ctx.db).to_string()) {
            acc.add_field(ctx, field, &field_ty);
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
    use insta::assert_debug_snapshot;

    fn complete(code: &str) -> Vec<CompletionItem> {
        do_completion(code, CompletionKind::Reference)
    }

    #[test]
    fn test_record_literal_deprecated_field() {
        let completions = complete(
            r"
            struct A {
                #[deprecated]
                the_field: u32,
            }
            fn foo() {
               A { the<|> }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [142; 145),
                delete: [142; 145),
                insert: "the_field",
                kind: Field,
                detail: "u32",
                deprecated: true,
            },
        ]
        "###);
    }

    #[test]
    fn test_record_literal_field() {
        let completions = complete(
            r"
            struct A { the_field: u32 }
            fn foo() {
               A { the<|> }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [83; 86),
                delete: [83; 86),
                insert: "the_field",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }

    #[test]
    fn test_record_literal_enum_variant() {
        let completions = complete(
            r"
            enum E {
                A { a: u32 }
            }
            fn foo() {
                let _ = E::A { <|> }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "a",
                source_range: [119; 119),
                delete: [119; 119),
                insert: "a",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }

    #[test]
    fn test_record_literal_two_structs() {
        let completions = complete(
            r"
            struct A { a: u32 }
            struct B { b: u32 }

            fn foo() {
               let _: A = B { <|> }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "b",
                source_range: [119; 119),
                delete: [119; 119),
                insert: "b",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }

    #[test]
    fn test_record_literal_generic_struct() {
        let completions = complete(
            r"
            struct A<T> { a: T }

            fn foo() {
               let _: A<u32> = A { <|> }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "a",
                source_range: [93; 93),
                delete: [93; 93),
                insert: "a",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }

    #[test]
    fn test_record_literal_field_in_simple_macro() {
        let completions = complete(
            r"
            macro_rules! m { ($e:expr) => { $e } }
            struct A { the_field: u32 }
            fn foo() {
               m!(A { the<|> })
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "the_field",
                source_range: [137; 140),
                delete: [137; 140),
                insert: "the_field",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }

    #[test]
    fn only_missing_fields_are_completed() {
        let completions = complete(
            r"
            struct S {
                foo1: u32,
                foo2: u32,
                bar: u32,
                baz: u32,
            }

            fn main() {
                let foo1 = 1;
                let s = S {
                    foo1,
                    foo2: 5,
                    <|>
                }
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "bar",
                source_range: [302; 302),
                delete: [302; 302),
                insert: "bar",
                kind: Field,
                detail: "u32",
            },
            CompletionItem {
                label: "baz",
                source_range: [302; 302),
                delete: [302; 302),
                insert: "baz",
                kind: Field,
                detail: "u32",
            },
        ]
        "###);
    }
}
<|endoftext|>


<commit_before>use std::ffi::CString;

use rustc::lib::llvm;
use rustc::lib::llvm::{ ContextRef
                      , ModuleRef
                      , ValueRef
                  };

use position::Positional;

pub type IRResult = Result<ValueRef, Positional<String>>;

/// Trait for an object that can be compiled to LLVM IR
pub trait ToIR {
    fn to_ir(&self) -> IRResult;
}

/// LLVM compilation context.
///
/// This is based rather loosely on MIT License code from
/// the [iron-kaleidoscope](https://github.com/jauhien/iron-kaleidoscope)
/// tutorial, and from [`librustc_trans`](https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/mod.rs)
/// from the Rust compiler.
pub struct LLVMContext {
    pub llctx: ContextRef,
    pub llmod: ModuleRef
}

impl LLVMContext {
    pub fn new(module_name: &str) -> Self {
        let name = CString::new(module_name).unwrap();
        unsafe {
            let c = llvm::LLVMContextCreate();
            assert!(c.is_null() == false,
                "Could not create LLVM context, ContextRef was null.");
            let m = llvm::LLVMModuleCreateWithNameInContext(name.into_raw(), c);
            assert!(m.is_null() == false,
                "Could not create LLVM context, ModuleRef was null.");
            LLVMContext { llctx: c, llmod: m }
        }
    }
}

impl Drop for LLVMContext {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeModule(self.llmod);
            llvm::LLVMContextDispose(self.llctx);
        }
    }
}
<commit_msg>Add not_null!() macro This will probably be useful when dealing with C FFI.<commit_after>use std::ffi::CString;

use rustc::lib::llvm;
use rustc::lib::llvm::{ ContextRef
                      , ModuleRef
                      , ValueRef
                  };

use position::Positional;

pub type IRResult = Result<ValueRef, Positional<String>>;

/// Trait for an object that can be compiled to LLVM IR
pub trait ToIR {
    fn to_ir(&self) -> IRResult;
}

/// LLVM compilation context.
///
/// This is based rather loosely on MIT License code from
/// the [iron-kaleidoscope](https://github.com/jauhien/iron-kaleidoscope)
/// tutorial, and from [`librustc_trans`](https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/mod.rs)
/// from the Rust compiler.
pub struct LLVMContext {
    pub llctx: ContextRef,
    pub llmod: ModuleRef
}

// because we are in the Raw Pointer Sadness Zone (read: unsafe),
// it is necessary that we assert that everything exists.
macro_rules! not_null {
    ($target:expr) => {
        if $target.is_null() {
            panic!("assertion failed: {} was null!", stringify!($target));
        }
    }
}

impl LLVMContext {
    pub fn new(module_name: &str) -> Self {
        let name = CString::new(module_name).unwrap();
        unsafe {
            let c = llvm::LLVMContextCreate();
            not_null!(c);
            let m = llvm::LLVMModuleCreateWithNameInContext(name.into_raw(),c);
            not_null!(m);
            LLVMContext { llctx: c, llmod: m }
        }
    }
}

impl Drop for LLVMContext {
    fn drop(&mut self) {
        unsafe {
            llvm::LLVMDisposeModule(self.llmod);
            llvm::LLVMContextDispose(self.llctx);
        }
    }
}
<|endoftext|>


<commit_before>extern crate document;

use std::cmp::min;
use std::io::File;
use std::io::BufferedWriter;
use std::io::stdio::stdout_raw;

use document::parser::Parser;

fn pretty_error(xml: &str, position: uint) -> &str {
    let s = xml.slice_from(position);
    let l = s.char_len();
    s.slice_chars(0, min(l, 15))
}

fn main() {
    let mut args = std::os::args();

    let filename = args.remove(1).expect("File required");
    let path = Path::new(filename);
    let mut file = File::open(&path);

    let data = match file.read_to_end() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    let data = match String::from_utf8(data) {
        Ok(x) => x,
        Err(x) => panic!("Unable to convert to UTF-8: {}", x),
    };

    let p = Parser::new();

    let package = match p.parse(data.as_slice()) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(data.as_slice(), point)),
    };

    let mut out = BufferedWriter::new(stdout_raw());

    {
        let d = package.as_document();
        document::writer::format_document(&d, &mut out).ok().expect("I can't output");
    }
}
<commit_msg>No need to convert to a string when Reader will do it for us<commit_after>extern crate document;

use std::cmp::min;
use std::io::File;
use std::io::BufferedWriter;
use std::io::stdio::stdout_raw;

use document::parser::Parser;

fn pretty_error(xml: &str, position: uint) -> &str {
    let s = xml.slice_from(position);
    let l = s.char_len();
    s.slice_chars(0, min(l, 15))
}

fn main() {
    let mut args = std::os::args();

    let filename = args.remove(1).expect("File required");
    let path = Path::new(filename);
    let mut file = File::open(&path);

    let data = match file.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    let p = Parser::new();

    let package = match p.parse(data.as_slice()) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(data.as_slice(), point)),
    };

    let mut out = BufferedWriter::new(stdout_raw());

    {
        let d = package.as_document();
        document::writer::format_document(&d, &mut out).ok().expect("I can't output");
    }
}
<|endoftext|>