<commit_before>#![feature(io)]

extern crate compiler;
extern crate argparse;

use compiler::{ir,machine,target};
use compiler::target::Target;
use std::error::Error;
use std::io::{Read,Write};
use std::fs;

use argparse::ArgumentParser;

#[derive(Copy,Clone)]
enum Task
{
    Parse,
    Assemble,
    ListTargets,
}

impl Task
{
    fn requires_input_files(&self) -> bool {
        match *self {
            Task::Parse => true,
            Task::Assemble => true,
            Task::ListTargets => false,
        }
    }
}

fn main() {
    machine::AVR::register();

    let mut files: Vec<String> = Vec::new();

    let mut task = Task::Assemble;
    let mut target_name = "".to_owned();

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Assembles files");

        ap.refer(&mut files)
            .add_argument("files", argparse::List,
                          r#"Files to process"#);
        ap.refer(&mut target_name)
            .add_option(&["--target"], argparse::Store,
                        "the target");
        ap.refer(&mut task)
            .add_option(&["--parse"], argparse::StoreConst(Task::Parse),
                        "only parse the module")
            .add_option(&["--list-targets"], argparse::StoreConst(Task::ListTargets),
                        "list all of the targets supported");
        ap.parse_args_or_exit();
    }

    if task.requires_input_files() && files.len() == 0 {
        abort("no files given");
    }

    match task {
        Task::ListTargets => list_targets(),
        Task::Parse => for file_name in files { parse(&file_name) },
        Task::Assemble => {
            if target_name.len() == 0 {
                abort("target not speficied on command line");
            }

            let target = match target::registry::lookup(&target_name) {
                Some(target) => target,
                None => {
                    abort(format!("target '{}' does not exist", target_name));
                },
            };

            for file_name in files.iter() {
                generate(target::OutputType::Assembly, target, &file_name);
            }
        }
    }
}

fn generate(output_type: target::OutputType, target: &Target, file_name: &str) {
    let mut file = fs::File::open(file_name).unwrap();
    let mut output: Vec<u8> = Vec::new();

    target.generate(output_type,
                    &mut file,
                    &mut output).unwrap();

    let asm = String::from_utf8(output).unwrap();
    print!("{}", asm);
}

fn list_targets() {
    for target in target::registry::list() {
        println!("{}", target.name());
    }
}

fn parse(file_name: &str) {
    let module = parse_module(&file_name);

    print_module(&module);
}

fn open_file(path: &str) -> std::fs::File {
    match std::fs::File::open(path) {
        Ok(f) => f,
        Err(e) => abort(format!("could not open {}: {}",
                                path, e.description())),
    }
}

fn parse_module(file_name: &str) -> ir::Module {
    let chars = open_file(file_name).chars().map(|c| c.unwrap());

    match ir::read::textual(chars) {
        Ok(module) => module,
        Err(e) => abort(format!("could not parse IR file: {}", e)),
    }
}

fn print_module(module: &ir::Module) {
    println!("{}", ir::printable(module));
}

fn abort<S>(msg: S) -> !
    where S: Into<String> {
    write!(std::io::stderr(),
           "{}\n", msg.into()).unwrap();
    std::process::exit(1);
}
<commit_msg>Default to compiling for AVR<commit_after>#![feature(io)]

extern crate compiler;
extern crate argparse;

use compiler::{ir,machine,target};
use compiler::target::Target;
use std::error::Error;
use std::io::{Read,Write};
use std::fs;

use argparse::ArgumentParser;

#[derive(Copy,Clone)]
enum Task
{
    Parse,
    Assemble,
    ListTargets,
}

impl Task
{
    fn requires_input_files(&self) -> bool {
        match *self {
            Task::Parse => true,
            Task::Assemble => true,
            Task::ListTargets => false,
        }
    }
}

fn main() {
    machine::AVR::register();

    let mut files: Vec<String> = Vec::new();

    let mut task = Task::Assemble;
    let mut target_name = "avr".to_owned();

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Assembles files");

        ap.refer(&mut files)
            .add_argument("files", argparse::List,
                          r#"Files to process"#);
        ap.refer(&mut target_name)
            .add_option(&["--target"], argparse::Store,
                        "the target");
        ap.refer(&mut task)
            .add_option(&["--parse"], argparse::StoreConst(Task::Parse),
                        "only parse the module")
            .add_option(&["--list-targets"], argparse::StoreConst(Task::ListTargets),
                        "list all of the targets supported");
        ap.parse_args_or_exit();
    }

    if task.requires_input_files() && files.len() == 0 {
        abort("no files given");
    }

    match task {
        Task::ListTargets => list_targets(),
        Task::Parse => for file_name in files { parse(&file_name) },
        Task::Assemble => {
            if target_name.len() == 0 {
                abort("target not speficied on command line");
            }

            let target = match target::registry::lookup(&target_name) {
                Some(target) => target,
                None => {
                    abort(format!("target '{}' does not exist", target_name));
                },
            };

            for file_name in files.iter() {
                generate(target::OutputType::Assembly, target, &file_name);
            }
        }
    }
}

fn generate(output_type: target::OutputType, target: &Target, file_name: &str) {
    let mut file = fs::File::open(file_name).unwrap();
    let mut output: Vec<u8> = Vec::new();

    target.generate(output_type,
                    &mut file,
                    &mut output).unwrap();

    let asm = String::from_utf8(output).unwrap();
    print!("{}", asm);
}

fn list_targets() {
    for target in target::registry::list() {
        println!("{}", target.name());
    }
}

fn parse(file_name: &str) {
    let module = parse_module(&file_name);

    print_module(&module);
}

fn open_file(path: &str) -> std::fs::File {
    match std::fs::File::open(path) {
        Ok(f) => f,
        Err(e) => abort(format!("could not open {}: {}",
                                path, e.description())),
    }
}

fn parse_module(file_name: &str) -> ir::Module {
    let chars = open_file(file_name).chars().map(|c| c.unwrap());

    match ir::read::textual(chars) {
        Ok(module) => module,
        Err(e) => abort(format!("could not parse IR file: {}", e)),
    }
}

fn print_module(module: &ir::Module) {
    println!("{}", ir::printable(module));
}

fn abort<S>(msg: S) -> !
    where S: Into<String> {
    write!(std::io::stderr(),
           "{}\n", msg.into()).unwrap();
    std::process::exit(1);
}
<|endoftext|>


<commit_before>//! Compatibility between the `tokio::io` and `futures-io` versions of the
//! `AsyncRead` and `AsyncWrite` traits.
use futures_core::ready;
use pin_project_lite::pin_project;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};

pin_project! {
    /// A compatibility layer that allows conversion between the
    /// `tokio::io` and `futures-io` `AsyncRead` and `AsyncWrite` traits.
    #[derive(Copy, Clone, Debug)]
    pub struct Compat<T> {
        #[pin]
        inner: T,
    }
}

/// Extension trait that allows converting a type implementing
/// `futures_io::AsyncRead` to implement `tokio::io::AsyncRead`.
pub trait FuturesAsyncReadCompatExt: futures_io::AsyncRead {
    /// Wraps `self` with a compatibility layer that implements
    /// `tokio_io::AsyncRead`.
    fn compat(self) -> Compat<Self>
    where
        Self: Sized,
    {
        Compat::new(self)
    }
}

impl<T: futures_io::AsyncRead> FuturesAsyncReadCompatExt for T {}

/// Extension trait that allows converting a type implementing
/// `futures_io::AsyncWrite` to implement `tokio::io::AsyncWrite`.
pub trait FuturesAsyncWriteCompatExt: futures_io::AsyncWrite {
    /// Wraps `self` with a compatibility layer that implements
    /// `tokio::io::AsyncWrite`.
    fn compat_write(self) -> Compat<Self>
    where
        Self: Sized,
    {
        Compat::new(self)
    }
}

impl<T: futures_io::AsyncWrite> FuturesAsyncWriteCompatExt for T {}

/// Extension trait that allows converting a type implementing
/// `tokio::io::AsyncRead` to implement `futures_io::AsyncRead`.
pub trait TokioAsyncReadCompatExt: tokio::io::AsyncRead {
    /// Wraps `self` with a compatibility layer that implements
    /// `futures_io::AsyncRead`.
    fn compat(self) -> Compat<Self>
    where
        Self: Sized,
    {
        Compat::new(self)
    }
}

impl<T: tokio::io::AsyncRead> TokioAsyncReadCompatExt for T {}

/// Extension trait that allows converting a type implementing
/// `tokio::io::AsyncWrite` to implement `futures_io::AsyncWrite`.
pub trait TokioAsyncWriteCompatExt: tokio::io::AsyncWrite {
    /// Wraps `self` with a compatibility layer that implements
    /// `futures_io::AsyncWrite`.
    fn compat_write(self) -> Compat<Self>
    where
        Self: Sized,
    {
        Compat::new(self)
    }
}

impl<T: tokio::io::AsyncWrite> TokioAsyncWriteCompatExt for T {}

// === impl Compat ===

impl<T> Compat<T> {
    fn new(inner: T) -> Self {
        Self { inner }
    }

    /// Get a reference to the `Future`, `Stream`, `AsyncRead`, or `AsyncWrite` object
    /// contained within.
    pub fn get_ref(&self) -> &T {
        &self.inner
    }

    /// Get a mutable reference to the `Future`, `Stream`, `AsyncRead`, or `AsyncWrite` object
    /// contained within.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner
    }

    /// Returns the wrapped item.
    pub fn into_inner(self) -> T {
        self.inner
    }
}

impl<T> tokio::io::AsyncRead for Compat<T>
where
    T: futures_io::AsyncRead,
{
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut tokio::io::ReadBuf<'_>,
    ) -> Poll<io::Result<()>> {
        // We can't trust the inner type to not peak at the bytes,
        // so we must defensively initialize the buffer.
        let slice = buf.initialize_unfilled();
        let n = ready!(futures_io::AsyncRead::poll_read(
            self.project().inner,
            cx,
            slice
        ))?;
        buf.advance(n);
        Poll::Ready(Ok(()))
    }
}

impl<T> futures_io::AsyncRead for Compat<T>
where
    T: tokio::io::AsyncRead,
{
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        slice: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        let mut buf = tokio::io::ReadBuf::new(slice);
        ready!(tokio::io::AsyncRead::poll_read(
            self.project().inner,
            cx,
            &mut buf
        ))?;
        Poll::Ready(Ok(buf.filled().len()))
    }
}

impl<T> tokio::io::AsyncBufRead for Compat<T>
where
    T: futures_io::AsyncBufRead,
{
    fn poll_fill_buf<'a>(
        self: Pin<&'a mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<io::Result<&'a [u8]>> {
        futures_io::AsyncBufRead::poll_fill_buf(self.project().inner, cx)
    }

    fn consume(self: Pin<&mut Self>, amt: usize) {
        futures_io::AsyncBufRead::consume(self.project().inner, amt)
    }
}

impl<T> futures_io::AsyncBufRead for Compat<T>
where
    T: tokio::io::AsyncBufRead,
{
    fn poll_fill_buf<'a>(
        self: Pin<&'a mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<io::Result<&'a [u8]>> {
        tokio::io::AsyncBufRead::poll_fill_buf(self.project().inner, cx)
    }

    fn consume(self: Pin<&mut Self>, amt: usize) {
        tokio::io::AsyncBufRead::consume(self.project().inner, amt)
    }
}

impl<T> tokio::io::AsyncWrite for Compat<T>
where
    T: futures_io::AsyncWrite,
{
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<io::Result<usize>> {
        futures_io::AsyncWrite::poll_write(self.project().inner, cx, buf)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        futures_io::AsyncWrite::poll_flush(self.project().inner, cx)
    }

    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        futures_io::AsyncWrite::poll_close(self.project().inner, cx)
    }
}

impl<T> futures_io::AsyncWrite for Compat<T>
where
    T: tokio::io::AsyncWrite,
{
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<io::Result<usize>> {
        tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        tokio::io::AsyncWrite::poll_flush(self.project().inner, cx)
    }

    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx)
    }
}
<commit_msg>util: impl AsRawFd/AsRawHandle for Compat<T> (#3765)<commit_after>//! Compatibility between the `tokio::io` and `futures-io` versions of the
//! `AsyncRead` and `AsyncWrite` traits.
use futures_core::ready;
use pin_project_lite::pin_project;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll};

pin_project! {
    /// A compatibility layer that allows conversion between the
    /// `tokio::io` and `futures-io` `AsyncRead` and `AsyncWrite` traits.
    #[derive(Copy, Clone, Debug)]
    pub struct Compat<T> {
        #[pin]
        inner: T,
    }
}

/// Extension trait that allows converting a type implementing
/// `futures_io::AsyncRead` to implement `tokio::io::AsyncRead`.
pub trait FuturesAsyncReadCompatExt: futures_io::AsyncRead {
    /// Wraps `self` with a compatibility layer that implements
    /// `tokio_io::AsyncRead`.
    fn compat(self) -> Compat<Self>
    where
        Self: Sized,
    {
        Compat::new(self)
    }
}

impl<T: futures_io::AsyncRead> FuturesAsyncReadCompatExt for T {}

/// Extension trait that allows converting a type implementing
/// `futures_io::AsyncWrite` to implement `tokio::io::AsyncWrite`.
pub trait FuturesAsyncWriteCompatExt: futures_io::AsyncWrite {
    /// Wraps `self` with a compatibility layer that implements
    /// `tokio::io::AsyncWrite`.
    fn compat_write(self) -> Compat<Self>
    where
        Self: Sized,
    {
        Compat::new(self)
    }
}

impl<T: futures_io::AsyncWrite> FuturesAsyncWriteCompatExt for T {}

/// Extension trait that allows converting a type implementing
/// `tokio::io::AsyncRead` to implement `futures_io::AsyncRead`.
pub trait TokioAsyncReadCompatExt: tokio::io::AsyncRead {
    /// Wraps `self` with a compatibility layer that implements
    /// `futures_io::AsyncRead`.
    fn compat(self) -> Compat<Self>
    where
        Self: Sized,
    {
        Compat::new(self)
    }
}

impl<T: tokio::io::AsyncRead> TokioAsyncReadCompatExt for T {}

/// Extension trait that allows converting a type implementing
/// `tokio::io::AsyncWrite` to implement `futures_io::AsyncWrite`.
pub trait TokioAsyncWriteCompatExt: tokio::io::AsyncWrite {
    /// Wraps `self` with a compatibility layer that implements
    /// `futures_io::AsyncWrite`.
    fn compat_write(self) -> Compat<Self>
    where
        Self: Sized,
    {
        Compat::new(self)
    }
}

impl<T: tokio::io::AsyncWrite> TokioAsyncWriteCompatExt for T {}

// === impl Compat ===

impl<T> Compat<T> {
    fn new(inner: T) -> Self {
        Self { inner }
    }

    /// Get a reference to the `Future`, `Stream`, `AsyncRead`, or `AsyncWrite` object
    /// contained within.
    pub fn get_ref(&self) -> &T {
        &self.inner
    }

    /// Get a mutable reference to the `Future`, `Stream`, `AsyncRead`, or `AsyncWrite` object
    /// contained within.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner
    }

    /// Returns the wrapped item.
    pub fn into_inner(self) -> T {
        self.inner
    }
}

impl<T> tokio::io::AsyncRead for Compat<T>
where
    T: futures_io::AsyncRead,
{
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut tokio::io::ReadBuf<'_>,
    ) -> Poll<io::Result<()>> {
        // We can't trust the inner type to not peak at the bytes,
        // so we must defensively initialize the buffer.
        let slice = buf.initialize_unfilled();
        let n = ready!(futures_io::AsyncRead::poll_read(
            self.project().inner,
            cx,
            slice
        ))?;
        buf.advance(n);
        Poll::Ready(Ok(()))
    }
}

impl<T> futures_io::AsyncRead for Compat<T>
where
    T: tokio::io::AsyncRead,
{
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        slice: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        let mut buf = tokio::io::ReadBuf::new(slice);
        ready!(tokio::io::AsyncRead::poll_read(
            self.project().inner,
            cx,
            &mut buf
        ))?;
        Poll::Ready(Ok(buf.filled().len()))
    }
}

impl<T> tokio::io::AsyncBufRead for Compat<T>
where
    T: futures_io::AsyncBufRead,
{
    fn poll_fill_buf<'a>(
        self: Pin<&'a mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<io::Result<&'a [u8]>> {
        futures_io::AsyncBufRead::poll_fill_buf(self.project().inner, cx)
    }

    fn consume(self: Pin<&mut Self>, amt: usize) {
        futures_io::AsyncBufRead::consume(self.project().inner, amt)
    }
}

impl<T> futures_io::AsyncBufRead for Compat<T>
where
    T: tokio::io::AsyncBufRead,
{
    fn poll_fill_buf<'a>(
        self: Pin<&'a mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<io::Result<&'a [u8]>> {
        tokio::io::AsyncBufRead::poll_fill_buf(self.project().inner, cx)
    }

    fn consume(self: Pin<&mut Self>, amt: usize) {
        tokio::io::AsyncBufRead::consume(self.project().inner, amt)
    }
}

impl<T> tokio::io::AsyncWrite for Compat<T>
where
    T: futures_io::AsyncWrite,
{
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<io::Result<usize>> {
        futures_io::AsyncWrite::poll_write(self.project().inner, cx, buf)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        futures_io::AsyncWrite::poll_flush(self.project().inner, cx)
    }

    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        futures_io::AsyncWrite::poll_close(self.project().inner, cx)
    }
}

impl<T> futures_io::AsyncWrite for Compat<T>
where
    T: tokio::io::AsyncWrite,
{
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<io::Result<usize>> {
        tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        tokio::io::AsyncWrite::poll_flush(self.project().inner, cx)
    }

    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx)
    }
}

#[cfg(unix)]
impl<T: std::os::unix::io::AsRawFd> std::os::unix::io::AsRawFd for Compat<T> {
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        self.inner.as_raw_fd()
    }
}

#[cfg(windows)]
impl<T: std::os::windows::io::AsRawHandle> std::os::windows::io::AsRawHandle for Compat<T> {
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        self.inner.as_raw_handle()
    }
}
<|endoftext|>


<commit_before>use core::sync::atomic::{AtomicUsize, Ordering};

use crate::context::timeout;
use crate::device::{local_apic, ioapic, pic};
use crate::device::serial::{COM1, COM2};
use crate::ipi::{ipi, IpiKind, IpiTarget};
use crate::scheme::debug::debug_input;
use crate::{context, ptrace, time};

//resets to 0 in context::switch()
#[thread_local]
pub static PIT_TICKS: AtomicUsize = AtomicUsize::new(0);

#[repr(u8)]
pub enum IrqMethod {
    Pic = 0,
    Apic = 1,
}

static IRQ_METHOD: AtomicUsize = AtomicUsize::new(IrqMethod::Pic as usize);

pub fn set_irq_method(method: IrqMethod) {
    IRQ_METHOD.store(method as usize, core::sync::atomic::Ordering::Release);
}

fn irq_method() -> IrqMethod {
    let raw = IRQ_METHOD.load(core::sync::atomic::Ordering::Acquire);

    match raw {
        0 => IrqMethod::Pic,
        1 => IrqMethod::Apic,
        _ => unreachable!(),
    }
}

extern {
    // triggers irq scheme
    fn irq_trigger(irq: u8);
}

/// Notify the IRQ scheme that an IRQ has been registered. This should mask the IRQ until the
/// scheme user unmasks it ("acknowledges" it).
unsafe fn trigger(irq: u8) {
    match irq_method() {
        IrqMethod::Pic => if irq < 16 { pic_mask(irq) },
        IrqMethod::Apic => ioapic_mask(irq),
    }
    irq_trigger(irq);
}
/// Unmask the IRQ. This is called from the IRQ scheme, which does this when a user process has
/// processed the IRQ.
pub unsafe fn acknowledge(irq: usize) {
    match irq_method() {
        IrqMethod::Pic => if irq < 16 { pic_unmask(irq) },
        IrqMethod::Apic => ioapic_unmask(irq),
    }
}
/// Sends an end-of-interrupt, so that the interrupt controller can go on to the next one.
pub unsafe fn eoi(irq: u8) {
    match irq_method() {
        IrqMethod::Pic => if irq < 16 { pic_eoi(irq) },
        IrqMethod::Apic => lapic_eoi(),
    }
}

unsafe fn pic_mask(irq: u8) {
    debug_assert!(irq < 16);

    if irq >= 8 {
        pic::SLAVE.mask_set(irq - 8);
    } else {
        pic::MASTER.mask_set(irq);
    }
}

unsafe fn ioapic_mask(irq: u8) {
    ioapic::mask(irq);
}

unsafe fn pic_eoi(irq: u8) {
    debug_assert!(irq < 16);

    if irq >= 8 {
        pic::MASTER.ack();
        pic::SLAVE.ack();
    } else {
        pic::MASTER.ack();
    }
}
unsafe fn lapic_eoi() {
    local_apic::LOCAL_APIC.eoi()
}

unsafe fn pic_unmask(irq: usize) {
    debug_assert!(irq < 16);

    if irq >= 8 {
        pic::SLAVE.mask_clear(irq as u8 - 8);
    } else {
        pic::MASTER.mask_clear(irq as u8);
    }
}
unsafe fn ioapic_unmask(irq: usize) {
    ioapic::unmask(irq as u8);
}

interrupt_stack!(pit, stack, {
    // Saves CPU time by not sending IRQ event irq_trigger(0);

    const PIT_RATE: u64 = 2_250_286;

    {
        let mut offset = time::OFFSET.lock();
        let sum = offset.1 + PIT_RATE;
        offset.1 = sum % 1_000_000_000;
        offset.0 += sum / 1_000_000_000;
    }

    eoi(0);

    // Wake up other CPUs
    ipi(IpiKind::Pit, IpiTarget::Other);

    // Any better way of doing this?
    timeout::trigger();

    if PIT_TICKS.fetch_add(1, Ordering::SeqCst) >= 10 {
        let _guard = ptrace::set_process_regs(stack);
        let _ = context::switch();
    }
});

interrupt!(keyboard, {
    trigger(1);
    eoi(1);
});

interrupt!(cascade, {
    // No need to do any operations on cascade
    eoi(2);
});

interrupt!(com2, {
    while let Some(c) = COM2.lock().receive() {
        debug_input(c);
    }
    eoi(3);
});

interrupt!(com1, {
    while let Some(c) = COM1.lock().receive() {
        debug_input(c);
    }
    eoi(4);
});

interrupt!(lpt2, {
    eoi(5);
    trigger(5);
});

interrupt!(floppy, {
    eoi(6);
    trigger(6);
});

interrupt!(lpt1, {
    eoi(7);
    trigger(7);
});

interrupt!(rtc, {
    eoi(8);
    trigger(8);
});

interrupt!(pci1, {
    eoi(9);
    trigger(9);
});

interrupt!(pci2, {
    eoi(10);
    trigger(10);
});

interrupt!(pci3, {
    eoi(11);
    trigger(11);
});

interrupt!(mouse, {
    eoi(12);
    trigger(12);
});

interrupt!(fpu, {
    eoi(13);
    trigger(13);
});

interrupt!(ata1, {
    eoi(14);
    trigger(14);
});

interrupt!(ata2, {
    eoi(15);
    trigger(15);
});
interrupt!(lapic_timer, {
    println!("Local apic timer interrupt");
    lapic_eoi();
});
interrupt!(lapic_error, {
    println!("Local apic internal error: ESR={:#0x}", local_apic::LOCAL_APIC.esr());
    lapic_eoi();
});
interrupt!(calib_pit, {
    const PIT_RATE: u64 = 2_250_286;

    {
        let mut offset = time::OFFSET.lock();
        let sum = offset.1 + PIT_RATE;
        offset.1 = sum % 1_000_000_000;
        offset.0 += sum / 1_000_000_000;
    }

    eoi(0);
});
// XXX: This would look way prettier using const generics.

macro_rules! allocatable_irq(
    ( $number:literal, $name:ident ) => {
        interrupt!($name, {
            allocatable_irq_generic($number);
        });
    }
);

pub unsafe fn allocatable_irq_generic(number: u8) {
    irq_trigger(number - 32);
    lapic_eoi();
}

define_default_irqs!();
<commit_msg>Fix order of masking IRQ and eoi<commit_after>use core::sync::atomic::{AtomicUsize, Ordering};

use crate::context::timeout;
use crate::device::{local_apic, ioapic, pic};
use crate::device::serial::{COM1, COM2};
use crate::ipi::{ipi, IpiKind, IpiTarget};
use crate::scheme::debug::debug_input;
use crate::{context, ptrace, time};

//resets to 0 in context::switch()
#[thread_local]
pub static PIT_TICKS: AtomicUsize = AtomicUsize::new(0);

#[repr(u8)]
pub enum IrqMethod {
    Pic = 0,
    Apic = 1,
}

static IRQ_METHOD: AtomicUsize = AtomicUsize::new(IrqMethod::Pic as usize);

pub fn set_irq_method(method: IrqMethod) {
    IRQ_METHOD.store(method as usize, core::sync::atomic::Ordering::Release);
}

fn irq_method() -> IrqMethod {
    let raw = IRQ_METHOD.load(core::sync::atomic::Ordering::Acquire);

    match raw {
        0 => IrqMethod::Pic,
        1 => IrqMethod::Apic,
        _ => unreachable!(),
    }
}

extern {
    // triggers irq scheme
    fn irq_trigger(irq: u8);
}

/// Notify the IRQ scheme that an IRQ has been registered. This should mask the IRQ until the
/// scheme user unmasks it ("acknowledges" it).
unsafe fn trigger(irq: u8) {
    match irq_method() {
        IrqMethod::Pic => if irq < 16 { pic_mask(irq) },
        IrqMethod::Apic => ioapic_mask(irq),
    }
    irq_trigger(irq);
}

/// Unmask the IRQ. This is called from the IRQ scheme, which does this when a user process has
/// processed the IRQ.
pub unsafe fn acknowledge(irq: usize) {
    match irq_method() {
        IrqMethod::Pic => if irq < 16 { pic_unmask(irq) },
        IrqMethod::Apic => ioapic_unmask(irq),
    }
}

/// Sends an end-of-interrupt, so that the interrupt controller can go on to the next one.
pub unsafe fn eoi(irq: u8) {
    match irq_method() {
        IrqMethod::Pic => if irq < 16 { pic_eoi(irq) },
        IrqMethod::Apic => lapic_eoi(),
    }
}

unsafe fn pic_mask(irq: u8) {
    debug_assert!(irq < 16);

    if irq >= 8 {
        pic::SLAVE.mask_set(irq - 8);
    } else {
        pic::MASTER.mask_set(irq);
    }
}

unsafe fn ioapic_mask(irq: u8) {
    ioapic::mask(irq);
}

unsafe fn pic_eoi(irq: u8) {
    debug_assert!(irq < 16);

    if irq >= 8 {
        pic::MASTER.ack();
        if irq == 15 {
            //TODO: check spurious
            return;
        }
        pic::SLAVE.ack();
    } else {
        if irq == 7 {
            //TODO: check spurious
            return;
        }
        pic::MASTER.ack();
    }
}

unsafe fn lapic_eoi() {
    local_apic::LOCAL_APIC.eoi()
}

unsafe fn pic_unmask(irq: usize) {
    debug_assert!(irq < 16);

    if irq >= 8 {
        pic::SLAVE.mask_clear(irq as u8 - 8);
    } else {
        pic::MASTER.mask_clear(irq as u8);
    }
}

unsafe fn ioapic_unmask(irq: usize) {
    ioapic::unmask(irq as u8);
}

interrupt_stack!(pit, stack, {
    // Saves CPU time by not sending IRQ event irq_trigger(0);

    const PIT_RATE: u64 = 2_250_286;

    {
        let mut offset = time::OFFSET.lock();
        let sum = offset.1 + PIT_RATE;
        offset.1 = sum % 1_000_000_000;
        offset.0 += sum / 1_000_000_000;
    }

    eoi(0);

    // Wake up other CPUs
    ipi(IpiKind::Pit, IpiTarget::Other);

    // Any better way of doing this?
    timeout::trigger();

    if PIT_TICKS.fetch_add(1, Ordering::SeqCst) >= 10 {
        let _guard = ptrace::set_process_regs(stack);
        let _ = context::switch();
    }
});

interrupt!(keyboard, {
    trigger(1);
    eoi(1);
});

interrupt!(cascade, {
    // No need to do any operations on cascade
    eoi(2);
});

interrupt!(com2, {
    while let Some(c) = COM2.lock().receive() {
        debug_input(c);
    }
    eoi(3);
});

interrupt!(com1, {
    while let Some(c) = COM1.lock().receive() {
        debug_input(c);
    }
    eoi(4);
});

interrupt!(lpt2, {
    trigger(5);
    eoi(5);
});

interrupt!(floppy, {
    trigger(6);
    eoi(6);
});

interrupt!(lpt1, {
    trigger(7);
    eoi(7);
});

interrupt!(rtc, {
    trigger(8);
    eoi(8);
});

interrupt!(pci1, {
    trigger(9);
    eoi(9);
});

interrupt!(pci2, {
    trigger(10);
    eoi(10);
});

interrupt!(pci3, {
    trigger(11);
    eoi(11);
});

interrupt!(mouse, {
    trigger(12);
    eoi(12);
});

interrupt!(fpu, {
    trigger(13);
    eoi(13);
});

interrupt!(ata1, {
    trigger(14);
    eoi(14);
});

interrupt!(ata2, {
    trigger(15);
    eoi(15);
});

interrupt!(lapic_timer, {
    println!("Local apic timer interrupt");
    lapic_eoi();
});

interrupt!(lapic_error, {
    println!("Local apic internal error: ESR={:#0x}", local_apic::LOCAL_APIC.esr());
    lapic_eoi();
});

interrupt!(calib_pit, {
    const PIT_RATE: u64 = 2_250_286;

    {
        let mut offset = time::OFFSET.lock();
        let sum = offset.1 + PIT_RATE;
        offset.1 = sum % 1_000_000_000;
        offset.0 += sum / 1_000_000_000;
    }

    eoi(0);
});
// XXX: This would look way prettier using const generics.

macro_rules! allocatable_irq(
    ( $number:literal, $name:ident ) => {
        interrupt!($name, {
            allocatable_irq_generic($number);
        });
    }
);

pub unsafe fn allocatable_irq_generic(number: u8) {
    irq_trigger(number - 32);
    lapic_eoi();
}

define_default_irqs!();
<|endoftext|>


<commit_before>use std::panic;
use webcore::ffi;

/// Initializes the library.
///
/// Necessary **only** when compiling **without** `cargo-web`.
#[inline(never)]
#[cold]
pub fn initialize() {
    static mut INITIALIZED: bool = false;
    unsafe {
        if INITIALIZED {
            return;
        }

        INITIALIZED = true;
    }

    include!( concat!( env!( "OUT_DIR" ), "/runtime.rs" ) );

    if cfg!( test ) == false {
        panic::set_hook( Box::new( |info| {
            __js_raw_asm!( "console.error( 'Encountered a panic!' );" );
            if let Some( value ) = info.payload().downcast_ref::< String >() {
                __js_raw_asm!( "\
                    console.error( 'Panic error message:', Module.STDWEB.to_js_string( $0, $1 ) );\
                ", value.as_ptr(), value.len() );
            }
            if let Some( location ) = info.location() {
                let file = location.file();
                __js_raw_asm!( "\
                    console.error( 'Panic location:', Module.STDWEB.to_js_string( $0, $1 ) + ':' + $2 );\
                ", file.as_ptr(), file.len(), location.line() );
            }
        }));
    }
}

/// Runs the event loop.
///
/// You should call this before returning from `main()`,
/// otherwise bad things will happen.
///
/// On Emscripten-based targets (`asmjs-unknown-emscripten`,
/// `wasm32-unknown-emscripten`) calling this is **mandatory**
/// and will **not** return. (It is, effectively, an infinite loop.)
///
/// On Rust's native wasm target (`wasm32-unknown-unknown`)
/// calling this is not necessary and doesn't do anything.
pub fn event_loop() {
    ffi::event_loop();
}
<commit_msg>Update documentation for the `event_loop` function<commit_after>use std::panic;
use webcore::ffi;

/// Initializes the library.
///
/// Necessary **only** when compiling **without** `cargo-web`.
#[inline(never)]
#[cold]
pub fn initialize() {
    static mut INITIALIZED: bool = false;
    unsafe {
        if INITIALIZED {
            return;
        }

        INITIALIZED = true;
    }

    include!( concat!( env!( "OUT_DIR" ), "/runtime.rs" ) );

    if cfg!( test ) == false {
        panic::set_hook( Box::new( |info| {
            __js_raw_asm!( "console.error( 'Encountered a panic!' );" );
            if let Some( value ) = info.payload().downcast_ref::< String >() {
                __js_raw_asm!( "\
                    console.error( 'Panic error message:', Module.STDWEB.to_js_string( $0, $1 ) );\
                ", value.as_ptr(), value.len() );
            }
            if let Some( location ) = info.location() {
                let file = location.file();
                __js_raw_asm!( "\
                    console.error( 'Panic location:', Module.STDWEB.to_js_string( $0, $1 ) + ':' + $2 );\
                ", file.as_ptr(), file.len(), location.line() );
            }
        }));
    }
}

/// Runs Emscripten's event loop.
///
/// If you're compiling your project **without** using `cargo-web`
/// **and** you're using an Emscripten-based target (`asmjs-unknown-emscripten`,
/// or `wasm32-unknown-emscripten`) then calling this before returning
/// from `main()` is **mandatory** and will **not** return. (It is, effectively, an infinite loop.)
///
/// If you're using `cargo-web` to build your project then you never need to call this.
pub fn event_loop() {
    ffi::event_loop();
}
<|endoftext|>


<commit_before>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use std::f64::consts::PI;
use intersect::lines_intersect;

fn to_cartesian(theta: f64, r: f64) -> (f64, f64) {
    return (
        theta.sin()*r,
        -theta.cos()*r,
    )
}

pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [
    [5.0, 7.0],
    [-5.0, 7.0],
    [0.0, -13.0],
];

impl Spaceship {
    pub fn new() -> Spaceship {
        return Spaceship{
            x: 100.0,
            y: 100.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&mut self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(
            &SPACESHIP_POINTS,
            ds,
            t
                .trans(self.x, self.y)
                .rot_rad(self.theta),
            gl,
        );
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let (dx, dy) = to_cartesian(self.v_theta, self.v*dt);
        self.x = (self.x + dx + x_max) % x_max;
        self.y = (self.y + dy + y_max) % y_max;
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse)*dt*100.0;
        let (dx, dy) = to_cartesian(self.v_theta, self.v);
        let (ddx, ddy) = to_cartesian(self.theta, net_accel);
        let new_dx = dx + ddx;
        let new_dy = dy + ddy;
        self.v = (new_dx*new_dx+new_dy*new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left)*dt*100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }
}

pub struct Bullet {
    x: f64,
    y: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet{
            x: x,
            y: y,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let v = 100.0;
        self.x = (self.x + self.theta.sin()*v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*v*dt + y_max) % y_max;
        self.distance += v*dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }
}

pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    border: Vec<[f64; 4]>,
}

impl Astroid {
    pub fn new<R: Rng>(rng: &mut R) -> Astroid {
        let radius = (rng.gen_range(1, 3)*5) as f64;
        return Astroid {
            x: rng.gen_range(0.0, 100.0),
            y: rng.gen_range(0.0, 100.0),
            v: rng.gen_range(40.0, 60.0),
            theta: rng.gen_range(0.0, 2.0*PI),
            border: Astroid::create_border(rng, radius),
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.theta.sin()*self.v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*self.v*dt + y_max) % y_max;
    }

    pub fn create_border<R: Rng>(rng: &mut R, radius: f64) -> Vec<[f64; 4]> {
        let spread = radius/5.0;
        let point_count = rng.gen_range(8, 12);
        let mut points = Vec::with_capacity(point_count);
        let theta_0 = rng.gen_range(0.0, 2.0*PI);
        for theta in (1..point_count+1).map(|i| theta_0 + 2.0*PI*i as f64/point_count as f64) {
            let distance = radius + rng.gen_range(-spread, spread);
            points.push(to_cartesian(theta, distance));
        };
        let point = points[0];
        points.push(point);
        let mut lines = Vec::with_capacity(point_count);
        for point in points.iter().zip(points.iter().skip(1)) {
            let (&(x1, x2), &(y1, y2)) = point;
            lines.push([x1, x2, y1, y2]);
        }
        return lines;
    }

    pub fn is_collision(&self, bullet_path: [f64; 4]) -> bool {
        return false;
    }
}<commit_msg>Added code to get the edges of objects<commit_after>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use std::f64::consts::PI;
use intersect::lines_intersect;

fn to_cartesian(theta: f64, r: f64) -> (f64, f64) {
    return (
        theta.sin()*r,
        -theta.cos()*r,
    )
}

pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [
    [5.0, 7.0],
    [-5.0, 7.0],
    [0.0, -13.0],
];

impl Spaceship {
    pub fn new() -> Spaceship {
        return Spaceship{
            x: 100.0,
            y: 100.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&mut self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(
            &SPACESHIP_POINTS,
            ds,
            t
                .trans(self.x, self.y)
                .rot_rad(self.theta),
            gl,
        );
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let (dx, dy) = to_cartesian(self.v_theta, self.v*dt);
        self.x = (self.x + dx + x_max) % x_max;
        self.y = (self.y + dy + y_max) % y_max;
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse)*dt*100.0;
        let (dx, dy) = to_cartesian(self.v_theta, self.v);
        let (ddx, ddy) = to_cartesian(self.theta, net_accel);
        let new_dx = dx + ddx;
        let new_dy = dy + ddy;
        self.v = (new_dx*new_dx+new_dy*new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left)*dt*100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }

    pub fn edges(&self) -> Vec<[f64; 4]> {
        return SPACESHIP_POINTS.iter().map(|edge|
            [edge[0] + self.x, edge[1] + self.y, edge[2] + self.x, edge[3] + self.y]
        ).collect();
    }
}

pub struct Bullet {
    x: f64,
    y: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet{
            x: x,
            y: y,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let v = 100.0;
        self.x = (self.x + self.theta.sin()*v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*v*dt + y_max) % y_max;
        self.distance += v*dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }
}

pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    border: Vec<[f64; 4]>,
}

use std::iter::Map;
use std::slice::Iter;

impl Astroid {
    pub fn new<R: Rng>(rng: &mut R) -> Astroid {
        let radius = (rng.gen_range(1, 3)*5) as f64;
        return Astroid {
            x: rng.gen_range(0.0, 100.0),
            y: rng.gen_range(0.0, 100.0),
            v: rng.gen_range(40.0, 60.0),
            theta: rng.gen_range(0.0, 2.0*PI),
            border: Astroid::create_border(rng, radius),
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.theta.sin()*self.v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*self.v*dt + y_max) % y_max;
    }

    pub fn create_border<R: Rng>(rng: &mut R, radius: f64) -> Vec<[f64; 4]> {
        let spread = radius/5.0;
        let point_count = rng.gen_range(8, 12);
        let mut points = Vec::with_capacity(point_count);
        let theta_0 = rng.gen_range(0.0, 2.0*PI);
        for theta in (1..point_count+1).map(|i| theta_0 + 2.0*PI*i as f64/point_count as f64) {
            let distance = radius + rng.gen_range(-spread, spread);
            points.push(to_cartesian(theta, distance));
        };
        let point = points[0];
        points.push(point);
        let mut lines = Vec::with_capacity(point_count);
        for point in points.iter().zip(points.iter().skip(1)) {
            let (&(x1, x2), &(y1, y2)) = point;
            lines.push([x1, x2, y1, y2]);
        }
        return lines;
    }

    pub fn edges(&self) -> Vec<[f64; 4]> {
        return self.border.iter().map(|edge|
            [edge[0] + self.x, edge[1] + self.y, edge[2] + self.x, edge[3] + self.y]
        ).collect();
    }

    pub fn is_collision(&self, bullet_path: [f64; 4]) -> bool {
        return false;
    }
}<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate extra;

use std::env;
use std::fs;
use std::io::{stderr, stdout, Write};
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{mv} */ r#"
NAME
    mv - move files

SYNOPSIS
    mv [ -h | --help ] SOURCE_FILE DESTINATION_FILE

DESCRIPTION
    The mv utility renames the file named by the SOURCE_FILE operand to the destination path named by the DESTINATION_FILE operand.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();

    if env::args().count() == 2 {
        if let Some(arg) = env::args().nth(1) {
            if arg == "--help" || arg == "-h" {
                stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
                stdout.flush().try(&mut stderr);
                return;
            }
        }
    }

    let ref src = env::args().nth(1).fail("No source argument. Use --help to see the usage.", &mut stderr);
    let ref dst = env::args().nth(2).fail("No destination argument. Use --help to see the usage.", &mut stderr);

    fs::rename(src, dst).try(&mut stderr);
}
<commit_msg>Update mv.rs with `ArgParser`<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::fs;
use std::io::{stderr, stdout, Write};
use std::process::exit;
use coreutils::{ArgParser, Flag};
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{mv} */ r#"
NAME
    mv - move files

SYNOPSIS
    mv [ -h | --help ] SOURCE_FILE DESTINATION_FILE

DESCRIPTION
    The mv utility renames the file named by the SOURCE_FILE operand to the destination path named by the DESTINATION_FILE operand.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag("h", "help");
    parser.initialize(env::args());

    if parser.enabled_flag(Flag::Long("help")) {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    let ref src = parser.args.get(1).fail("No source argument. Use --help to see the usage.", &mut stderr);
    let ref dst = parser.args.get(2).fail("No destination argument. Use --help to see the usage.", &mut stderr);

    fs::rename(src, dst).try(&mut stderr);
}
<|endoftext|>


<commit_before>use std::iter::IntoIterator;

pub struct FilteredCollectionIterator<'a, I>
    where I: Iterator,
{
    iter_wrapped: I,
    iter_bitmap: ::std::slice::Iter<'a, bool>,
}

#[derive(Debug)]
pub struct FilteredCollection<'a, A>
    where &'a A: IntoIterator,
          A: 'a,
{
    // Test ref or Rc
    wrapped: &'a A,
    bitmap: Vec<bool>,
    valid_items: usize
}

impl<'a, A> FilteredCollection<'a, A>
    where &'a A: IntoIterator,
          A: 'a,
{

    pub fn new(wrapped: &'a A, len: usize) -> Self {
        Self {
            wrapped,
            bitmap: vec![true; len],
            valid_items: len,
        }
    }

    pub fn iter(&'a self) -> FilteredCollectionIterator<'a, <&'a A as IntoIterator>::IntoIter> {
        FilteredCollectionIterator {
            iter_wrapped: self.wrapped.into_iter(),
            iter_bitmap: self.bitmap.iter(),
        }
    }

    pub fn iter_mut(&'a mut self) -> ::std::slice::Iter<'a, ()> {
        panic!("Not yet implemented")
    }

    pub fn len(&'a self) -> usize {
        self.valid_items
    }

    pub fn is_empty(&self) -> bool {
        self.valid_items == 0
    }

    pub fn retain<F>(&mut self, mut f: F)
        where F: FnMut(&<&'a A as IntoIterator>::Item) -> bool,
    {
        for (valid, item) in self.bitmap.iter_mut().zip(self.wrapped.into_iter()) {
            if *valid {
                *valid = f(&item);
                if !*valid {
                    self.valid_items -= 1;
                }
            }
        }
    }

}

impl<'a, I> Iterator for FilteredCollectionIterator<'a, I>
    where I: Iterator,
{
    type Item = I::Item;
    fn next(&mut self) -> Option<Self::Item> {
        let mut valid = self.iter_bitmap.next();
        let mut item = self.iter_wrapped.next();
        while item.is_some() {
            if let Some(valid) = valid {
                if *valid {
                    return Some(item.expect("is_some wrong!"))
                }
            } else {
                panic!("Bitmap iterator ended prematurely!");
            }
            valid = self.iter_bitmap.next();
            item = self.iter_wrapped.next();
        }
        None
    }
}
<commit_msg>columnar/bitmap: Stop yielding elements if bitmap is exhausted<commit_after>use std::iter::IntoIterator;

pub struct FilteredCollectionIterator<'a, I>
    where I: Iterator,
{
    iter_wrapped: I,
    iter_bitmap: ::std::slice::Iter<'a, bool>,
}

#[derive(Debug)]
pub struct FilteredCollection<'a, A>
    where &'a A: IntoIterator,
          A: 'a,
{
    // Test ref or Rc
    wrapped: &'a A,
    bitmap: Vec<bool>,
    valid_items: usize
}

impl<'a, A> FilteredCollection<'a, A>
    where &'a A: IntoIterator,
          A: 'a,
{

    pub fn new(wrapped: &'a A, len: usize) -> Self {
        Self {
            wrapped,
            bitmap: vec![true; len],
            valid_items: len,
        }
    }

    pub fn iter(&'a self) -> FilteredCollectionIterator<'a, <&'a A as IntoIterator>::IntoIter> {
        FilteredCollectionIterator {
            iter_wrapped: self.wrapped.into_iter(),
            iter_bitmap: self.bitmap.iter(),
        }
    }

    pub fn iter_mut(&'a mut self) -> ::std::slice::Iter<'a, ()> {
        panic!("Not yet implemented")
    }

    pub fn len(&'a self) -> usize {
        self.valid_items
    }

    pub fn is_empty(&self) -> bool {
        self.valid_items == 0
    }

    pub fn retain<F>(&mut self, mut f: F)
        where F: FnMut(&<&'a A as IntoIterator>::Item) -> bool,
    {
        for (valid, item) in self.bitmap.iter_mut().zip(self.wrapped.into_iter()) {
            if *valid {
                *valid = f(&item);
                if !*valid {
                    self.valid_items -= 1;
                }
            }
        }
    }

}

impl<'a, I> Iterator for FilteredCollectionIterator<'a, I>
    where I: Iterator,
{
    type Item = I::Item;
    fn next(&mut self) -> Option<Self::Item> {
        let mut valid = self.iter_bitmap.next();
        let mut item = self.iter_wrapped.next();
        while item.is_some() {
            if let Some(valid) = valid {
                if *valid {
                    return Some(item.expect("is_some wrong!"));
                }
            } else {
                // TODO: panicing here is bad because it might happen much later
                // than when the problem really happened, i.e. when creating
                // a FilteredCollection.
                // panic!("Bitmap iterator ended prematurely!");
                return None;
            }
            valid = self.iter_bitmap.next();
            item = self.iter_wrapped.next();
        }
        None
    }
}
<|endoftext|>


<commit_before>use error;
use reqwest;
use reqwest::header;
use serde_json;
use serde_urlencoded;
use std::env;
use std::fmt;
use std::io::Read;

const API_BASE_PATH: &str = "http://proxer.me/api/v1/";

/// Client that holds the api key and sends requests
#[derive(Debug, Clone)]
pub struct Client {
	api_key: String,
	base_uri: String,
	user_agent: String,
}

#[allow(unused)]
impl Client {
	/// Create a new api client
	pub fn new(api_key: String) -> Self
	{
		let crates_name = env::var("CARGO_PKG_NAME").unwrap_or("unknown".to_string());

		let crates_version = &env::var("CARGO_PKG_VERSION").unwrap_or("unknown".to_string());

		let ua = format!("libproxer-rust({}/v{})", crates_name, crates_version);

		Self {
			api_key: api_key,
			base_uri: API_BASE_PATH.to_string(),
			user_agent: ua,
		}
	}

	pub fn with_env_key(env_key: &str) -> Option<Client>
	{
		match env::var_os(env_key)
		{
			Some(r) => Some(Client::new(r.into_string().unwrap())),
			None => None,
		}
	}

	/// execute a request that satisfies [Request](../trait.Request.html)
	pub fn execute<'a, T: super::Endpoint + Clone + fmt::Debug>(
		&self,
		mut endpoint: T,
	) -> Result<T::ResponseType, error::Error>
	{

		let uristring = self.base_uri.to_string() + T::URL;

		header!{(ProxerApiKey, "Proxer-Api-Key") => [String]}

		let mut headers = reqwest::header::Headers::new();

		headers.set(header::UserAgent::new(self.user_agent.to_string()));
		headers.set(header::Host::new("proxer.me", None));
		headers.set(header::ContentType::form_url_encoded());
		headers.set(ProxerApiKey(self.api_key.clone()));

		let mut http_req = reqwest::Request::new(reqwest::Method::Post, uristring.parse().unwrap());

		// add our headers to the request
		http_req.headers_mut().extend(headers.iter());

		match serde_urlencoded::to_string(endpoint.clone())
		{
			Ok(body) => {
				debug!("post data: {}", body);
				*http_req.body_mut() = Some(body.into());
			}
			Err(err) => panic!("can't serialize form parameters"),
		}

		let client = reqwest::Client::new();

		let response = client.execute(http_req);

		// This section needs some rewriting. maybe... later
		match response
		{
			Err(e) => return Err(error::Error::Http),
			Ok(mut res) => {
				let mut json_string = String::new();
				res.read_to_string(&mut json_string);

				// println!("{}", json_string);
				//
				// let value: Value = serde_json::from_str(&json_string).unwrap();
				// println!("{:#?}", value);

				match serde_json::from_str::<ApiResponse<T::ResponseType>>(&json_string)
				{
					Err(e) => return Err(error::Error::Json(e)),
					Ok(r) => {
						if r.error != 0 {
							Err(error::Error::Api(error::api::Api::new(r.code.unwrap(), r.message)))
						}
						else {
							Ok(r.data.unwrap())
						}
					}
				}
			}
		}
	}
}

/// responses are parsed into ApiRequest
#[derive(Debug, Clone, Deserialize)]
pub struct ApiResponse<T> {
	/// api error
	pub error: i64,
	/// api message
	pub message: String,
	/// actual data
	pub data: Option<T>,
	/// optional error code
	/// in case of an error this contains the error code
	pub code: Option<i64>,
}
<commit_msg>remove unused lifetime<commit_after>use error;
use reqwest;
use reqwest::header;
use serde_json;
use serde_urlencoded;
use std::env;
use std::fmt;
use std::io::Read;

const API_BASE_PATH: &str = "http://proxer.me/api/v1/";

/// Client that holds the api key and sends requests
#[derive(Debug, Clone)]
pub struct Client {
	api_key: String,
	base_uri: String,
	user_agent: String,
}

#[allow(unused)]
impl Client {
	/// Create a new api client with a given api key
	pub fn new(api_key: String) -> Self
	{
		let crates_name = env::var("CARGO_PKG_NAME").unwrap_or("unknown".to_string());

		let crates_version = &env::var("CARGO_PKG_VERSION").unwrap_or("unknown".to_string());

		let ua = format!("libproxer-rust({}/v{})", crates_name, crates_version);

		Self {
			api_key: api_key,
			base_uri: API_BASE_PATH.to_string(),
			user_agent: ua,
		}
	}

	/// load api key from an environment variable
	pub fn with_env_key(env_key: &str) -> Option<Client>
	{
		match env::var_os(env_key)
		{
			Some(r) => Some(Client::new(r.into_string().unwrap())),
			None => None,
		}
	}

	/// execute a request that satisfies [`Endpoint`](../trait.Endpoint.html)
	pub fn execute<T: super::Endpoint + Clone + fmt::Debug>(
		&self,
		mut endpoint: T,
	) -> Result<T::ResponseType, error::Error>
	{

		let uristring = self.base_uri.to_string() + T::URL;

		header!{(ProxerApiKey, "Proxer-Api-Key") => [String]}

		let mut headers = reqwest::header::Headers::new();

		headers.set(header::UserAgent::new(self.user_agent.to_string()));
		headers.set(header::Host::new("proxer.me", None));
		headers.set(header::ContentType::form_url_encoded());
		headers.set(ProxerApiKey(self.api_key.clone()));

		let mut http_req = reqwest::Request::new(reqwest::Method::Post, uristring.parse().unwrap());

		// add our headers to the request
		http_req.headers_mut().extend(headers.iter());

		match serde_urlencoded::to_string(endpoint.clone())
		{
			Ok(body) => {
				debug!("post data: {}", body);
				*http_req.body_mut() = Some(body.into());
			}
			Err(err) => panic!("can't serialize form parameters"),
		}

		let client = reqwest::Client::new();

		let response = client.execute(http_req);

		// This section needs some rewriting. maybe... later
		match response
		{
			Err(e) => return Err(error::Error::Http),
			Ok(mut res) => {
				let mut json_string = String::new();
				res.read_to_string(&mut json_string);

				// println!("{}", json_string);
				//
				// let value: Value = serde_json::from_str(&json_string).unwrap();
				// println!("{:#?}", value);

				match serde_json::from_str::<ApiResponse<T::ResponseType>>(&json_string)
				{
					Err(e) => return Err(error::Error::Json(e)),
					Ok(r) => {
						if r.error != 0 {
							Err(error::Error::Api(error::api::Api::new(r.code.unwrap(), r.message)))
						}
						else {
							Ok(r.data.unwrap())
						}
					}
				}
			}
		}
	}
}

/// responses are parsed into ApiRequest
#[derive(Debug, Clone, Deserialize)]
pub struct ApiResponse<T> {
	/// api error
	pub error: i64,
	/// api message
	pub message: String,
	/// actual data
	pub data: Option<T>,
	/// optional error code
	/// in case of an error this contains the error code
	pub code: Option<i64>,
}
<|endoftext|>


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

extern crate toml;

use file_lines::FileLines;
use lists::{SeparatorTactic, ListTactic};

macro_rules! configuration_option_enum{
    ($e:ident: $( $x:ident ),+ $(,)*) => {
        #[derive(Copy, Clone, Eq, PartialEq, Debug)]
        pub enum $e {
            $( $x ),+
        }

        impl_enum_decodable!($e, $( $x ),+);
    }
}

configuration_option_enum! { Style:
    Rfc, // Follow the style RFCs style.
    Default, // Follow the traditional Rustfmt style.
}

configuration_option_enum! { NewlineStyle:
    Windows, // \r\n
    Unix, // \n
    Native, // \r\n in Windows, \n on other platforms
}

configuration_option_enum! { BraceStyle:
    AlwaysNextLine,
    PreferSameLine,
    // Prefer same line except where there is a where clause, in which case force
    // the brace to the next line.
    SameLineWhere,
}

configuration_option_enum! { ControlBraceStyle:
    // K&R style, Rust community default
    AlwaysSameLine,
    // Stroustrup style
    ClosingNextLine,
    // Allman style
    AlwaysNextLine,
}

// How to indent a function's return type.
configuration_option_enum! { ReturnIndent:
    // Aligned with the arguments
    WithArgs,
    // Aligned with the where clause
    WithWhereClause,
}

configuration_option_enum! { IndentStyle:
    // First line on the same line as the opening brace, all lines aligned with
    // the first line.
    Visual,
    // First line is on a new line and all lines align with block indent.
    Block,
}

configuration_option_enum! { Density:
    // Fit as much on one line as possible.
    Compressed,
    // Use more lines.
    Tall,
    // Try to compress if the body is empty.
    CompressedIfEmpty,
    // Place every item on a separate line.
    Vertical,
}

configuration_option_enum! { TypeDensity:
    // No spaces around "=" and "+"
    Compressed,
    // Spaces around " = " and " + "
    Wide,
}

impl Density {
    pub fn to_list_tactic(self) -> ListTactic {
        match self {
            Density::Compressed => ListTactic::Mixed,
            Density::Tall |
            Density::CompressedIfEmpty => ListTactic::HorizontalVertical,
            Density::Vertical => ListTactic::Vertical,
        }
    }
}

configuration_option_enum! { LicensePolicy:
    // Do not place license text at top of files
    NoLicense,
    // Use the text in "license" field as the license
    TextLicense,
    // Use a text file as the license text
    FileLicense,
}

configuration_option_enum! { MultilineStyle:
    // Use horizontal layout if it fits in one line, fall back to vertical
    PreferSingle,
    // Use vertical layout
    ForceMulti,
}

impl MultilineStyle {
    pub fn to_list_tactic(self) -> ListTactic {
        match self {
            MultilineStyle::PreferSingle => ListTactic::HorizontalVertical,
            MultilineStyle::ForceMulti => ListTactic::Vertical,
        }
    }
}

configuration_option_enum! { ReportTactic:
    Always,
    Unnumbered,
    Never,
}

configuration_option_enum! { WriteMode:
    // Backs the original file up and overwrites the original.
    Replace,
    // Overwrites original file without backup.
    Overwrite,
    // Writes the output to stdout.
    Display,
    // Writes the diff to stdout.
    Diff,
    // Displays how much of the input file was processed
    Coverage,
    // Unfancy stdout
    Plain,
    // Outputs a checkstyle XML file.
    Checkstyle,
}

/// Trait for types that can be used in `Config`.
pub trait ConfigType: Sized {
    /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a
    /// pipe-separated list of variants; for other types it returns "<type>".
    fn doc_hint() -> String;
}

impl ConfigType for bool {
    fn doc_hint() -> String {
        String::from("<boolean>")
    }
}

impl ConfigType for usize {
    fn doc_hint() -> String {
        String::from("<unsigned integer>")
    }
}

impl ConfigType for isize {
    fn doc_hint() -> String {
        String::from("<signed integer>")
    }
}

impl ConfigType for String {
    fn doc_hint() -> String {
        String::from("<string>")
    }
}

impl ConfigType for FileLines {
    fn doc_hint() -> String {
        String::from("<json>")
    }
}

pub struct ConfigHelpItem {
    option_name: &'static str,
    doc_string: &'static str,
    variant_names: String,
    default: &'static str,
}

impl ConfigHelpItem {
    pub fn option_name(&self) -> &'static str {
        self.option_name
    }

    pub fn doc_string(&self) -> &'static str {
        self.doc_string
    }

    pub fn variant_names(&self) -> &String {
        &self.variant_names
    }

    pub fn default(&self) -> &'static str {
        self.default
    }
}

macro_rules! create_config {
    ($($i:ident: $ty:ty, $def:expr, $( $dstring:expr ),+ );+ $(;)*) => (
        #[derive(Deserialize, Clone)]
        pub struct Config {
            $(pub $i: $ty),+
        }

        // Just like the Config struct but with each property wrapped
        // as Option<T>. This is used to parse a rustfmt.toml that doesn't
        // specity all properties of `Config`.
        // We first parse into `ParsedConfig`, then create a default `Config`
        // and overwrite the properties with corresponding values from `ParsedConfig`
        #[derive(Deserialize, Clone)]
        pub struct ParsedConfig {
            $(pub $i: Option<$ty>),+
        }

        impl Config {

            fn fill_from_parsed_config(mut self, parsed: ParsedConfig) -> Config {
            $(
                if let Some(val) = parsed.$i {
                    self.$i = val;
                }
            )+
                self
            }

            pub fn from_toml(toml: &str) -> Result<Config, String> {
                let parsed: toml::Value =
                    toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?;
                let mut err: String = String::new();
                {
                    let table = parsed
                        .as_table()
                        .ok_or(String::from("Parsed config was not table"))?;
                    for (key, _) in table {
                        match &**key {
                            $(
                                stringify!($i) => (),
                            )+
                                _ => {
                                    let msg =
                                        &format!("Warning: Unknown configuration option `{}`\n",
                                                 key);
                                    err.push_str(msg)
                                }
                        }
                    }
                }
                match parsed.try_into() {
                    Ok(parsed_config) =>
                        Ok(Config::default().fill_from_parsed_config(parsed_config)),
                    Err(_) => {
                        err.push_str("Error: Decoding config file failed. ");
                        err.push_str("Please check your config file.\n");
                        Err(err)
                    }
                }
            }

            pub fn override_value(&mut self, key: &str, val: &str) {
                match key {
                    $(
                        stringify!($i) => {
                            self.$i = val.parse::<$ty>()
                                .expect(&format!("Failed to parse override for {} (\"{}\") as a {}",
                                                 stringify!($i),
                                                 val,
                                                 stringify!($ty)));
                        }
                    )+
                    _ => panic!("Unknown config key in override: {}", key)
                }
            }

            pub fn print_docs() {
                use std::cmp;
                let max = 0;
                $( let max = cmp::max(max, stringify!($i).len()+1); )+
                let mut space_str = String::with_capacity(max);
                for _ in 0..max {
                    space_str.push(' ');
                }
                println!("Configuration Options:");
                $(
                    let name_raw = stringify!($i);
                    let mut name_out = String::with_capacity(max);
                    for _ in name_raw.len()..max-1 {
                        name_out.push(' ')
                    }
                    name_out.push_str(name_raw);
                    name_out.push(' ');
                    println!("{}{} Default: {:?}",
                             name_out,
                             <$ty>::doc_hint(),
                             $def);
                    $(
                        println!("{}{}", space_str, $dstring);
                    )+
                    println!("");
                )+
            }
        }

        // Template for the default configuration
        impl Default for Config {
            fn default() -> Config {
                Config {
                    $(
                        $i: $def,
                    )+
                }
            }
        }
    )
}

create_config! {
    verbose: bool, false, "Use verbose output";
    disable_all_formatting: bool, false, "Don't reformat anything";
    skip_children: bool, false, "Don't reformat out of line modules";
    file_lines: FileLines, FileLines::all(),
        "Lines to format; this is not supported in rustfmt.toml, and can only be specified \
         via the --file-lines option";
    max_width: usize, 100, "Maximum width of each line";
    error_on_line_overflow: bool, true, "Error if unable to get all lines within max_width";
    tab_spaces: usize, 4, "Number of spaces per tab";
    fn_call_width: usize, 60,
        "Maximum width of the args of a function call before falling back to vertical formatting";
    struct_lit_width: usize, 18,
        "Maximum width in the body of a struct lit before falling back to vertical formatting";
    struct_variant_width: usize, 35,
        "Maximum width in the body of a struct variant before falling back to vertical formatting";
    force_explicit_abi: bool, true, "Always print the abi for extern items";
    newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings";
    fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions";
    item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums";
    control_style: Style, Style::Default, "Indent style for control flow statements";
    control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine,
        "Brace style for control flow constructs";
    impl_empty_single_line: bool, true, "Put empty-body implementations on a single line";
    trailing_comma: SeparatorTactic, SeparatorTactic::Vertical,
        "How to handle trailing commas for lists";
    fn_empty_single_line: bool, true, "Put empty-body functions on a single line";
    fn_single_line: bool, false, "Put single-expression functions on a single line";
    fn_return_indent: ReturnIndent, ReturnIndent::WithArgs,
        "Location of return type in function declaration";
    fn_args_paren_newline: bool, true, "If function argument parenthesis goes on a newline";
    fn_args_density: Density, Density::Tall, "Argument density in functions";
    fn_args_layout: IndentStyle, IndentStyle::Visual,
        "Layout of function arguments and tuple structs";
    array_layout: IndentStyle, IndentStyle::Visual, "Indent on arrays";
    array_width: usize, 60,
        "Maximum width of an array literal before falling back to vertical formatting";
    type_punctuation_density: TypeDensity, TypeDensity::Wide,
        "Determines if '+' or '=' are wrapped in spaces in the punctuation of types";
    where_style: Style, Style::Default, "Overall strategy for where clauses";
    // TODO:
    // 1. Should we at least try to put the where clause on the same line as the rest of the
    // function decl?
    // 2. Currently options `Tall` and `Vertical` produce the same output.
    where_density: Density, Density::CompressedIfEmpty, "Density of a where clause";
    where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause";
    where_pred_indent: IndentStyle, IndentStyle::Visual,
        "Indentation style of a where predicate";
    generics_indent: IndentStyle, IndentStyle::Visual, "Indentation of generics";
    struct_lit_style: IndentStyle, IndentStyle::Block, "Style of struct definition";
    struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle,
        "Multiline style on literal structs";
    fn_call_style: IndentStyle, IndentStyle::Visual, "Indentation for function calls, etc.";
    report_todo: ReportTactic, ReportTactic::Never,
        "Report all, none or unnumbered occurrences of TODO in source file comments";
    report_fixme: ReportTactic, ReportTactic::Never,
        "Report all, none or unnumbered occurrences of FIXME in source file comments";
    chain_indent: IndentStyle, IndentStyle::Block, "Indentation of chain";
    chain_one_line_max: usize, 60, "Maximum length of a chain to fit on a single line";
    reorder_imports: bool, false, "Reorder import statements alphabetically";
    reorder_imported_names: bool, false,
        "Reorder lists of names in import statements alphabetically";
    single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \
                                                expressions. A value of zero means always break \
                                                if-else expressions.";
    format_strings: bool, false, "Format string literals where necessary";
    force_format_strings: bool, false, "Always format string literals";
    take_source_hints: bool, false, "Retain some formatting characteristics from the source code";
    hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment";
    wrap_comments: bool, false, "Break comments to fit on the line";
    comment_width: usize, 80, "Maximum length of comments. No effect unless wrap_comments = true";
    normalize_comments: bool, false, "Convert /* */ comments to // comments where possible";
    wrap_match_arms: bool, true, "Wrap multiline match arms in blocks";
    match_block_trailing_comma: bool, false,
        "Put a trailing comma after a block based match arm (non-block arms are not affected)";
    indent_match_arms: bool, true, "Indent match arms instead of keeping them at the same \
                                    indentation level as the match keyword";
    closure_block_indent_threshold: isize, 7, "How many lines a closure must have before it is \
                                               block indented. -1 means never use block indent.";
    space_before_type_annotation: bool, false,
        "Leave a space before the colon in a type annotation";
    space_after_type_annotation_colon: bool, true,
        "Leave a space after the colon in a type annotation";
    space_before_bound: bool, false, "Leave a space before the colon in a trait or lifetime bound";
    space_after_bound_colon: bool, true,
        "Leave a space after the colon in a trait or lifetime bound";
    spaces_around_ranges: bool, false, "Put spaces around the  .. and ... range operators";
    spaces_within_angle_brackets: bool, false, "Put spaces within non-empty generic arguments";
    spaces_within_square_brackets: bool, false, "Put spaces within non-empty square brackets";
    spaces_within_parens: bool, false, "Put spaces within non-empty parentheses";
    use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand";
    write_mode: WriteMode, WriteMode::Replace,
        "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage";
    condense_wildcard_suffices: bool, false, "Replace strings of _ wildcards by a single .. in \
                                              tuple patterns"
}
<commit_msg>add more specific reason why it fails to parse<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate toml;

use file_lines::FileLines;
use lists::{SeparatorTactic, ListTactic};

macro_rules! configuration_option_enum{
    ($e:ident: $( $x:ident ),+ $(,)*) => {
        #[derive(Copy, Clone, Eq, PartialEq, Debug)]
        pub enum $e {
            $( $x ),+
        }

        impl_enum_decodable!($e, $( $x ),+);
    }
}

configuration_option_enum! { Style:
    Rfc, // Follow the style RFCs style.
    Default, // Follow the traditional Rustfmt style.
}

configuration_option_enum! { NewlineStyle:
    Windows, // \r\n
    Unix, // \n
    Native, // \r\n in Windows, \n on other platforms
}

configuration_option_enum! { BraceStyle:
    AlwaysNextLine,
    PreferSameLine,
    // Prefer same line except where there is a where clause, in which case force
    // the brace to the next line.
    SameLineWhere,
}

configuration_option_enum! { ControlBraceStyle:
    // K&R style, Rust community default
    AlwaysSameLine,
    // Stroustrup style
    ClosingNextLine,
    // Allman style
    AlwaysNextLine,
}

// How to indent a function's return type.
configuration_option_enum! { ReturnIndent:
    // Aligned with the arguments
    WithArgs,
    // Aligned with the where clause
    WithWhereClause,
}

configuration_option_enum! { IndentStyle:
    // First line on the same line as the opening brace, all lines aligned with
    // the first line.
    Visual,
    // First line is on a new line and all lines align with block indent.
    Block,
}

configuration_option_enum! { Density:
    // Fit as much on one line as possible.
    Compressed,
    // Use more lines.
    Tall,
    // Try to compress if the body is empty.
    CompressedIfEmpty,
    // Place every item on a separate line.
    Vertical,
}

configuration_option_enum! { TypeDensity:
    // No spaces around "=" and "+"
    Compressed,
    // Spaces around " = " and " + "
    Wide,
}

impl Density {
    pub fn to_list_tactic(self) -> ListTactic {
        match self {
            Density::Compressed => ListTactic::Mixed,
            Density::Tall |
            Density::CompressedIfEmpty => ListTactic::HorizontalVertical,
            Density::Vertical => ListTactic::Vertical,
        }
    }
}

configuration_option_enum! { LicensePolicy:
    // Do not place license text at top of files
    NoLicense,
    // Use the text in "license" field as the license
    TextLicense,
    // Use a text file as the license text
    FileLicense,
}

configuration_option_enum! { MultilineStyle:
    // Use horizontal layout if it fits in one line, fall back to vertical
    PreferSingle,
    // Use vertical layout
    ForceMulti,
}

impl MultilineStyle {
    pub fn to_list_tactic(self) -> ListTactic {
        match self {
            MultilineStyle::PreferSingle => ListTactic::HorizontalVertical,
            MultilineStyle::ForceMulti => ListTactic::Vertical,
        }
    }
}

configuration_option_enum! { ReportTactic:
    Always,
    Unnumbered,
    Never,
}

configuration_option_enum! { WriteMode:
    // Backs the original file up and overwrites the original.
    Replace,
    // Overwrites original file without backup.
    Overwrite,
    // Writes the output to stdout.
    Display,
    // Writes the diff to stdout.
    Diff,
    // Displays how much of the input file was processed
    Coverage,
    // Unfancy stdout
    Plain,
    // Outputs a checkstyle XML file.
    Checkstyle,
}

/// Trait for types that can be used in `Config`.
pub trait ConfigType: Sized {
    /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a
    /// pipe-separated list of variants; for other types it returns "<type>".
    fn doc_hint() -> String;
}

impl ConfigType for bool {
    fn doc_hint() -> String {
        String::from("<boolean>")
    }
}

impl ConfigType for usize {
    fn doc_hint() -> String {
        String::from("<unsigned integer>")
    }
}

impl ConfigType for isize {
    fn doc_hint() -> String {
        String::from("<signed integer>")
    }
}

impl ConfigType for String {
    fn doc_hint() -> String {
        String::from("<string>")
    }
}

impl ConfigType for FileLines {
    fn doc_hint() -> String {
        String::from("<json>")
    }
}

pub struct ConfigHelpItem {
    option_name: &'static str,
    doc_string: &'static str,
    variant_names: String,
    default: &'static str,
}

impl ConfigHelpItem {
    pub fn option_name(&self) -> &'static str {
        self.option_name
    }

    pub fn doc_string(&self) -> &'static str {
        self.doc_string
    }

    pub fn variant_names(&self) -> &String {
        &self.variant_names
    }

    pub fn default(&self) -> &'static str {
        self.default
    }
}

macro_rules! create_config {
    ($($i:ident: $ty:ty, $def:expr, $( $dstring:expr ),+ );+ $(;)*) => (
        #[derive(Deserialize, Clone)]
        pub struct Config {
            $(pub $i: $ty),+
        }

        // Just like the Config struct but with each property wrapped
        // as Option<T>. This is used to parse a rustfmt.toml that doesn't
        // specity all properties of `Config`.
        // We first parse into `ParsedConfig`, then create a default `Config`
        // and overwrite the properties with corresponding values from `ParsedConfig`
        #[derive(Deserialize, Clone)]
        pub struct ParsedConfig {
            $(pub $i: Option<$ty>),+
        }

        impl Config {

            fn fill_from_parsed_config(mut self, parsed: ParsedConfig) -> Config {
            $(
                if let Some(val) = parsed.$i {
                    self.$i = val;
                }
            )+
                self
            }

            pub fn from_toml(toml: &str) -> Result<Config, String> {
                let parsed: toml::Value =
                    toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?;
                let mut err: String = String::new();
                {
                    let table = parsed
                        .as_table()
                        .ok_or(String::from("Parsed config was not table"))?;
                    for (key, _) in table {
                        match &**key {
                            $(
                                stringify!($i) => (),
                            )+
                                _ => {
                                    let msg =
                                        &format!("Warning: Unknown configuration option `{}`\n",
                                                 key);
                                    err.push_str(msg)
                                }
                        }
                    }
                }
                match parsed.try_into() {
                    Ok(parsed_config) =>
                        Ok(Config::default().fill_from_parsed_config(parsed_config)),
                    Err(e) => {
                        err.push_str("Error: Decoding config file failed:\n");
                        err.push_str(format!("{}\n", e).as_str());
                        err.push_str("Please check your config file.\n");
                        Err(err)
                    }
                }
            }

            pub fn override_value(&mut self, key: &str, val: &str) {
                match key {
                    $(
                        stringify!($i) => {
                            self.$i = val.parse::<$ty>()
                                .expect(&format!("Failed to parse override for {} (\"{}\") as a {}",
                                                 stringify!($i),
                                                 val,
                                                 stringify!($ty)));
                        }
                    )+
                    _ => panic!("Unknown config key in override: {}", key)
                }
            }

            pub fn print_docs() {
                use std::cmp;
                let max = 0;
                $( let max = cmp::max(max, stringify!($i).len()+1); )+
                let mut space_str = String::with_capacity(max);
                for _ in 0..max {
                    space_str.push(' ');
                }
                println!("Configuration Options:");
                $(
                    let name_raw = stringify!($i);
                    let mut name_out = String::with_capacity(max);
                    for _ in name_raw.len()..max-1 {
                        name_out.push(' ')
                    }
                    name_out.push_str(name_raw);
                    name_out.push(' ');
                    println!("{}{} Default: {:?}",
                             name_out,
                             <$ty>::doc_hint(),
                             $def);
                    $(
                        println!("{}{}", space_str, $dstring);
                    )+
                    println!("");
                )+
            }
        }

        // Template for the default configuration
        impl Default for Config {
            fn default() -> Config {
                Config {
                    $(
                        $i: $def,
                    )+
                }
            }
        }
    )
}

create_config! {
    verbose: bool, false, "Use verbose output";
    disable_all_formatting: bool, false, "Don't reformat anything";
    skip_children: bool, false, "Don't reformat out of line modules";
    file_lines: FileLines, FileLines::all(),
        "Lines to format; this is not supported in rustfmt.toml, and can only be specified \
         via the --file-lines option";
    max_width: usize, 100, "Maximum width of each line";
    error_on_line_overflow: bool, true, "Error if unable to get all lines within max_width";
    tab_spaces: usize, 4, "Number of spaces per tab";
    fn_call_width: usize, 60,
        "Maximum width of the args of a function call before falling back to vertical formatting";
    struct_lit_width: usize, 18,
        "Maximum width in the body of a struct lit before falling back to vertical formatting";
    struct_variant_width: usize, 35,
        "Maximum width in the body of a struct variant before falling back to vertical formatting";
    force_explicit_abi: bool, true, "Always print the abi for extern items";
    newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings";
    fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions";
    item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums";
    control_style: Style, Style::Default, "Indent style for control flow statements";
    control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine,
        "Brace style for control flow constructs";
    impl_empty_single_line: bool, true, "Put empty-body implementations on a single line";
    trailing_comma: SeparatorTactic, SeparatorTactic::Vertical,
        "How to handle trailing commas for lists";
    fn_empty_single_line: bool, true, "Put empty-body functions on a single line";
    fn_single_line: bool, false, "Put single-expression functions on a single line";
    fn_return_indent: ReturnIndent, ReturnIndent::WithArgs,
        "Location of return type in function declaration";
    fn_args_paren_newline: bool, true, "If function argument parenthesis goes on a newline";
    fn_args_density: Density, Density::Tall, "Argument density in functions";
    fn_args_layout: IndentStyle, IndentStyle::Visual,
        "Layout of function arguments and tuple structs";
    array_layout: IndentStyle, IndentStyle::Visual, "Indent on arrays";
    array_width: usize, 60,
        "Maximum width of an array literal before falling back to vertical formatting";
    type_punctuation_density: TypeDensity, TypeDensity::Wide,
        "Determines if '+' or '=' are wrapped in spaces in the punctuation of types";
    where_style: Style, Style::Default, "Overall strategy for where clauses";
    // TODO:
    // 1. Should we at least try to put the where clause on the same line as the rest of the
    // function decl?
    // 2. Currently options `Tall` and `Vertical` produce the same output.
    where_density: Density, Density::CompressedIfEmpty, "Density of a where clause";
    where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause";
    where_pred_indent: IndentStyle, IndentStyle::Visual,
        "Indentation style of a where predicate";
    generics_indent: IndentStyle, IndentStyle::Visual, "Indentation of generics";
    struct_lit_style: IndentStyle, IndentStyle::Block, "Style of struct definition";
    struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle,
        "Multiline style on literal structs";
    fn_call_style: IndentStyle, IndentStyle::Visual, "Indentation for function calls, etc.";
    report_todo: ReportTactic, ReportTactic::Never,
        "Report all, none or unnumbered occurrences of TODO in source file comments";
    report_fixme: ReportTactic, ReportTactic::Never,
        "Report all, none or unnumbered occurrences of FIXME in source file comments";
    chain_indent: IndentStyle, IndentStyle::Block, "Indentation of chain";
    chain_one_line_max: usize, 60, "Maximum length of a chain to fit on a single line";
    reorder_imports: bool, false, "Reorder import statements alphabetically";
    reorder_imported_names: bool, false,
        "Reorder lists of names in import statements alphabetically";
    single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \
                                                expressions. A value of zero means always break \
                                                if-else expressions.";
    format_strings: bool, false, "Format string literals where necessary";
    force_format_strings: bool, false, "Always format string literals";
    take_source_hints: bool, false, "Retain some formatting characteristics from the source code";
    hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment";
    wrap_comments: bool, false, "Break comments to fit on the line";
    comment_width: usize, 80, "Maximum length of comments. No effect unless wrap_comments = true";
    normalize_comments: bool, false, "Convert /* */ comments to // comments where possible";
    wrap_match_arms: bool, true, "Wrap multiline match arms in blocks";
    match_block_trailing_comma: bool, false,
        "Put a trailing comma after a block based match arm (non-block arms are not affected)";
    indent_match_arms: bool, true, "Indent match arms instead of keeping them at the same \
                                    indentation level as the match keyword";
    closure_block_indent_threshold: isize, 7, "How many lines a closure must have before it is \
                                               block indented. -1 means never use block indent.";
    space_before_type_annotation: bool, false,
        "Leave a space before the colon in a type annotation";
    space_after_type_annotation_colon: bool, true,
        "Leave a space after the colon in a type annotation";
    space_before_bound: bool, false, "Leave a space before the colon in a trait or lifetime bound";
    space_after_bound_colon: bool, true,
        "Leave a space after the colon in a trait or lifetime bound";
    spaces_around_ranges: bool, false, "Put spaces around the  .. and ... range operators";
    spaces_within_angle_brackets: bool, false, "Put spaces within non-empty generic arguments";
    spaces_within_square_brackets: bool, false, "Put spaces within non-empty square brackets";
    spaces_within_parens: bool, false, "Put spaces within non-empty parentheses";
    use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand";
    write_mode: WriteMode, WriteMode::Replace,
        "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage";
    condense_wildcard_suffices: bool, false, "Replace strings of _ wildcards by a single .. in \
                                              tuple patterns"
}
<|endoftext|>