<commit_before>
use super::job::*;
use super::active_queue::*;
use super::queue_state::*;
use super::wake_thread::*;

use std::fmt;
use std::sync::*;
use std::thread;
use std::collections::vec_deque::*;

use futures::task;
use futures::task::{Context, Poll};

///
/// A job queue provides a list of jobs to perform in order
///
pub struct JobQueue {
    /// The shared data for this queue is stored within a mutex
    pub (super) core: Mutex<JobQueueCore>
}

///
/// The result of running a job
///
pub (super) enum JobStatus {
    /// No jobs were waiting on the queue
    NoJobsWaiting,

    /// Job was run successfully
    Finished,

    /// The job caused the queue to suspend: it will be rescheduled in the background
    WaitInBackground
}

///
/// Structure protected by the jobqueue matrix
///
pub (super) struct JobQueueCore {
    /// The jobs that are scheduled on this queue
    pub (super) queue: VecDeque<Box<dyn ScheduledJob>>,

    /// The current state of this queue
    pub (super) state: QueueState,

    /// How many times this queue has been suspended (can be negative to indicate the suspension ended before it began)
    pub (super) suspension_count: i32
}

impl fmt::Debug for JobQueue {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let core = self.core.lock().expect("JobQueue core lock");

        fmt.write_str(&format!("JobQueue: State: {:?}, Pending: {}", core.state, core.queue.len()))
    }
}

impl JobQueue {
    ///
    /// Creates a new job queue
    ///
    pub (super) fn new() -> JobQueue {
        JobQueue {
            core: Mutex::new(JobQueueCore {
                queue:              VecDeque::new(),
                state:              QueueState::Idle,
                suspension_count:   0
            })
        }
    }

    ///
    /// If there are any jobs waiting, dequeues the next one
    ///
    pub (super) fn dequeue(&self) -> Option<Box<dyn ScheduledJob>> {
        let mut core = self.core.lock().expect("JobQueue core lock");

        match core.state {
            QueueState::Suspending      => None,
            QueueState::WaitingForWake  => None,
            other                       => {
                debug_assert!(other == QueueState::Running);
                core.queue.pop_front()
            }
        }
    }

    ///
    /// Adds a job to the front of the queue (so it's the next one to run)
    ///
    pub (super) fn requeue(&self, job: Box<dyn ScheduledJob>) {
        let mut core = self.core.lock().expect("JobQueue core lock");

        core.queue.push_front(job);
    }

    ///
    /// Runs jobs on this queue until there are none left, marking the job as inactive when done
    ///
    pub (super) fn drain(&self, context: &mut Context) {
        let _active = ActiveQueue { queue: self };

        debug_assert!(self.core.lock().unwrap().state == QueueState::Running);
        let mut done = false;

        while !done {
            // Run jobs until the queue is drained or blocks
            while let Some(mut job) = self.dequeue() {
                debug_assert!(self.core.lock().unwrap().state == QueueState::Running);

                let poll_result = job.run(context);

                match poll_result {
                    Poll::Ready(()) => { },
                    Poll::Pending   => {
                        // Job needs requeing
                        self.requeue(job);

                        // Queue should move from the 'running' state to the 'waiting for wake' state
                        let mut core = self.core.lock().expect("JobQueue core lock");

                        core.state = match core.state {
                            QueueState::Running             => QueueState::WaitingForWake,
                            QueueState::AwokenWhileRunning  => QueueState::Running,
                            other                           => other
                        };

                        if core.state == QueueState::WaitingForWake {
                            return;
                        }
                    }
                }
            }

            // Try to move back to the 'not running' state
            {
                let mut core = self.core.lock().expect("JobQueue core lock");
                debug_assert!(core.state == QueueState::Running || core.state == QueueState::Suspending);

                // If the queue is empty at the point where we obtain the lock, we can deactivate ourselves
                if core.queue.len() == 0 {
                    core.state = match core.state {
                        QueueState::Running         => QueueState::Idle,
                        QueueState::Suspending      => QueueState::Suspended,
                        x                           => x
                    };
                    done = true;
                } else if core.state == QueueState::Suspending {
                    // Stop draining as we're suspending
                    core.state = QueueState::Suspended;
                    done = true;
                } else if core.state == QueueState::Pending {
                    // Will restart when we get re-scheduled
                    done = true;
                }
            }
        }
    }

    ///
    /// With the queue already in the running state, dequeues a single job and runs it synchronously on the current thread
    ///
    pub (super) fn run_one_job_now(queue: &Arc<JobQueue>) -> JobStatus {
        if let Some(mut job) = queue.dequeue() {
            // Queue is running
            debug_assert!(queue.core.lock().unwrap().state == QueueState::Running);

            let waker       = Arc::new(WakeThread(Arc::clone(queue), thread::current()));
            let waker       = task::waker_ref(&waker);
            let mut context = Context::from_waker(&waker);

            loop {
                let poll_result = job.run(&mut context);

                match poll_result {
                    // A ready result ends the loop
                    Poll::Ready(()) => break,
                    Poll::Pending   => {
                        // Try to move to the parking state
                        let should_park = {
                            let mut core = queue.core.lock().unwrap();

                            core.state = match core.state {
                                QueueState::AwokenWhileRunning  => QueueState::Running,
                                QueueState::Running             => QueueState::WaitingForWake,
                                other                           => panic!("Queue was in unexpected state {:?}", other)
                            };

                            core.state == QueueState::WaitingForWake
                        };

                        // Park until the queue state returns changes
                        if should_park {
                            // If should_park is set to false, the queue was awoken very quickly
                            loop {
                                let current_state = { queue.core.lock().unwrap().state };
                                match current_state {
                                    QueueState::Idle            => break,
                                    QueueState::WaitingForWake  => (),
                                    other                       => panic!("Queue was in unexpected state {:?}", other)
                                }

                                // Park until we're awoken from the other thread (once awoken, we re-check the state)
                                thread::park();
                            }
                        }
                    }
                }
            }

            JobStatus::Finished
        } else {
            // Queue may have suspended (or gone to suspending and back to running)
            let wait_in_background = {
                let mut core = queue.core.lock().expect("JobQueue core lock");
                if core.state == QueueState::Suspending {
                    // Finish suspension, then wait for job to complete
                    core.state = QueueState::Suspended;
                    true
                } else {
                    // Queue is still running
                    debug_assert!(core.state == QueueState::Running);
                    false
                }
            };

            if wait_in_background {
                JobStatus::WaitInBackground
            } else {
                JobStatus::NoJobsWaiting
            }
        }
    }
}
<commit_msg>The suspension count is no longer used<commit_after>
use super::job::*;
use super::active_queue::*;
use super::queue_state::*;
use super::wake_thread::*;

use std::fmt;
use std::sync::*;
use std::thread;
use std::collections::vec_deque::*;

use futures::task;
use futures::task::{Context, Poll};

///
/// A job queue provides a list of jobs to perform in order
///
pub struct JobQueue {
    /// The shared data for this queue is stored within a mutex
    pub (super) core: Mutex<JobQueueCore>
}

///
/// The result of running a job
///
pub (super) enum JobStatus {
    /// No jobs were waiting on the queue
    NoJobsWaiting,

    /// Job was run successfully
    Finished,

    /// The job caused the queue to suspend: it will be rescheduled in the background
    WaitInBackground
}

///
/// Structure protected by the jobqueue matrix
///
pub (super) struct JobQueueCore {
    /// The jobs that are scheduled on this queue
    pub (super) queue: VecDeque<Box<dyn ScheduledJob>>,

    /// The current state of this queue
    pub (super) state: QueueState,
}

impl fmt::Debug for JobQueue {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let core = self.core.lock().expect("JobQueue core lock");

        fmt.write_str(&format!("JobQueue: State: {:?}, Pending: {}", core.state, core.queue.len()))
    }
}

impl JobQueue {
    ///
    /// Creates a new job queue
    ///
    pub (super) fn new() -> JobQueue {
        JobQueue {
            core: Mutex::new(JobQueueCore {
                queue:              VecDeque::new(),
                state:              QueueState::Idle
            })
        }
    }

    ///
    /// If there are any jobs waiting, dequeues the next one
    ///
    pub (super) fn dequeue(&self) -> Option<Box<dyn ScheduledJob>> {
        let mut core = self.core.lock().expect("JobQueue core lock");

        match core.state {
            QueueState::Suspending      => None,
            QueueState::WaitingForWake  => None,
            other                       => {
                debug_assert!(other == QueueState::Running);
                core.queue.pop_front()
            }
        }
    }

    ///
    /// Adds a job to the front of the queue (so it's the next one to run)
    ///
    pub (super) fn requeue(&self, job: Box<dyn ScheduledJob>) {
        let mut core = self.core.lock().expect("JobQueue core lock");

        core.queue.push_front(job);
    }

    ///
    /// Runs jobs on this queue until there are none left, marking the job as inactive when done
    ///
    pub (super) fn drain(&self, context: &mut Context) {
        let _active = ActiveQueue { queue: self };

        debug_assert!(self.core.lock().unwrap().state == QueueState::Running);
        let mut done = false;

        while !done {
            // Run jobs until the queue is drained or blocks
            while let Some(mut job) = self.dequeue() {
                debug_assert!(self.core.lock().unwrap().state == QueueState::Running);

                let poll_result = job.run(context);

                match poll_result {
                    Poll::Ready(()) => { },
                    Poll::Pending   => {
                        // Job needs requeing
                        self.requeue(job);

                        // Queue should move from the 'running' state to the 'waiting for wake' state
                        let mut core = self.core.lock().expect("JobQueue core lock");

                        core.state = match core.state {
                            QueueState::Running             => QueueState::WaitingForWake,
                            QueueState::AwokenWhileRunning  => QueueState::Running,
                            other                           => other
                        };

                        if core.state == QueueState::WaitingForWake {
                            return;
                        }
                    }
                }
            }

            // Try to move back to the 'not running' state
            {
                let mut core = self.core.lock().expect("JobQueue core lock");
                debug_assert!(core.state == QueueState::Running || core.state == QueueState::Suspending);

                // If the queue is empty at the point where we obtain the lock, we can deactivate ourselves
                if core.queue.len() == 0 {
                    core.state = match core.state {
                        QueueState::Running         => QueueState::Idle,
                        QueueState::Suspending      => QueueState::Suspended,
                        x                           => x
                    };
                    done = true;
                } else if core.state == QueueState::Suspending {
                    // Stop draining as we're suspending
                    core.state = QueueState::Suspended;
                    done = true;
                } else if core.state == QueueState::Pending {
                    // Will restart when we get re-scheduled
                    done = true;
                }
            }
        }
    }

    ///
    /// With the queue already in the running state, dequeues a single job and runs it synchronously on the current thread
    ///
    pub (super) fn run_one_job_now(queue: &Arc<JobQueue>) -> JobStatus {
        if let Some(mut job) = queue.dequeue() {
            // Queue is running
            debug_assert!(queue.core.lock().unwrap().state == QueueState::Running);

            let waker       = Arc::new(WakeThread(Arc::clone(queue), thread::current()));
            let waker       = task::waker_ref(&waker);
            let mut context = Context::from_waker(&waker);

            loop {
                let poll_result = job.run(&mut context);

                match poll_result {
                    // A ready result ends the loop
                    Poll::Ready(()) => break,
                    Poll::Pending   => {
                        // Try to move to the parking state
                        let should_park = {
                            let mut core = queue.core.lock().unwrap();

                            core.state = match core.state {
                                QueueState::AwokenWhileRunning  => QueueState::Running,
                                QueueState::Running             => QueueState::WaitingForWake,
                                other                           => panic!("Queue was in unexpected state {:?}", other)
                            };

                            core.state == QueueState::WaitingForWake
                        };

                        // Park until the queue state returns changes
                        if should_park {
                            // If should_park is set to false, the queue was awoken very quickly
                            loop {
                                let current_state = { queue.core.lock().unwrap().state };
                                match current_state {
                                    QueueState::Idle            => break,
                                    QueueState::WaitingForWake  => (),
                                    other                       => panic!("Queue was in unexpected state {:?}", other)
                                }

                                // Park until we're awoken from the other thread (once awoken, we re-check the state)
                                thread::park();
                            }
                        }
                    }
                }
            }

            JobStatus::Finished
        } else {
            // Queue may have suspended (or gone to suspending and back to running)
            let wait_in_background = {
                let mut core = queue.core.lock().expect("JobQueue core lock");
                if core.state == QueueState::Suspending {
                    // Finish suspension, then wait for job to complete
                    core.state = QueueState::Suspended;
                    true
                } else {
                    // Queue is still running
                    debug_assert!(core.state == QueueState::Running);
                    false
                }
            };

            if wait_in_background {
                JobStatus::WaitInBackground
            } else {
                JobStatus::NoJobsWaiting
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Example of a `busybox-style` multicall program
//!
//! `busybox` is a single executable that contains a variety of applets
//! for a fully functional Linux userland.
//!
//! `busybox`-style differs from `hostname`-style in that there is a launcher program
//! which the applets are available as subcommands.
//! i.e. you can use the `cat` command either as a link named `cat`
//! or as `busybox cat`.
//!
//! This behaviour is opted-into by not naming an applet the same as the main program.
//!
//! This is desirable when the launcher program has additional options
//! or it is useful to run the applet without installing a symlink
//! e.g. for testing purposes, or there may already be a command of that name installed.
//!
//! This example omits every command except true and false,
//! which are the most trivial to implement,
//! but includes the `--install` option as an example of why it can be useful
//! for the main program to take arguments that aren't applet subcommands.

use std::{
    env::args_os,
    fs::{hard_link, read_link},
    path::{Path, PathBuf},
    process::exit,
};

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

fn main() {
    let mut app = App::new(env!("CARGO_CRATE_NAME"))
        .setting(AppSettings::ArgRequiredElseHelp)
        .setting(AppSettings::Multicall)
        .arg(
            Arg::new("install")
                .long("install")
                .about("Install hardlinks for all subcommands in path")
                .exclusive(true)
                .takes_value(true)
                .default_missing_value("/usr/local/bin")
                .use_delimiter(false),
        )
        .subcommand(App::new("true").about("does nothing successfully"))
        .subcommand(App::new("false").about("does nothing unsuccessfully"));
    let matches = app.get_matches_mut();
    if matches.occurrences_of("install") > 0 {
        let exec_path = read_link("/proc/self/exe")
            .ok()
            .or_else(|| {
                args_os().next().and_then(|s| {
                    let p: &Path = s.as_ref();
                    if p.is_absolute() {
                        Some(PathBuf::from(s))
                    } else {
                        None
                    }
                })
            })
            .expect(
                "Should be able to read /proc/self/exe or argv0 should be present and absolute",
            );
        let mut dest = PathBuf::from(matches.value_of("install").unwrap());
        for applet in app.get_subcommands().map(|c| c.get_name()) {
            dest.push(applet);
            hard_link(&exec_path, &dest).expect("Should be able to hardlink");
            dest.pop();
        }
        exit(0);
    }

    exit(match matches.subcommand_name() {
        Some("true") => 0,
        Some("false") => 1,
        _ => 127,
    })
}
<commit_msg>fixup! trim hardlink implementation from busybox example<commit_after>//! Example of a `busybox-style` multicall program
//!
//! `busybox` is a single executable that contains a variety of applets
//! for a fully functional Linux userland.
//!
//! `busybox`-style differs from `hostname`-style in that there is a launcher program
//! which the applets are available as subcommands.
//! i.e. you can use the `cat` command either as a link named `cat`
//! or as `busybox cat`.
//!
//! This behaviour is opted-into by not naming an applet the same as the main program.
//!
//! This is desirable when the launcher program has additional options
//! or it is useful to run the applet without installing a symlink
//! e.g. for testing purposes, or there may already be a command of that name installed.
//!
//! This example omits every command except true and false,
//! which are the most trivial to implement,
//! but includes the `--install` option as an example of why it can be useful
//! for the main program to take arguments that aren't applet subcommands.

use std::process::exit;

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

fn main() {
    let mut app = App::new(env!("CARGO_CRATE_NAME"))
        .setting(AppSettings::ArgRequiredElseHelp)
        .setting(AppSettings::Multicall)
        .arg(
            Arg::new("install")
                .long("install")
                .about("Install hardlinks for all subcommands in path")
                .exclusive(true)
                .takes_value(true)
                .default_missing_value("/usr/local/bin")
                .use_delimiter(false),
        )
        .subcommand(App::new("true").about("does nothing successfully"))
        .subcommand(App::new("false").about("does nothing unsuccessfully"));
    let matches = app.get_matches_mut();
    if matches.occurrences_of("install") > 0 {
        unimplemented!("Make hardlinks to the executable here");
    }

    exit(match matches.subcommand_name() {
        Some("true") => 0,
        Some("false") => 1,
        _ => 127,
    })
}
<|endoftext|>


<commit_before>//! Provides the following procedural derive macros:
//!
//! - `#[derive(Encode)]`
//! - `#[derive(Decode)]`
//!
//! These macros provide SSZ encoding/decoding for a `struct`. Fields are encoded/decoded in the
//! order they are defined.
//!
//! Presently, only `structs` with named fields are supported. `enum`s and tuple-structs are
//! unsupported.
//!
//! Example:
//! ```
//! use ssz::{ssz_encode, Decodable, Encodable};
//!
//! #[derive(Encodable, Decodable)]
//! struct Foo {
//!     bar: bool,
//!     baz: u64,
//! }
//!
//! fn main() {
//!     let foo = Foo {
//!         bar: true,
//!         baz: 42,
//!     };
//!
//!     let bytes = ssz_encode(&foo);
//!
//!     let decoded_foo = Foo::ssz_decode(bytes, 0).unwrap();
//!
//!     assert_eq!(foo.baz, decoded_foo.baz);
//! }
//! ```

extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

fn get_named_field_idents<'a>(struct_data: &'a syn::DataStruct) -> Vec<&'a syn::Ident> {
    struct_data
        .fields
        .iter()
        .map(|f| match &f.ident {
            Some(ref ident) => ident,
            _ => panic!("ssz_derive only supports named struct fields."),
        })
        .collect()
}

/// Implements `ssz::Encodable` on some `struct`.
///
/// Fields are encoded in the order they are defined.
#[proc_macro_derive(Encode)]
pub fn ssz_encode_derive(input: TokenStream) -> TokenStream {
    let item = parse_macro_input!(input as DeriveInput);

    let name = &item.ident;

    let struct_data = match &item.data {
        syn::Data::Struct(s) => s,
        _ => panic!("ssz_derive only supports structs."),
    };

    let field_idents = get_named_field_idents(&struct_data);

    let output = quote! {
        impl Encodable for #name {
            fn ssz_append(&self, s: &mut SszStream) {
                #(
                    s.append(&self.#field_idents);
                )*
            }
        }
    };
    output.into()
}

/// Implements `ssz::Decodable` on some `struct`.
///
/// Fields are decoded in the order they are defined.
#[proc_macro_derive(Decode)]
pub fn ssz_decode_derive(input: TokenStream) -> TokenStream {
    let item = parse_macro_input!(input as DeriveInput);

    let name = &item.ident;

    let struct_data = match &item.data {
        syn::Data::Struct(s) => s,
        _ => panic!("ssz_derive only supports structs."),
    };

    let field_idents = get_named_field_idents(&struct_data);

    // Using a var in an iteration always consumes the var, therefore we must make a `fields_a` and
    // a `fields_b` in order to perform two loops.
    //
    // https://github.com/dtolnay/quote/issues/8
    let field_idents_a = &field_idents;
    let field_idents_b = &field_idents;

    let output = quote! {
        impl Decodable for #name {
            fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
                #(
                    let (#field_idents_a, i) = <_>::ssz_decode(bytes, i)?;
                )*

                Ok((
                    Self {
                        #(
                            #field_idents_b,
                        )*
                    },
                    i
                ))
            }
        }
    };
    output.into()
}
<commit_msg>Fix failing doc examples in ssz_derive<commit_after>//! Provides the following procedural derive macros:
//!
//! - `#[derive(Encode)]`
//! - `#[derive(Decode)]`
//!
//! These macros provide SSZ encoding/decoding for a `struct`. Fields are encoded/decoded in the
//! order they are defined.
//!
//! Presently, only `structs` with named fields are supported. `enum`s and tuple-structs are
//! unsupported.
//!
//! Example:
//! ```
//! use ssz::{ssz_encode, Decodable, Encodable, SszStream, DecodeError};
//! use ssz_derive::{Encode, Decode};
//!
//! #[derive(Encode, Decode)]
//! struct Foo {
//!     pub bar: bool,
//!     pub baz: u64,
//! }
//!
//! fn main() {
//!     let foo = Foo {
//!         bar: true,
//!         baz: 42,
//!     };
//!
//!     let bytes = ssz_encode(&foo);
//!
//!     let (decoded_foo, _i) = Foo::ssz_decode(&bytes, 0).unwrap();
//!
//!     assert_eq!(foo.baz, decoded_foo.baz);
//! }
//! ```

extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

fn get_named_field_idents<'a>(struct_data: &'a syn::DataStruct) -> Vec<&'a syn::Ident> {
    struct_data
        .fields
        .iter()
        .map(|f| match &f.ident {
            Some(ref ident) => ident,
            _ => panic!("ssz_derive only supports named struct fields."),
        })
        .collect()
}

/// Implements `ssz::Encodable` for some `struct`.
///
/// Fields are encoded in the order they are defined.
#[proc_macro_derive(Encode)]
pub fn ssz_encode_derive(input: TokenStream) -> TokenStream {
    let item = parse_macro_input!(input as DeriveInput);

    let name = &item.ident;

    let struct_data = match &item.data {
        syn::Data::Struct(s) => s,
        _ => panic!("ssz_derive only supports structs."),
    };

    let field_idents = get_named_field_idents(&struct_data);

    let output = quote! {
        impl Encodable for #name {
            fn ssz_append(&self, s: &mut SszStream) {
                #(
                    s.append(&self.#field_idents);
                )*
            }
        }
    };
    output.into()
}

/// Implements `ssz::Decodable` for some `struct`.
///
/// Fields are decoded in the order they are defined.
#[proc_macro_derive(Decode)]
pub fn ssz_decode_derive(input: TokenStream) -> TokenStream {
    let item = parse_macro_input!(input as DeriveInput);

    let name = &item.ident;

    let struct_data = match &item.data {
        syn::Data::Struct(s) => s,
        _ => panic!("ssz_derive only supports structs."),
    };

    let field_idents = get_named_field_idents(&struct_data);

    // Using a var in an iteration always consumes the var, therefore we must make a `fields_a` and
    // a `fields_b` in order to perform two loops.
    //
    // https://github.com/dtolnay/quote/issues/8
    let field_idents_a = &field_idents;
    let field_idents_b = &field_idents;

    let output = quote! {
        impl Decodable for #name {
            fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
                #(
                    let (#field_idents_a, i) = <_>::ssz_decode(bytes, i)?;
                )*

                Ok((
                    Self {
                        #(
                            #field_idents_b,
                        )*
                    },
                    i
                ))
            }
        }
    };
    output.into()
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2019 Fabian Schuiki

mod common;
use crate::common::*;

/// Compile a module in a piece of verilog code and return the LLHD.
fn compile_module(name: &str, code: &str) -> String {
    simple_logger::init().is_ok();
    let sess = Session::new();
    let store = GlobalArenas::default();
    let ast = parse(code);
    let cx = GlobalContext::new(&sess, &store);
    cx.add_root_nodes(ast.iter());
    let m = cx.find_module(name.into()).unwrap();
    let mut cg = CodeGenerator::new(&cx);
    cg.emit_module(m.into()).unwrap();
    module_to_string(&cg.finalize())
}

#[test]
fn empty_module() {
    assert_eq!(
        compile_module("foo", "module foo; endmodule").trim(),
        "entity @foo () () {\n}"
    );
}

#[test]
fn module_with_trivial_ports() {
    assert_eq!(
        compile_module("foo", "module foo (input bit a, output bit b); endmodule").trim(),
        "entity @foo (i1$ %a) (i1$ %b) {\n}"
    );
}

#[test]
fn empty_instances() {
    assert_eq!(
        compile_module(
            "foo",
            "
            module foo;
                bar b();
            endmodule

            module bar;
            endmodule
            "
        )
        .trim(),
        "entity @bar () () {\n}\n\nentity @foo () () {\n    inst @bar () ()\n}"
    );
}
<commit_msg>tests: fix codegen unit test<commit_after>// Copyright (c) 2016-2019 Fabian Schuiki

mod common;
use crate::common::*;

/// Compile a module in a piece of verilog code and return the LLHD.
fn compile_module(name: &str, code: &str) -> String {
    simple_logger::init().is_ok();
    let sess = Session::new();
    let store = GlobalArenas::default();
    let ast = parse(code);
    let cx = GlobalContext::new(&sess, &store);
    cx.add_root_nodes(ast.iter());
    let m = cx.find_module(name.into()).unwrap();
    let mut cg = CodeGenerator::new(&cx);
    cg.emit_module(m.into()).unwrap();
    module_to_string(&cg.finalize())
}

#[test]
fn empty_module() {
    assert_eq!(
        compile_module("foo", "module foo; endmodule").trim(),
        "entity @foo () () {\n}"
    );
}

#[test]
fn module_with_trivial_ports() {
    assert_eq!(
        compile_module("foo", "module foo (input bit a, output bit b); endmodule").trim(),
        "entity @foo (i1$ %a) (i1$ %b) {\n    drv %b 0\n}"
    );
}

#[test]
fn empty_instances() {
    assert_eq!(
        compile_module(
            "foo",
            "
            module foo;
                bar b();
            endmodule

            module bar;
            endmodule
            "
        )
        .trim(),
        "entity @bar () () {\n}\n\nentity @foo () () {\n    inst @bar () ()\n}"
    );
}
<|endoftext|>


<commit_before>fn main() {
    // 通过闭包和函数实现增量。
    fn  function            (i: i32) -> i32 { i + 1 }

    // 类型标注和函数的一样，不过类型标注和使用 `{}` 来围住代码都是可选的。
    // 这些匿名函数（nameless function）赋值给合适命名的变量。
    let closure_annotated = |i: i32| -> i32 { i + 1 };
    let closure_inferred  = |i     |          i + 1  ;

    let i = 1;
    // 调用函数和闭包。
    println!("function: {}", function(i));
    println!("annotated closure: {}", closure_annotated(i));
    println!("inferred closure: {}", closure_inferred(i));

    // 没有参数的闭包，返回一个 `i32` 类型。
    // 返回类型是自动推导的。
    let one = || 1;
    println!("closure returning one: {}", one());
}
<commit_msg>Minor string fixes<commit_after>fn main() {
    // 通过闭包和函数实现增量。
    fn  function            (i: i32) -> i32 { i + 1 }

    // 类型标注和函数的一样，不过类型标注和使用 `{}` 来围住代码都是可选的。
    // 这些匿名函数（nameless function）赋值给合适命名的变量。
    let closure_annotated = |i: i32| -> i32 { i + 1 };
    let closure_inferred  = |i     |          i + 1  ;

    let i = 1;
    // 调用函数和闭包。
    println!("function: {}", function(i));
    println!("closure_annotated: {}", closure_annotated(i));
    println!("closure_inferred: {}", closure_inferred(i));

    // 没有参数的闭包，返回一个 `i32` 类型。
    // 返回类型是自动推导的。
    let one = || 1;
    println!("closure returning one: {}", one());
}
<|endoftext|>


<commit_before>// Copyright 2017 Google 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate cmake;

mod cmd_finder;

use std::env;
use std::path::{Path, PathBuf};

fn build_shaderc(shaderc_dir: &PathBuf, use_ninja: bool) -> PathBuf {
    let mut config = cmake::Config::new(shaderc_dir);
    config.profile("Release")
        .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
        .define("SPIRV_SKIP_EXECUTABLES", "ON")
        .define("SPIRV_WERROR", "OFF")
        .define("SHADERC_SKIP_TESTS", "ON")
        .define("CMAKE_INSTALL_LIBDIR", "lib");
    if use_ninja {
        config.generator("Ninja");
    }
    config.build()
}

fn build_shaderc_msvc(shaderc_dir: &PathBuf, use_ninja: bool) -> PathBuf {
    let mut config = cmake::Config::new(shaderc_dir);
    config.profile("Release")
        .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
        .define("SPIRV_SKIP_EXECUTABLES", "ON")
        .define("SPIRV_WERROR", "OFF")
        .define("SHADERC_SKIP_TESTS", "ON")
        // cmake-rs tries to be clever on Windows by injecting several
        // C/C++ flags, which causes problems. So I have to manually
        // define CMAKE_*_FLAGS_* here to suppress that.
        .define("CMAKE_C_FLAGS", " /nologo /EHsc")
        .define("CMAKE_CXX_FLAGS", " /nologo /EHsc")
        .define("CMAKE_C_FLAGS_RELEASE", " /nologo /EHsc")
        .define("CMAKE_CXX_FLAGS_RELEASE", " /nologo /EHsc")
        .define("CMAKE_INSTALL_LIBDIR", "lib");
    if use_ninja {
        config.generator("Ninja");
    }
    config.build()
}

fn main() {
    if env::var("CARGO_FEATURE_BUILD_NATIVE_SHADERC").is_err() {
        let out_dir = env::var("OUT_DIR").unwrap();
        println!("cargo:warning=Requested to skip building native C++ shaderc.");
        println!("cargo:warning=Searching {} for shaderc_combined static lib...", out_dir);
        println!("cargo:rustc-link-search=native={}", out_dir);
        println!("cargo:rustc-link-lib=static=shaderc_combined");
        return;
    }

    let mut finder = cmd_finder::CommandFinder::new();

    finder.must_have("cmake");
    finder.must_have("git");
    finder.must_have("python");

    let has_ninja = finder.maybe_have("ninja").is_some();

    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();

    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let shaderc_dir = Path::new(&manifest_dir).join("build");

    let mut lib_path = if target_env == "msvc" {
        build_shaderc_msvc(&shaderc_dir, has_ninja)
    } else {
        build_shaderc(&shaderc_dir, has_ninja)
    };

    lib_path.push("lib");

    println!("cargo:rustc-link-search=native={}", lib_path.display());
    println!("cargo:rustc-link-lib=static=shaderc_combined");

    match (target_os.as_str(), target_env.as_str()) {
        ("linux", _) | ("windows", "gnu") => println!("cargo:rustc-link-lib=dylib=stdc++"),
        ("macos", _) => println!("cargo:rustc-link-lib=dylib=c++"),
        _ => {}
    }
}
<commit_msg>Require ninja when building with MSVC.<commit_after>// Copyright 2017 Google 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate cmake;

mod cmd_finder;

use std::env;
use std::path::{Path, PathBuf};

fn build_shaderc(shaderc_dir: &PathBuf, use_ninja: bool) -> PathBuf {
    let mut config = cmake::Config::new(shaderc_dir);
    config.profile("Release")
        .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
        .define("SPIRV_SKIP_EXECUTABLES", "ON")
        .define("SPIRV_WERROR", "OFF")
        .define("SHADERC_SKIP_TESTS", "ON")
        .define("CMAKE_INSTALL_LIBDIR", "lib");
    if use_ninja {
        config.generator("Ninja");
    }
    config.build()
}

fn build_shaderc_msvc(shaderc_dir: &PathBuf) -> PathBuf {
    let mut config = cmake::Config::new(shaderc_dir);
    config.profile("Release")
        .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
        .define("SPIRV_SKIP_EXECUTABLES", "ON")
        .define("SPIRV_WERROR", "OFF")
        .define("SHADERC_SKIP_TESTS", "ON")
        // cmake-rs tries to be clever on Windows by injecting several
        // C/C++ flags, which causes problems. So I have to manually
        // define CMAKE_*_FLAGS_* here to suppress that.
        .define("CMAKE_C_FLAGS", " /nologo /EHsc")
        .define("CMAKE_CXX_FLAGS", " /nologo /EHsc")
        .define("CMAKE_C_FLAGS_RELEASE", " /nologo /EHsc")
        .define("CMAKE_CXX_FLAGS_RELEASE", " /nologo /EHsc")
        .define("CMAKE_INSTALL_LIBDIR", "lib")
        .generator("Ninja");
    config.build()
}

fn main() {
    if env::var("CARGO_FEATURE_BUILD_NATIVE_SHADERC").is_err() {
        let out_dir = env::var("OUT_DIR").unwrap();
        println!("cargo:warning=Requested to skip building native C++ shaderc.");
        println!("cargo:warning=Searching {} for shaderc_combined static lib...", out_dir);
        println!("cargo:rustc-link-search=native={}", out_dir);
        println!("cargo:rustc-link-lib=static=shaderc_combined");
        return;
    }

    let mut finder = cmd_finder::CommandFinder::new();

    finder.must_have("cmake");
    finder.must_have("git");
    finder.must_have("python");

    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();

    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let shaderc_dir = Path::new(&manifest_dir).join("build");

    let mut lib_path = if target_env == "msvc" {
        finder.must_have("ninja");
        build_shaderc_msvc(&shaderc_dir)
    } else {
        let has_ninja = finder.maybe_have("ninja").is_some();
        build_shaderc(&shaderc_dir, has_ninja)
    };

    lib_path.push("lib");

    println!("cargo:rustc-link-search=native={}", lib_path.display());
    println!("cargo:rustc-link-lib=static=shaderc_combined");

    match (target_os.as_str(), target_env.as_str()) {
        ("linux", _) | ("windows", "gnu") => println!("cargo:rustc-link-lib=dylib=stdc++"),
        ("macos", _) => println!("cargo:rustc-link-lib=dylib=c++"),
        _ => {}
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate apache2;

use apache2::{Request, Status};

apache2_module!(coming_soon_handler, c_coming_soon_handler, coming_soon_module, b"mod_coming_soon\0");

macro_rules! html_template {() => ("<!doctype html>

      <meta charset=\"utf-8\">
      <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">
      <title>PolyDraw – Coming Soon</title>
      <meta name=\"description\" content=\"PolyDraw website is coming soon\">
      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">

      <link href=\"https://fonts.googleapis.com/css?family=Fira+Sans:300,500\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Roboto+Condensed:400\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Khand:400\" rel=\"stylesheet\" type=\"text/css\">

PolyDraw

Open source software development

COMING SOON

in

000

days

                  In the meantime, please sign the international petition against

ORGAN HARVESTING

from Falun Gong practitioners in China!

                  JOIN THE PETITION!

")}

fn coming_soon_handler(r: &mut Request) -> Status {
   if r.handler().unwrap() != "coming-soon" || r.uri().unwrap() != "/" {
      return Status::DECLINED
   }

   r.set_content_type("text/html");

   r.write(format!(
      html_template!(),
      STYLESHEET
   ));

   Status::OK
}

const STYLESHEET: &'static str = "
   html, body {
      height: 100%;
      width: 100%;
      margin: 0;
   }

   body {
      display: block;
      font-family: 'Roboto Condensed', sans-serif;
      background-image: url(https://www.polydraw.com/img/mountain-mist.jpg);
      background-size: cover;
      background-repeat: no-repeat;
      background-attachment: fixed;
      background-position: right bottom;
   }

   main {
      display: block;
      position: relative;
      top: 50%;
      margin: 0 auto;
      -webkit-transform: translateY(-50%);
      -ms-transform: translateY(-50%);
      transform: translateY(-50%);
   }

   h1 {
      display: block;
      width: 60%;
      margin: 0 auto;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 500;
      font-size: 3.5em;
      color: white;
      text-align: center;
   }

   h2 {
      display: block;
      width: 70%;
      margin: -0.2em auto 0;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: 1.2em;
      color: #5b5b5b;
      text-align: center;
   }

   .coming-soon {
      display: block;
      width: 40%;
      margin: 2.5em auto .1em;
      font-size: 1.5em;
      color: white;
      text-align: center;
   }

   .in {
      display: block;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: .8em;
      font-style: italic;
      color: white;
      text-align: center;
   }

   .timer {
      display: block;
      width: 7em;
      text-align: center;
      border-style: solid none solid none;
      border-color: #e6e6e6;
      border-width: 1px;
      margin: 0 auto 1em;
   }

   .timer .number {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 4em;
      font-weight: bold;
      color: white;
      text-align: center;
   }

   .timer .days {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 1.5em;
      color: white;
      text-align: center;
      margin: -1em auto 0;
   }

   .urgent-call {
      margin: 3% auto 0;
   }

   .urgent-call .description {
      display: block;
      width: 100%;
      padding-top: 1em;
      padding-bottom: 1em;
      background: -webkit-linear-gradient(left, rgba(86,86,107,0), rgba(86,86,107,.25), rgba(86,86,107,0));
      background: linear-gradient(to right,rgba(86,86,107,0),rgba(86,86,107,.25),rgba(86,86,107,0));
   }

   .urgent-call .first, .urgent-call .second, .urgent-call .third {
      margin: 0 auto;
      width: 90%;
      color: white;
      font-size: 1em;
      text-align: center;
   }

   .urgent-call .first {
      margin-bottom: 0.25em;
   }

   .urgent-call .second {
      width: 100%;
      color: #9c292e;
      font-family: 'Khand', sans-serif;
      font-weight: bold;
      font-size: 1.2em;
   }

   .petition .button {
      display: block;
      width: 120px;
      margin: 1em auto 0;
      padding: 3px 6px;
      background: #829776;
      color: #ffffff;
      font-family: 'Fira Sans', sans-serif;
      font-size: .85em;
      font-weight: 300;
      text-align: center;
      text-decoration: none;
      border: solid #ffffff 1px;
      border-radius: 3px;
   }

   .petition .button:hover {
      background: #4d6b3c;
   }

   footer {
      display: table;
      position: fixed;
      width: 96%;
      bottom: 0;
      padding-left: 2%;
      padding-right: 2%;
   }

   .social {
      display: block;
      vertical-align: middle;
      float: right;
   }

   .social a {
      display: inline-block;
      width: 28px;
      height: 28px;
      background-repeat: no-repeat;
      opacity: .5;
      margin-left: .5em;
   }

   .social a:hover {
      opacity: .9;
   }

   .social a.facebook {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAG1BMVEUAAADY2NjY2NjY2NjY2NhGRkZqamqFhYWtra1jMrL/AAAACXRSTlMAPGaw//////9HdVBWAAAAp0lEQVQoz42TQRLDIAwDVyb/f3GxegAGmJC0PhkWge0RYoYQxuvGSGKkTu9wohW3vQj2yAQoR4Zwh3fWaYAODEJwQWNltqAKEJXShSV71dVWGJCJLuy6+MxFEKwN8uGSPGraml+uaG9s9RuqvVX8FLvSgqJ5PPysdPASP5SP1AS5O2IuEkHRcfCuCFSOt1Y3J5wGkW5O8IFmDg/daTPYH9Z8N/X5O3wBpdI+PxtA6DIAAAAASUVORK5CYII=);
   }

   .social a.twitter {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjV1dXY2NjY2NjY2NjY2NhHR0empqaQkJBtbW3Dw8PQfCyMAAAADHRSTlMAPPVmwKD////////J66Z0AAAA5UlEQVQoz32T0ZKFIAxDT1qc/f+/3VFo9wFQXL23D+oQGpJQxVXCCHJdmB+lFQCq17yDclsoonXYx9NZ+dPy7PQbBEBro/MFw0gwUPJSKRAUewOJiqEbZu5QAUyITQBbVgAPwHUA5OHQO6N4zOMsAFpKW89lAw8FgLW+6XB1Hz9KcuY6XuEjt12XqBKn2bGwgMcpfe7a/XFRYQ+uUzRY9wdE7/DfCdX0cZp5l2jt5FI46QC5F5M4Fl31e/AOmW9oDbB+c89S9klI7POYkIvf4aJd05do5Y6IZTQhYjqsqvE/yLff4Q+6BFspw2Tr1AAAAABJRU5ErkJggg==);
   }

   .social a.github {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjY2NjY2NjY2NjY2NhHR0ebm5u3t7dYWFh3d3dqampwrbVmAAAADHRSTlMAPGbxsP////////80TrKnAAAA4UlEQVQoz32TwW7DMAxDH+ns/z94tbhDpDRBi+lkSCBN0bR4lxAh98YcVgxAaec51NKNIj1eANjmyR+AA8CLZxmqkR8zwAQMEl9KAsExQy+RXaPqxXEBl9gidnZDowGu0olxvBvqcUTSOgmGKlhudeU6JJWLbmmWXwXs04Ga1UaqVK/z9LsuT9+2/XxxovWkFwB2pjfI7ZaB8L6Q53aFdw44UqZb8dyek0R4WMUa5iybIEvNuv83XqBnDLqqgiH59p7JmYTwCd0TE3KLaHPWO315ZiV1jyZUFLUdl2D99x3+AND/ZE+Y11fiAAAAAElFTkSuQmCC);
   }

   @media all and (max-width: 319px) {
      main {
         margin: auto 0;
      }

      h1 {
         margin: -7% auto 0;
         font-size: 1.6em;
      }

      h2 {
         margin: 0 auto;
         font-size: .8em;
      }

      .coming-soon {
         margin: .7em auto 0;
         font-size: .8em;
      }

      .in {
         font-size: .7em;
      }

      .timer {
         width: 3em;
         margin: 0 auto .2em;
      }

      .timer .number {
         font-size: 2em;
      }

      .timer .days {
         font-size: .75em;
      }

      .urgent-call {
         margin: 0 auto;
      }

      .urgent-call .description {
         font-size: 0.7em;
      }

      .petition .button {
         width: 120px;
         margin: 1em auto 0;
         padding: 3px;
         font-size: .6em;
      }
   }

   @media all and (min-width: 320px) and (max-width: 460px) {
      h1 {
         margin: 0 auto;
         font-size: 2.5em;
      }

      h2 {
         margin: 0 auto 2em;
         font-size: .9em;
      }

      .coming-soon {
         margin: 0 auto;
         font-size: 1.3em;
      }

      .timer {
         width: 5em;
         margin: 0 auto 1em;
      }

      .timer .number {
         font-size: 2.8em;
      }

      .timer .days {
         font-size: 1.1em;
      }

      .urgent-call .description {
         font-size: .85em;
      }

      .petition .button {
         width: 100px;
         margin: 1em auto 0;
         font-size: .6em;
      }
   }

   @media all and (min-width: 1600px) {
      h1 {
         font-size: 5em;
      }

      h2 {
         font-size: 1.7em;
      }

      .coming-soon {
         font-size: 2.25em;
      }

      .in {
         font-size: 1.2em;
      }

      .timer {
         width: 10em;
         margin: 0.5em auto 2em;
      }

      .timer .number {
         font-size: 5em;
      }

      .timer .days {
         font-size: 2.25em;
      }

      .urgent-call .description {
      }

      .urgent-call .first, .urgent-call .third {
         font-size: 1.5em;
      }

      .urgent-call .second {
         font-size: 1.8em;
      }

      .petition .button {
         width: 180px;
         margin: .8em auto 0;
         padding: 5px;
         font-size: 1.2em;
      }
   }
";
<commit_msg>Color adjustments on the coming soon page.<commit_after>#[macro_use]
extern crate apache2;

use apache2::{Request, Status};

apache2_module!(coming_soon_handler, c_coming_soon_handler, coming_soon_module, b"mod_coming_soon\0");

macro_rules! html_template {() => ("<!doctype html>

      <meta charset=\"utf-8\">
      <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">
      <title>PolyDraw – Coming Soon</title>
      <meta name=\"description\" content=\"PolyDraw website is coming soon\">
      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">

      <link href=\"https://fonts.googleapis.com/css?family=Fira+Sans:300,500\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Roboto+Condensed:400\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Khand:400\" rel=\"stylesheet\" type=\"text/css\">

PolyDraw

Open source software development

COMING SOON

in

000

days

                  In the meantime, please sign the international petition against

ORGAN HARVESTING

from Falun Gong practitioners in China!

                  JOIN THE PETITION!

")}

fn coming_soon_handler(r: &mut Request) -> Status {
   if r.handler().unwrap() != "coming-soon" || r.uri().unwrap() != "/" {
      return Status::DECLINED
   }

   r.set_content_type("text/html");

   r.write(format!(
      html_template!(),
      STYLESHEET
   ));

   Status::OK
}

const STYLESHEET: &'static str = "
   html, body {
      height: 100%;
      width: 100%;
      margin: 0;
   }

   body {
      display: block;
      font-family: 'Roboto Condensed', sans-serif;
      background-image: url(https://www.polydraw.com/img/mountain-mist.jpg);
      background-size: cover;
      background-repeat: no-repeat;
      background-attachment: fixed;
      background-position: right bottom;
   }

   main {
      display: block;
      position: relative;
      top: 50%;
      margin: 0 auto;
      -webkit-transform: translateY(-50%);
      -ms-transform: translateY(-50%);
      transform: translateY(-50%);
   }

   h1 {
      display: block;
      width: 60%;
      margin: 0 auto;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 500;
      font-size: 3.5em;
      color: white;
      text-align: center;
   }

   h2 {
      display: block;
      width: 70%;
      margin: -0.2em auto 0;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: 1.2em;
      color: #5b5b5b;
      text-align: center;
   }

   .coming-soon {
      display: block;
      width: 40%;
      margin: 2.5em auto .1em;
      font-size: 1.5em;
      color: white;
      text-align: center;
   }

   .in {
      display: block;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: .8em;
      font-style: italic;
      color: white;
      text-align: center;
   }

   .timer {
      display: block;
      width: 7em;
      text-align: center;
      border-style: solid none solid none;
      border-color: #e6e6e6;
      border-width: 1px;
      margin: 0 auto 1em;
   }

   .timer .number {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 4em;
      font-weight: bold;
      color: white;
      text-align: center;
   }

   .timer .days {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 1.5em;
      color: white;
      text-align: center;
      margin: -1em auto 0;
   }

   .urgent-call {
      margin: 3% auto 0;
   }

   .urgent-call .description {
      display: block;
      width: 100%;
      padding-top: 1em;
      padding-bottom: 1em;
      background: -webkit-linear-gradient(left, rgba(86,86,107,0), rgba(86,86,107,.25), rgba(86,86,107,0));
      background: linear-gradient(to right,rgba(86,86,107,0),rgba(86,86,107,.25),rgba(86,86,107,0));
   }

   .urgent-call .first, .urgent-call .second, .urgent-call .third {
      margin: 0 auto;
      width: 90%;
      color: white;
      font-size: 1em;
      text-align: center;
   }

   .urgent-call .first {
      margin-bottom: 0.5em;
   }

   .urgent-call .second {
      width: 100%;
      color: #e66f3f;
      font-family: 'Khand', sans-serif;
      font-weight: bold;
      font-size: 1.2em;
      text-shadow: 0px 1px 6px rgba(0, 0, 0, 0.3);
      letter-spacing: 0.1em;
   }

   .urgent-call .third {
      margin-top: 0.15em;
   }

   .petition .button {
      display: block;
      width: 120px;
      margin: 1em auto 0;
      padding: 3px 6px;
      background: #829776;
      color: #ffffff;
      font-family: 'Fira Sans', sans-serif;
      font-size: .85em;
      font-weight: 300;
      text-align: center;
      text-decoration: none;
      border: solid #ffffff 1px;
      border-radius: 3px;
   }

   .petition .button:hover {
      background: #4d6b3c;
   }

   footer {
      display: table;
      position: fixed;
      width: 96%;
      bottom: 0;
      padding-left: 2%;
      padding-right: 2%;
   }

   .social {
      display: block;
      vertical-align: middle;
      float: right;
   }

   .social a {
      display: inline-block;
      width: 28px;
      height: 28px;
      background-repeat: no-repeat;
      opacity: .5;
      margin-left: .5em;
   }

   .social a:hover {
      opacity: .9;
   }

   .social a.facebook {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAG1BMVEUAAADY2NjY2NjY2NjY2NhGRkZqamqFhYWtra1jMrL/AAAACXRSTlMAPGaw//////9HdVBWAAAAp0lEQVQoz42TQRLDIAwDVyb/f3GxegAGmJC0PhkWge0RYoYQxuvGSGKkTu9wohW3vQj2yAQoR4Zwh3fWaYAODEJwQWNltqAKEJXShSV71dVWGJCJLuy6+MxFEKwN8uGSPGraml+uaG9s9RuqvVX8FLvSgqJ5PPysdPASP5SP1AS5O2IuEkHRcfCuCFSOt1Y3J5wGkW5O8IFmDg/daTPYH9Z8N/X5O3wBpdI+PxtA6DIAAAAASUVORK5CYII=);
   }

   .social a.twitter {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjV1dXY2NjY2NjY2NjY2NhHR0empqaQkJBtbW3Dw8PQfCyMAAAADHRSTlMAPPVmwKD////////J66Z0AAAA5UlEQVQoz32T0ZKFIAxDT1qc/f+/3VFo9wFQXL23D+oQGpJQxVXCCHJdmB+lFQCq17yDclsoonXYx9NZ+dPy7PQbBEBro/MFw0gwUPJSKRAUewOJiqEbZu5QAUyITQBbVgAPwHUA5OHQO6N4zOMsAFpKW89lAw8FgLW+6XB1Hz9KcuY6XuEjt12XqBKn2bGwgMcpfe7a/XFRYQ+uUzRY9wdE7/DfCdX0cZp5l2jt5FI46QC5F5M4Fl31e/AOmW9oDbB+c89S9klI7POYkIvf4aJd05do5Y6IZTQhYjqsqvE/yLff4Q+6BFspw2Tr1AAAAABJRU5ErkJggg==);
   }

   .social a.github {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjY2NjY2NjY2NjY2NhHR0ebm5u3t7dYWFh3d3dqampwrbVmAAAADHRSTlMAPGbxsP////////80TrKnAAAA4UlEQVQoz32TwW7DMAxDH+ns/z94tbhDpDRBi+lkSCBN0bR4lxAh98YcVgxAaec51NKNIj1eANjmyR+AA8CLZxmqkR8zwAQMEl9KAsExQy+RXaPqxXEBl9gidnZDowGu0olxvBvqcUTSOgmGKlhudeU6JJWLbmmWXwXs04Ga1UaqVK/z9LsuT9+2/XxxovWkFwB2pjfI7ZaB8L6Q53aFdw44UqZb8dyek0R4WMUa5iybIEvNuv83XqBnDLqqgiH59p7JmYTwCd0TE3KLaHPWO315ZiV1jyZUFLUdl2D99x3+AND/ZE+Y11fiAAAAAElFTkSuQmCC);
   }

   @media all and (max-width: 319px) {
      main {
         margin: auto 0;
      }

      h1 {
         margin: -7% auto 0;
         font-size: 1.6em;
      }

      h2 {
         margin: 0 auto;
         font-size: .8em;
      }

      .coming-soon {
         margin: .7em auto 0;
         font-size: .8em;
      }

      .in {
         font-size: .7em;
      }

      .timer {
         width: 3em;
         margin: 0 auto .2em;
      }

      .timer .number {
         font-size: 2em;
      }

      .timer .days {
         font-size: .75em;
      }

      .urgent-call {
         margin: 0 auto;
      }

      .urgent-call .description {
         font-size: 0.7em;
      }

      .petition .button {
         width: 120px;
         margin: 1em auto 0;
         padding: 3px;
         font-size: .6em;
      }
   }

   @media all and (min-width: 320px) and (max-width: 460px) {
      h1 {
         margin: 0 auto;
         font-size: 2.5em;
      }

      h2 {
         margin: 0 auto 2em;
         font-size: .9em;
      }

      .coming-soon {
         margin: 0 auto;
         font-size: 1.3em;
      }

      .timer {
         width: 5em;
         margin: 0 auto 1em;
      }

      .timer .number {
         font-size: 2.8em;
      }

      .timer .days {
         font-size: 1.1em;
      }

      .urgent-call .description {
         font-size: .85em;
      }

      .petition .button {
         width: 100px;
         margin: 1em auto 0;
         font-size: .6em;
      }
   }

   @media all and (min-width: 1600px) {
      h1 {
         font-size: 5em;
      }

      h2 {
         font-size: 1.7em;
      }

      .coming-soon {
         font-size: 2.25em;
      }

      .in {
         font-size: 1.2em;
      }

      .timer {
         width: 10em;
         margin: 0.5em auto 2em;
      }

      .timer .number {
         font-size: 5em;
      }

      .timer .days {
         font-size: 2.25em;
      }

      .urgent-call .description {
      }

      .urgent-call .first, .urgent-call .third {
         font-size: 1.5em;
      }

      .urgent-call .second {
         font-size: 1.8em;
      }

      .petition .button {
         width: 180px;
         margin: .8em auto 0;
         padding: 5px;
         font-size: 1.2em;
      }
   }
";
<|endoftext|>


<commit_before>use nbody::NBodyBenchmark;
use rand::{self, Rng, SeedableRng};
use sdl;
use sdl::video::{SurfaceFlag, VideoFlag};
use sdl::event::{Event, Key};

pub fn visualize_benchmarks(num_bodies: usize) {
    let mut benchmark = NBodyBenchmark::new(num_bodies, &mut rand::thread_rng());

    sdl::init(&[sdl::InitFlag::Video]);
    sdl::wm::set_caption("nbody demo", "nbody");
    let screen = match sdl::video::set_video_mode(800, 600, 32,
                                                  &[SurfaceFlag::HWSurface],
                                                  &[VideoFlag::DoubleBuf]) {
        Ok(screen) => screen,
        Err(err) => panic!("failed to set video mode: {}", err)
    };

    let mut par_mode = true;

    loop {
        match sdl::event::poll_event() {
            Event::Quit => break,
            Event::None => { }
            Event::Key(k, _, _, _) if k == Key::Escape => break,
            _ => {}
        }

        let bodies = if par_mode {
            benchmark.tick_par()
        } else {
            benchmark.tick_seq()
        };

        let mut color_rng = rand::XorShiftRng::from_seed([0, 1, 2, 3]);
        screen.clear();
        for body in bodies {
            // Project 3d point onto 2d screen. I really ought to be using OpenGL.
            let b_z = -3000.0;
            let a_z = body.position.z;
            let x = (body.position.x) * b_z / a_z;
            let y = (body.position.y) * b_z / a_z;
            let size = 10.0 * b_z / a_z;
            screen.fill_rect(Some(sdl::Rect {
                x: (x as i16) + 400,
                y: (y as i16) + 300,
                w: size as u16,
                h: size as u16,
            }), color_rng.gen::<sdl::video::Color>());
        }

        screen.flip();
    }

    sdl::quit();
}

<commit_msg>Add FIXME.<commit_after>use nbody::NBodyBenchmark;
use rand::{self, Rng, SeedableRng};
use sdl;
use sdl::video::{SurfaceFlag, VideoFlag};
use sdl::event::{Event, Key};

pub fn visualize_benchmarks(num_bodies: usize) {
    let mut benchmark = NBodyBenchmark::new(num_bodies, &mut rand::thread_rng());

    sdl::init(&[sdl::InitFlag::Video]);
    sdl::wm::set_caption("nbody demo", "nbody");
    let screen = match sdl::video::set_video_mode(800, 600, 32,
                                                  &[SurfaceFlag::HWSurface],
                                                  &[VideoFlag::DoubleBuf]) {
        Ok(screen) => screen,
        Err(err) => panic!("failed to set video mode: {}", err)
    };

    let mut par_mode = true;

    loop {
        match sdl::event::poll_event() {
            Event::Quit => break,
            Event::None => { }
            Event::Key(k, _, _, _) if k == Key::Escape => break,
            _ => {}
        }

        let bodies = if par_mode {
            benchmark.tick_par()
        } else {
            benchmark.tick_seq()
        };

        // FIXME -- it'd be interesting to do this in parallel with
        // the actual construction of the next frame. I presume though
        // that this ought to be done on the main thread (I guess
        // that's a bit unclear).  That would be a use case for a
        // variant on join as described in #20.
        let mut color_rng = rand::XorShiftRng::from_seed([0, 1, 2, 3]);
        screen.clear();
        for body in bodies {
            // Project 3d point onto 2d screen. I really ought to be using OpenGL.
            let b_z = -3000.0;
            let a_z = body.position.z;
            let x = (body.position.x) * b_z / a_z;
            let y = (body.position.y) * b_z / a_z;
            let size = 10.0 * b_z / a_z;
            screen.fill_rect(Some(sdl::Rect {
                x: (x as i16) + 400,
                y: (y as i16) + 300,
                w: size as u16,
                h: size as u16,
            }), color_rng.gen::<sdl::video::Color>());
        }

        screen.flip();
    }

    sdl::quit();
}

<|endoftext|>


<commit_before>// rust - simulate occasional problematic (long blocking) requests for disk IO
// language version: 1.9.0
// to build: rustc http-threaded-simulated-disk-io-server.rs
// NOTE: this is my first Rust program, so much of it is probably crappy

use std::io::Read;
use std::io::Write;
use std::net::Shutdown;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Duration;

const READ_TIMEOUT_SECS: u32 = 4;
const LISTEN_BACKLOG: u32 = 500;

const SERVER_NAME = "http-threaded-simulated-disk-io-server.rs";
const HTTP_STATUS_OK: =  "200 OK";
const HTTP_STATUS_TIMEOUT: = "408 TIMEOUT";
const HTTP_STATUS_BAD_REQUEST: = "400 BAD REQUEST";

fn current_time_millis() -> u64 {
    //TODO: time::now()
    return 0;
}

fn simulated_file_read(disk_read_time_ms: u64) {
    thread::sleep(Duration::from_millis(disk_read_time_ms));
}

fn handle_socket_request(stream: &mut TcpStream,
                         receipt_timestamp: u64) {
    // read request from client
    let mut request_buffer = [0; 1024];
    let mut rc = HTTP_STATUS_OK;
    let mut file_path = "";
    let mut tot_request_time_ms: u64 = 0;

    if stream.read(&mut request_buffer).unwrap() > 0 {
        let request_text = str::from_utf8(&request_buffer).unwrap();
        // did we get anything from client?
        if request_text.trim().len() > 0 {
            // determine how long the request has waited in queue
            let start_processing_timestamp = current_time_millis();
            let server_queue_time_ms =
                start_processing_timestamp - receipt_timestamp;
            let x = server_queue_time_ms / 1000;
            let server_queue_time_secs = x as u32;

            let mut disk_read_time_ms: u64 = 0;

            // has this request already timed out?
            if server_queue_time_secs >= READ_TIMEOUT_SECS {
                println!("timeout (queue)");
                rc = HTTP_STATUS_TIMEOUT;
            } else {
                let line_tokens: Vec<&str> = request_text.split(' ').collect();
                if line_tokens.len() > 1 {
                    let request_method = line_tokens[0];
                    let args_text = line_tokens[1];
                    let fields: Vec<&str> = args_text.split(',').collect();
                    if fields.len() == 3 {
                        let parse_rc_result = fields[0].parse();
                        match parse_rc_result {
                            Err(_) => {},
                            Ok(rc_input) => {
                                let parse_time_result = fields[1].parse();
                                match parse_time_result {
                                    Err(_) => {},
                                    Ok(req_response_time_ms) => {
                                        //rc = rc_input;
                                        disk_read_time_ms = req_response_time_ms;
                                        file_path = fields[2];
                                        simulated_file_read(disk_read_time_ms);
                                    }
                                }
                            }
                        }
                    } else {
                        // we didn't get the 3 input fields as expected
                        rc = HTTP_STATUS_BAD_REQUEST;
                    }
                } else {
                    // we didn't get the HTTP request line as expected
                    rc = HTTP_STATUS_BAD_REQUEST;
                }
            }
        } else {
            // we didn't get any input
            rc = HTTP_STATUS_BAD_REQUEST;
        }

        // total request time is sum of time spent in queue and the
        // simulated disk read time
        tot_request_time_ms =
            queue_time_ms + disk_read_time_ms;
    } else {
        // read of request failed
        rc = HTTP_STATUS_BAD_REQUEST;
        tot_request_time_ms = 0;
        file_path = "";
    }

    // create response
    let response_body = format!("{0},{1}",
        tot_request_time_ms,
        file_path);

    let response_headers = format!("",
                                   rc,
                                   SERVER_NAME,
                                   response_body.length);

    // return response to client
    stream.write_all(response_headers.as_bytes()).unwrap();
    stream.write_all(response_body.as_bytes()).unwrap();

    let _ = stream.shutdown(Shutdown::Both);
}

fn main() {
    let server_port = 7000;
    //TODO: build string using server_port
    let listener = TcpListener::bind("127.0.0.1:7000").unwrap();
    println!("server listening on port {0}", server_port);

    for stream in listener.incoming() {
        match stream {
            Err(_) => {},
            Ok(mut stream) => {
                let receipt_timestamp = current_time_millis();
                thread::spawn(move|| {
                    handle_socket_request(&mut stream, receipt_timestamp);
                });
            }
        }
    }
}

<commit_msg>completed http rust<commit_after>// rust - simulate occasional problematic (long blocking) requests for disk IO
// language version: 1.9.0
// to build: rustc http-threaded-simulated-disk-io-server.rs
// NOTE: this is my first Rust program, so much of it is probably crappy

use std::io::Read;
use std::io::Write;
use std::net::Shutdown;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Duration;

const READ_TIMEOUT_SECS: u32 = 4;
//const LISTEN_BACKLOG: u32 = 500;

const SERVER_NAME: &'static str = "http-threaded-simulated-disk-io-server.rs";
const HTTP_STATUS_OK: &'static str =  "200 OK";
const HTTP_STATUS_TIMEOUT: &'static str = "408 TIMEOUT";
const HTTP_STATUS_BAD_REQUEST: &'static str = "400 BAD REQUEST";

fn current_time_millis() -> u64 {
    //TODO: time::now()
    return 0;
}

fn simulated_file_read(disk_read_time_ms: u64) {
    thread::sleep(Duration::from_millis(disk_read_time_ms));
}

fn handle_socket_request(stream: &mut TcpStream,
                         receipt_timestamp: u64) {
    // read request from client
    let mut request_buffer = [0; 1024];
    let mut rc = HTTP_STATUS_OK;
    let mut file_path = "";
    let tot_request_time_ms: u64;
    let mut server_queue_time_ms: u64 = 0;
    let mut disk_read_time_ms: u64 = 0;

    if stream.read(&mut request_buffer).unwrap() > 0 {
        let request_text = str::from_utf8(&request_buffer).unwrap();
        // did we get anything from client?
        if request_text.trim().len() > 0 {
            // determine how long the request has waited in queue
            let start_processing_timestamp = current_time_millis();
            server_queue_time_ms =
                start_processing_timestamp - receipt_timestamp;
            let x = server_queue_time_ms / 1000;
            let server_queue_time_secs = x as u32;

            // has this request already timed out?
            if server_queue_time_secs >= READ_TIMEOUT_SECS {
                println!("timeout (queue)");
                rc = HTTP_STATUS_TIMEOUT;
            } else {
                let line_tokens: Vec<&str> = request_text.split(' ').collect();
                if line_tokens.len() > 1 {
                    //let request_method = line_tokens[0];
                    let args_text = line_tokens[1];
                    let http_status_code: u32;
                    let fields: Vec<&str> = args_text.split(',').collect();
                    if fields.len() == 3 {
                        let parse_rc_result = fields[0].parse();
                        match parse_rc_result {
                            Err(_) => {},
                            Ok(rc_input) => {
                                let parse_time_result = fields[1].parse();
                                match parse_time_result {
                                    Err(_) => {},
                                    Ok(req_response_time_ms) => {
                                        http_status_code = rc_input;
                                        if http_status_code > 0 {
                                            disk_read_time_ms = req_response_time_ms;
                                            file_path = fields[2];
                                            simulated_file_read(disk_read_time_ms);
                                        } else {
                                            rc = HTTP_STATUS_BAD_REQUEST;
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        // we didn't get the 3 input fields as expected
                        rc = HTTP_STATUS_BAD_REQUEST;
                    }
                } else {
                    // we didn't get the HTTP request line as expected
                    rc = HTTP_STATUS_BAD_REQUEST;
                }
            }
        } else {
            // we didn't get any input
            rc = HTTP_STATUS_BAD_REQUEST;
        }

        // total request time is sum of time spent in queue and the
        // simulated disk read time
        tot_request_time_ms =
            server_queue_time_ms + disk_read_time_ms;
    } else {
        // read of request failed
        rc = HTTP_STATUS_BAD_REQUEST;
        tot_request_time_ms = 0;
        file_path = "";
    }

    // create response
    let response_body = format!("{0},{1}",
        tot_request_time_ms,
        file_path);

    let response_headers = format!("HTTP/1.1 {0}\n \
                                   Server: {1}\n \
                                   Content-Length: {2}\n \
                                   Connection: close\n \
                                   \n",
                                   rc,
                                   SERVER_NAME,
                                   response_body.len());

    // return response to client
    stream.write_all(response_headers.as_bytes()).unwrap();
    stream.write_all(response_body.as_bytes()).unwrap();

    let _ = stream.shutdown(Shutdown::Both);
}

fn main() {
    let server_port = 7000;
    //TODO: build string using server_port
    let listener = TcpListener::bind("127.0.0.1:7000").unwrap();
    println!("server listening on port {0}", server_port);

    for stream in listener.incoming() {
        match stream {
            Err(_) => {},
            Ok(mut stream) => {
                let receipt_timestamp = current_time_millis();
                thread::spawn(move|| {
                    handle_socket_request(&mut stream, receipt_timestamp);
                });
            }
        }
    }
}

<|endoftext|>


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

extern crate oak_tests;

use crate::OakChannelLogger;
use log::{Level, LevelFilter, Log, Metadata, Record};
use oak_tests::last_message_as_string;

#[test]
fn test_enabled() {
    let x = OakChannelLogger {};
    struct T {
        l: Level,
        max: LevelFilter,
        want: bool,
    };
    let tests = vec![
        T {
            l: Level::Debug,
            max: LevelFilter::Debug,
            want: true,
        },
        T {
            l: Level::Error,
            max: LevelFilter::Debug,
            want: true,
        },
        T {
            l: Level::Trace,
            max: LevelFilter::Debug,
            want: false,
        },
    ];
    for test in &tests {
        let m = Metadata::builder().level(test.l).target("test").build();
        log::set_max_level(test.max);
        assert_eq!(test.want, x.enabled(&m));
    }
}

#[test]
fn test_log() {
    let logger = OakChannelLogger {};
    let trace = Metadata::builder()
        .level(Level::Trace)
        .target("test")
        .build();
    let r1 = Record::builder()
        .metadata(trace)
        .args(format_args!("Detailed trace"))
        .line(Some(433))
        .file(Some("app.rs"))
        .module_path(Some("server"))
        .build();
    logger.log(&r1);
    assert_eq!("", last_message_as_string());

    let error = Metadata::builder()
        .level(Level::Error)
        .target("test")
        .build();
    let r2 = Record::builder()
        .metadata(error)
        .args(format_args!("Error!"))
        .line(Some(433))
        .file(Some("app.rs"))
        .module_path(Some("server"))
        .build();
    logger.log(&r2);
    assert_eq!("ERROR  app.rs : 433 : Error!\n", last_message_as_string());
}

#[test]
fn test_flush() {
    let x = OakChannelLogger {};
    x.flush(); // Purely for coverage
}
<commit_msg>Clear channel state before oak_log test<commit_after>//
// Copyright 2019 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

extern crate oak_tests;

use crate::OakChannelLogger;
use log::{Level, LevelFilter, Log, Metadata, Record};
use oak_tests::last_message_as_string;

#[test]
fn test_enabled() {
    let x = OakChannelLogger {};
    struct T {
        l: Level,
        max: LevelFilter,
        want: bool,
    };
    let tests = vec![
        T {
            l: Level::Debug,
            max: LevelFilter::Debug,
            want: true,
        },
        T {
            l: Level::Error,
            max: LevelFilter::Debug,
            want: true,
        },
        T {
            l: Level::Trace,
            max: LevelFilter::Debug,
            want: false,
        },
    ];
    for test in &tests {
        let m = Metadata::builder().level(test.l).target("test").build();
        log::set_max_level(test.max);
        assert_eq!(test.want, x.enabled(&m));
    }
}

#[test]
fn test_log() {
    oak_tests::reset_channels();
    let logger = OakChannelLogger {};
    let trace = Metadata::builder()
        .level(Level::Trace)
        .target("test")
        .build();
    let r1 = Record::builder()
        .metadata(trace)
        .args(format_args!("Detailed trace"))
        .line(Some(433))
        .file(Some("app.rs"))
        .module_path(Some("server"))
        .build();
    logger.log(&r1);
    assert_eq!("", last_message_as_string());

    let error = Metadata::builder()
        .level(Level::Error)
        .target("test")
        .build();
    let r2 = Record::builder()
        .metadata(error)
        .args(format_args!("Error!"))
        .line(Some(433))
        .file(Some("app.rs"))
        .module_path(Some("server"))
        .build();
    logger.log(&r2);
    assert_eq!("ERROR  app.rs : 433 : Error!\n", last_message_as_string());
}

#[test]
fn test_flush() {
    let x = OakChannelLogger {};
    x.flush(); // Purely for coverage
}
<|endoftext|>


<commit_before>use level::*;
use std::f32;

pub fn ai_step(level : &mut Level, player_pos: (i32,i32)) {
    let mut x = 0;
    let mut y = 0;
    let mut enemies = Vec::with_capacity(16);

    for line in &level.tiles {
        for tile in line {
            match tile.entity {
                Some(Entity::Dragon{..}) => {
                    enemies.push((x,y));
                },
                _ => {}
            }
            x+=1;
        }
        y+=1;
        x=0;
    }

    let (px, py) = player_pos;
    for e in enemies {
        let (x,y) = e;
        let dx = (px-x) as f32;
        let dy = (py-y) as f32;
        let distance = (dx*dx + dy*dy).sqrt();

        if distance<6f32 {
            let dir = if dx<0f32 {
                Direction::Left
            } else if dx>0f32 {
                Direction::Right
            } else if dy<0f32 {
                Direction::Up
            } else {
                Direction::Down
            };
            level.interact((x,y), dir);
        }
    }
}
<commit_msg>removed unused import<commit_after>use level::*;

pub fn ai_step(level : &mut Level, player_pos: (i32,i32)) {
    let mut x = 0;
    let mut y = 0;
    let mut enemies = Vec::with_capacity(16);

    for line in &level.tiles {
        for tile in line {
            match tile.entity {
                Some(Entity::Dragon{..}) => {
                    enemies.push((x,y));
                },
                _ => {}
            }
            x+=1;
        }
        y+=1;
        x=0;
    }

    let (px, py) = player_pos;
    for e in enemies {
        let (x,y) = e;
        let dx = (px-x) as f32;
        let dy = (py-y) as f32;
        let distance = (dx*dx + dy*dy).sqrt();

        if distance<6f32 {
            let dir = if dx<0f32 {
                Direction::Left
            } else if dx>0f32 {
                Direction::Right
            } else if dy<0f32 {
                Direction::Up
            } else {
                Direction::Down
            };
            level.interact((x,y), dir);
        }
    }
}
<|endoftext|>


<commit_before>use std::ffi::c_void;
use std::fmt::{self, Debug};
use std::marker::PhantomData;
use std::slice;

use libc::iovec;

/// This type is essentialy `std::io::IoSliceMut`, and guaranteed to be ABI-compatible with
/// `libc::iovec`; however, it does NOT automatically deref to `&mut [u8]`, which is critical
/// because it can point to guest memory. (Guest memory is implicitly mutably borrowed by the
/// guest, so another mutable borrow would violate Rust assumptions about references.)
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct IoSliceMut<'a> {
    iov: iovec,
    phantom: PhantomData<&'a mut [u8]>,
}

impl<'a> IoSliceMut<'a> {
    pub fn new(buf: &mut [u8]) -> IoSliceMut<'a> {
        // Safe because buf's memory is of the supplied length, and
        // guaranteed to exist for the lifetime of the returned value.
        unsafe { Self::from_raw_parts(buf.as_mut_ptr(), buf.len()) }
    }

    /// Creates a `IoSliceMut` from a pointer and a length.
    ///
    /// # Safety
    ///
    /// In order to use this method safely, `addr` must be valid for reads and writes of `len` bytes
    /// and should live for the entire duration of lifetime `'a`.
    pub unsafe fn from_raw_parts(addr: *mut u8, len: usize) -> IoSliceMut<'a> {
        IoSliceMut {
            iov: iovec {
                iov_base: addr as *mut c_void,
                iov_len: len,
            },
            phantom: PhantomData,
        }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.iov.iov_len as usize
    }

    #[inline]
    pub fn as_iobuf(&self) -> libc::iovec {
        self.iov
    }

    /// Gets a const pointer to this slice's memory.
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        self.iov.iov_base as *const u8
    }

    /// Gets a mutable pointer to this slice's memory.
    #[inline]
    pub fn as_mut_ptr(&self) -> *mut u8 {
        self.iov.iov_base as *mut u8
    }

    /// Converts a slice of `IoSliceMut`s into a slice of `iovec`s.
    #[allow(clippy::wrong_self_convention)]
    #[inline]
    pub fn as_iobufs<'slice>(iovs: &'slice [IoSliceMut<'_>]) -> &'slice [iovec] {
        // Safe because `IoSliceMut` is ABI-compatible with `iovec`.
        unsafe { slice::from_raw_parts(iovs.as_ptr() as *const libc::iovec, iovs.len()) }
    }
}

struct DebugIovec(iovec);
impl Debug for DebugIovec {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("iovec")
            .field("iov_base", &self.0.iov_base)
            .field("iov_len", &self.0.iov_len)
            .finish()
    }
}

impl<'a> Debug for IoSliceMut<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("IoSliceMut")
            .field("iov", &DebugIovec(self.iov))
            .field("phantom", &self.phantom)
            .finish()
    }
}
<commit_msg>data_model: Implement Send + Sync for IoSliceMut<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::ffi::c_void;
use std::fmt::{self, Debug};
use std::marker::PhantomData;
use std::slice;

use libc::iovec;

/// This type is essentialy `std::io::IoSliceMut`, and guaranteed to be ABI-compatible with
/// `libc::iovec`; however, it does NOT automatically deref to `&mut [u8]`, which is critical
/// because it can point to guest memory. (Guest memory is implicitly mutably borrowed by the
/// guest, so another mutable borrow would violate Rust assumptions about references.)
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct IoSliceMut<'a> {
    iov: iovec,
    phantom: PhantomData<&'a mut [u8]>,
}

impl<'a> IoSliceMut<'a> {
    pub fn new(buf: &mut [u8]) -> IoSliceMut<'a> {
        // Safe because buf's memory is of the supplied length, and
        // guaranteed to exist for the lifetime of the returned value.
        unsafe { Self::from_raw_parts(buf.as_mut_ptr(), buf.len()) }
    }

    /// Creates a `IoSliceMut` from a pointer and a length.
    ///
    /// # Safety
    ///
    /// In order to use this method safely, `addr` must be valid for reads and writes of `len` bytes
    /// and should live for the entire duration of lifetime `'a`.
    pub unsafe fn from_raw_parts(addr: *mut u8, len: usize) -> IoSliceMut<'a> {
        IoSliceMut {
            iov: iovec {
                iov_base: addr as *mut c_void,
                iov_len: len,
            },
            phantom: PhantomData,
        }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.iov.iov_len as usize
    }

    #[inline]
    pub fn as_iobuf(&self) -> libc::iovec {
        self.iov
    }

    /// Gets a const pointer to this slice's memory.
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        self.iov.iov_base as *const u8
    }

    /// Gets a mutable pointer to this slice's memory.
    #[inline]
    pub fn as_mut_ptr(&self) -> *mut u8 {
        self.iov.iov_base as *mut u8
    }

    /// Converts a slice of `IoSliceMut`s into a slice of `iovec`s.
    #[allow(clippy::wrong_self_convention)]
    #[inline]
    pub fn as_iobufs<'slice>(iovs: &'slice [IoSliceMut<'_>]) -> &'slice [iovec] {
        // Safe because `IoSliceMut` is ABI-compatible with `iovec`.
        unsafe { slice::from_raw_parts(iovs.as_ptr() as *const libc::iovec, iovs.len()) }
    }
}

// It's safe to implement Send + Sync for this type for the same reason that `std::io::IoSliceMut`
// is Send + Sync. Internally, it contains a pointer and a length. The integer length is safely Send
// + Sync.  There's nothing wrong with sending a pointer between threads and de-referencing the
// pointer requires an unsafe block anyway. See also https://github.com/rust-lang/rust/pull/70342.
unsafe impl<'a> Send for IoSliceMut<'a> {}
unsafe impl<'a> Sync for IoSliceMut<'a> {}

struct DebugIovec(iovec);
impl Debug for DebugIovec {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("iovec")
            .field("iov_base", &self.0.iov_base)
            .field("iov_len", &self.0.iov_len)
            .finish()
    }
}

impl<'a> Debug for IoSliceMut<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("IoSliceMut")
            .field("iov", &DebugIovec(self.iov))
            .field("phantom", &self.phantom)
            .finish()
    }
}
<|endoftext|>