<commit_before>//! Performs cached merkle-hashing adhering to the Ethereum 2.0 specification defined
//! [here](https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/simple-serialize.md#merkleization).
//!
//! Caching allows for reduced hashing when some object has only been partially modified. This
//! gives significant CPU-time savings (at the cost of additional storage). For example,
//! determining the root of a list of 1024 items with a single modification has been observed to
//! run in 1/25th of the time of a full merkle hash.
//!
//!
//! # Example:
//!
//! ```
//! use cached_tree_hash::TreeHashCache;
//! use tree_hash_derive::{TreeHash, CachedTreeHash};
//!
//! #[derive(TreeHash, CachedTreeHash)]
//! struct Foo {
//!     bar: u64,
//!     baz: Vec<u64>
//! }
//!
//! let mut foo = Foo {
//!     bar: 1,
//!     baz: vec![0, 1, 2]
//! };
//!
//! let mut cache = TreeHashCache::new(&foo).unwrap();
//!
//! foo.baz[1] = 0;
//!
//! cache.update(&foo).unwrap();
//!
//! println!("Root is: {:?}", cache.tree_hash_root().unwrap());
//! ```

use hashing::hash;
use std::ops::Range;
use tree_hash::{TreeHash, TreeHashType, BYTES_PER_CHUNK, HASHSIZE};

mod btree_overlay;
mod errors;
mod impls;
pub mod merkleize;
mod resize;
mod tree_hash_cache;

pub use btree_overlay::{BTreeOverlay, BTreeSchema};
pub use errors::Error;
pub use impls::vec;
pub use tree_hash_cache::TreeHashCache;

pub trait CachedTreeHash: TreeHash {
    fn tree_hash_cache_schema(&self, depth: usize) -> BTreeSchema;

    fn num_tree_hash_cache_chunks(&self) -> usize {
        self.tree_hash_cache_schema(0).into_overlay(0).num_chunks()
    }

    fn new_tree_hash_cache(&self, depth: usize) -> Result<TreeHashCache, Error>;

    fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error>;
}

/// Implements `CachedTreeHash` on `$type`, where `$type` is a fixed-length vector and each item in
/// the `$type` is encoded as bytes using `ssz_encode`.
#[macro_export]
macro_rules! cached_tree_hash_ssz_encoding_as_vector {
    ($type: ident, $num_bytes: expr) => {
        impl cached_tree_hash::CachedTreeHash for $type {
            fn new_tree_hash_cache(
                &self,
                depth: usize,
            ) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
                let (cache, _schema) =
                    cached_tree_hash::vec::new_tree_hash_cache(&ssz::ssz_encode(self), depth)?;

                Ok(cache)
            }

            fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
                let lengths =
                    vec![1; cached_tree_hash::merkleize::num_unsanitized_leaves($num_bytes)];
                cached_tree_hash::BTreeSchema::from_lengths(depth, lengths)
            }

            fn update_tree_hash_cache(
                &self,
                cache: &mut cached_tree_hash::TreeHashCache,
            ) -> Result<(), cached_tree_hash::Error> {
                cached_tree_hash::vec::update_tree_hash_cache(&ssz::ssz_encode(self), cache)?;

                Ok(())
            }
        }
    };
}

/// Implements `CachedTreeHash` on `$type`, where `$type` is a variable-length list and each item
/// in `$type` is encoded as bytes by calling `item.as_bytes()`.
#[macro_export]
macro_rules! cached_tree_hash_bytes_as_list {
    ($type: ident) => {
        impl cached_tree_hash::CachedTreeHash for $type {
            fn new_tree_hash_cache(
                &self,
                depth: usize,
            ) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
                let bytes = self.to_bytes();

                let (mut cache, schema) =
                    cached_tree_hash::vec::new_tree_hash_cache(&bytes, depth)?;

                cache.add_length_nodes(schema.into_overlay(0).chunk_range(), bytes.len())?;

                Ok(cache)
            }

            fn num_tree_hash_cache_chunks(&self) -> usize {
                // Add two extra nodes to cater for the node before and after to allow mixing-in length.
                cached_tree_hash::BTreeOverlay::new(self, 0, 0).num_chunks() + 2
            }

            fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
                let bytes = self.to_bytes();
                cached_tree_hash::vec::produce_schema(&bytes, depth)
            }

            fn update_tree_hash_cache(
                &self,
                cache: &mut cached_tree_hash::TreeHashCache,
            ) -> Result<(), cached_tree_hash::Error> {
                let bytes = self.to_bytes();

                // Skip the length-mixed-in root node.
                cache.chunk_index += 1;

                // Update the cache, returning the new overlay.
                let new_overlay = cached_tree_hash::vec::update_tree_hash_cache(&bytes, cache)?;

                // Mix in length
                cache.mix_in_length(new_overlay.chunk_range(), bytes.len())?;

                // Skip an extra node to clear the length node.
                cache.chunk_index += 1;

                Ok(())
            }
        }
    };
}
<commit_msg>Very small wording/typo fixes for docs.<commit_after>//! Performs cached merkle-hashing adhering to the Ethereum 2.0 specification defined
//! [here](https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/simple-serialize.md#merkleization).
//!
//! Caching allows for reduced hashing when some object has only been partially modified, which
//! consumes less CPU-time at the cost of additional storage. For example,
//! determining the root of a list of 1024 items with a single modification has been observed to
//! run in 1/25th of the time of a full merkle hash.
//!
//!
//! # Example:
//!
//! ```
//! use cached_tree_hash::TreeHashCache;
//! use tree_hash_derive::{TreeHash, CachedTreeHash};
//!
//! #[derive(TreeHash, CachedTreeHash)]
//! struct Foo {
//!     bar: u64,
//!     baz: Vec<u64>
//! }
//!
//! let mut foo = Foo {
//!     bar: 1,
//!     baz: vec![0, 1, 2]
//! };
//!
//! let mut cache = TreeHashCache::new(&foo).unwrap();
//!
//! foo.baz[1] = 0;
//!
//! cache.update(&foo).unwrap();
//!
//! println!("Root is: {:?}", cache.tree_hash_root().unwrap());
//! ```

use hashing::hash;
use std::ops::Range;
use tree_hash::{TreeHash, TreeHashType, BYTES_PER_CHUNK, HASHSIZE};

mod btree_overlay;
mod errors;
mod impls;
pub mod merkleize;
mod resize;
mod tree_hash_cache;

pub use btree_overlay::{BTreeOverlay, BTreeSchema};
pub use errors::Error;
pub use impls::vec;
pub use tree_hash_cache::TreeHashCache;

pub trait CachedTreeHash: TreeHash {
    fn tree_hash_cache_schema(&self, depth: usize) -> BTreeSchema;

    fn num_tree_hash_cache_chunks(&self) -> usize {
        self.tree_hash_cache_schema(0).into_overlay(0).num_chunks()
    }

    fn new_tree_hash_cache(&self, depth: usize) -> Result<TreeHashCache, Error>;

    fn update_tree_hash_cache(&self, cache: &mut TreeHashCache) -> Result<(), Error>;
}

/// Implements `CachedTreeHash` on `$type`, where `$type` is a fixed-length vector and each item in
/// the `$type` is encoded as bytes using `ssz_encode`.
#[macro_export]
macro_rules! cached_tree_hash_ssz_encoding_as_vector {
    ($type: ident, $num_bytes: expr) => {
        impl cached_tree_hash::CachedTreeHash for $type {
            fn new_tree_hash_cache(
                &self,
                depth: usize,
            ) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
                let (cache, _schema) =
                    cached_tree_hash::vec::new_tree_hash_cache(&ssz::ssz_encode(self), depth)?;

                Ok(cache)
            }

            fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
                let lengths =
                    vec![1; cached_tree_hash::merkleize::num_unsanitized_leaves($num_bytes)];
                cached_tree_hash::BTreeSchema::from_lengths(depth, lengths)
            }

            fn update_tree_hash_cache(
                &self,
                cache: &mut cached_tree_hash::TreeHashCache,
            ) -> Result<(), cached_tree_hash::Error> {
                cached_tree_hash::vec::update_tree_hash_cache(&ssz::ssz_encode(self), cache)?;

                Ok(())
            }
        }
    };
}

/// Implements `CachedTreeHash` on `$type`, where `$type` is a variable-length list and each item
/// in `$type` is encoded as bytes by calling `item.to_bytes()`.
#[macro_export]
macro_rules! cached_tree_hash_bytes_as_list {
    ($type: ident) => {
        impl cached_tree_hash::CachedTreeHash for $type {
            fn new_tree_hash_cache(
                &self,
                depth: usize,
            ) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
                let bytes = self.to_bytes();

                let (mut cache, schema) =
                    cached_tree_hash::vec::new_tree_hash_cache(&bytes, depth)?;

                cache.add_length_nodes(schema.into_overlay(0).chunk_range(), bytes.len())?;

                Ok(cache)
            }

            fn num_tree_hash_cache_chunks(&self) -> usize {
                // Add two extra nodes to cater for the node before and after to allow mixing-in length.
                cached_tree_hash::BTreeOverlay::new(self, 0, 0).num_chunks() + 2
            }

            fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
                let bytes = self.to_bytes();
                cached_tree_hash::vec::produce_schema(&bytes, depth)
            }

            fn update_tree_hash_cache(
                &self,
                cache: &mut cached_tree_hash::TreeHashCache,
            ) -> Result<(), cached_tree_hash::Error> {
                let bytes = self.to_bytes();

                // Skip the length-mixed-in root node.
                cache.chunk_index += 1;

                // Update the cache, returning the new overlay.
                let new_overlay = cached_tree_hash::vec::update_tree_hash_cache(&bytes, cache)?;

                // Mix in length
                cache.mix_in_length(new_overlay.chunk_range(), bytes.len())?;

                // Skip an extra node to clear the length node.
                cache.chunk_index += 1;

                Ok(())
            }
        }
    };
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt;
use std::fs;
use std::io::Read;
use std::io::Write;
use std::io;
use std::path;

use regex;

use rustc_serialize::json;
use rustc_serialize::Decodable;
use rustc_serialize::Encodable;

// FIXME: replace with quick_error?
#[derive(Debug)]
pub struct ServerError {
    pub error: Box<Error + Send>
}

impl fmt::Display for ServerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.description().fmt(f)
    }
}

impl Error for ServerError {
    fn description(&self) -> &str { self.error.description() }
    fn cause(&self) -> Option<&Error> { Some(&*self.error) }
}

impl From<io::Error> for ServerError {
    fn from(e: io::Error) -> ServerError {
        ServerError { error: Box::new(e) }
    }
}

impl From<json::DecoderError> for ServerError {
    fn from(e: json::DecoderError) -> ServerError {
        ServerError { error: Box::new(e) }
    }
}

impl From<json::EncoderError> for ServerError {
    fn from(e: json::EncoderError) -> ServerError {
        ServerError { error: Box::new(e) }
    }
}

pub fn safe_join<P: AsRef<path::Path>, Q: AsRef<path::Path>>(base: P, user_input: Q) -> Option<path::PathBuf> {
    let a = base.as_ref();
    let b = user_input.as_ref();

    let rv = a.join(b);
    if rv.starts_with(a) && rv.is_absolute() {
        Some(rv)
    } else {
        None
    }
}

pub fn prompt<T: AsRef<str>>(text: T) -> String {
    let mut stdout = io::stdout();
    stdout.write(text.as_ref().as_bytes()).unwrap();
    stdout.flush().unwrap();

    let stdin = io::stdin();
    let mut response = String::new();
    stdin.read_line(&mut response).unwrap();
    if response.ends_with("\n") { response.pop(); }
    response
}

pub fn double_prompt<T: AsRef<str>>(text: T) -> String {
    let again_text = {
        let mut x = "(confirm) ".to_string();
        x.push_str(text.as_ref());
        x
    };

    loop {
        let first = prompt(text.as_ref());
        let second = prompt(&again_text[..]);
        if first == second {
            return first;
        } else {
            println!("Inputs don't match. Try again.");
        }
    }
}

pub fn prompt_confirm<T: AsRef<str>>(question: T, default: bool) -> bool {
    let mut question = question.as_ref().to_owned();
    question.push_str(" ");
    question.push_str(if default { "[Y/n]" } else { "[y/N]" });
    question.push_str(" ");
    loop {
        let response = prompt(&question[..]);
        return match response.trim() {
            "y" | "Y" => true,
            "n" | "N" => false,
            "" => default,
            _ => {
                println!("Invalid answer.");
                continue;
            }
        };
    };
}

pub fn read_json_file<T: Decodable, P: AsRef<path::Path>>(p: P) -> Result<T, ServerError> {
    let mut f = try!(fs::File::open(p.as_ref()));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    let rv = try!(json::decode(&s));
    Ok(rv)
}

pub fn write_json_file<T: Encodable, P: AsRef<path::Path>>(t: T, p: P) -> Result<(), ServerError> {
    let mut f = try!(fs::File::create(p.as_ref()));
    let data = try!(json::encode(&t));
    try!(f.write(&data.into_bytes()));
    Ok(())
}

pub fn is_safe_identifier(string: &str) -> bool {
    regex::Regex::new(r"^[A-Za-z0-9_-]+$").unwrap().is_match(string)
}
<commit_msg>remove fixme<commit_after>use std::error::Error;
use std::fmt;
use std::fs;
use std::io::Read;
use std::io::Write;
use std::io;
use std::path;

use regex;

use rustc_serialize::json;
use rustc_serialize::Decodable;
use rustc_serialize::Encodable;

#[derive(Debug)]
pub struct ServerError {
    pub error: Box<Error + Send>
}

impl fmt::Display for ServerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.description().fmt(f)
    }
}

impl Error for ServerError {
    fn description(&self) -> &str { self.error.description() }
    fn cause(&self) -> Option<&Error> { Some(&*self.error) }
}

impl From<io::Error> for ServerError {
    fn from(e: io::Error) -> ServerError {
        ServerError { error: Box::new(e) }
    }
}

impl From<json::DecoderError> for ServerError {
    fn from(e: json::DecoderError) -> ServerError {
        ServerError { error: Box::new(e) }
    }
}

impl From<json::EncoderError> for ServerError {
    fn from(e: json::EncoderError) -> ServerError {
        ServerError { error: Box::new(e) }
    }
}

pub fn safe_join<P: AsRef<path::Path>, Q: AsRef<path::Path>>(base: P, user_input: Q) -> Option<path::PathBuf> {
    let a = base.as_ref();
    let b = user_input.as_ref();

    let rv = a.join(b);
    if rv.starts_with(a) && rv.is_absolute() {
        Some(rv)
    } else {
        None
    }
}

pub fn prompt<T: AsRef<str>>(text: T) -> String {
    let mut stdout = io::stdout();
    stdout.write(text.as_ref().as_bytes()).unwrap();
    stdout.flush().unwrap();

    let stdin = io::stdin();
    let mut response = String::new();
    stdin.read_line(&mut response).unwrap();
    if response.ends_with("\n") { response.pop(); }
    response
}

pub fn double_prompt<T: AsRef<str>>(text: T) -> String {
    let again_text = {
        let mut x = "(confirm) ".to_string();
        x.push_str(text.as_ref());
        x
    };

    loop {
        let first = prompt(text.as_ref());
        let second = prompt(&again_text[..]);
        if first == second {
            return first;
        } else {
            println!("Inputs don't match. Try again.");
        }
    }
}

pub fn prompt_confirm<T: AsRef<str>>(question: T, default: bool) -> bool {
    let mut question = question.as_ref().to_owned();
    question.push_str(" ");
    question.push_str(if default { "[Y/n]" } else { "[y/N]" });
    question.push_str(" ");
    loop {
        let response = prompt(&question[..]);
        return match response.trim() {
            "y" | "Y" => true,
            "n" | "N" => false,
            "" => default,
            _ => {
                println!("Invalid answer.");
                continue;
            }
        };
    };
}

pub fn read_json_file<T: Decodable, P: AsRef<path::Path>>(p: P) -> Result<T, ServerError> {
    let mut f = try!(fs::File::open(p.as_ref()));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    let rv = try!(json::decode(&s));
    Ok(rv)
}

pub fn write_json_file<T: Encodable, P: AsRef<path::Path>>(t: T, p: P) -> Result<(), ServerError> {
    let mut f = try!(fs::File::create(p.as_ref()));
    let data = try!(json::encode(&t));
    try!(f.write(&data.into_bytes()));
    Ok(())
}

pub fn is_safe_identifier(string: &str) -> bool {
    regex::Regex::new(r"^[A-Za-z0-9_-]+$").unwrap().is_match(string)
}
<|endoftext|>


<commit_before>use paging::{PageTable, frame_for, PAGE_TABLE_SIZE, PAGE_SIZE};
use smp::{locals, locals_mut, globals};
use mutex::Mutex;
use interrupts::{Context,Contextable};

use interrupts::apic;
use tasks;
use console;
use malloc::must_allocate;

use core::prelude::*;
use core::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use core::mem::size_of;
use alloc::boxed::Box;
use collections::{Vec,VecDeque};

pub const USER_LOAD_ADDR: usize = 0x400_000;

pub type Page = Box<PageTable>;

fn new_user_page() -> Page {
    unsafe {
        Box::from_raw(must_allocate(size_of::<PageTable>(), PAGE_SIZE) as *mut PageTable)
    }
}

pub struct Process {
    pub id: u32,
    pub pd: Page,
    pub code_addr: usize,
    pub code_len: usize,
    pub pages: Vec<Page>,
    pub context: Context,
}

static PROCESSES_LOCK: Mutex<Option<VecDeque<Process>>> = mutex!(None);
static PID: AtomicUsize = ATOMIC_USIZE_INIT;

impl Process {
    // Adds a page to the process, returning its frame and index in the pages array
    pub fn add_page(&mut self) -> (usize, u32) {
        let mut page = new_user_page();
        page[0] = 0;
        let frame = frame_for(&page[0] as *const u32 as usize) as u32;
        let len = self.pages.len();
        self.pages.push(page);
        (len, frame)
    }
}

fn create_process(code: &[u32]) {
    let locals = locals_mut();
    let mut lock = PROCESSES_LOCK.lock();
    let mut processes = lock.as_mut().unwrap();
    let id = PID.fetch_add(1, Ordering::SeqCst);

    let code_addr = &code[0] as *const u32 as usize;
    let code_len = code.len();
    let mut pd = new_user_page();
    let system_pd = 0xFF_FF_F000 as *const u32;
    pd[0] = unsafe { *(system_pd) };
    let tss_pd = &locals.tss as *const tasks::Tss as usize >> 22;
    pd[tss_pd] = unsafe { *(system_pd.offset(tss_pd as isize)) };

    let mut limit = USER_LOAD_ADDR + code.len() * 4 + 32 * PAGE_TABLE_SIZE; // 32 pages away from end of code
    limit += PAGE_TABLE_SIZE - (limit % PAGE_TABLE_SIZE);
    let cr3 = frame_for(&*pd as *const PageTable as usize);

    let mut process = Process { id: id as u32, pd: pd, pages: Vec::new(),
                                code_addr: code_addr, code_len: code_len,
                                context: Context::new(USER_LOAD_ADDR,
                                                      limit - size_of::<u32>(),
                                                      cr3) };

    let (pt_idx, pt_frame) = process.add_page();
    process.pages[pt_idx][0] = frame_for(code_addr) as u32 | 0x7;

    let (stack_idx, stack_frame) = process.add_page();
    let stack_ppn = ((limit >> 12) - 1) & 0x3ff;
    process.pages[pt_idx][stack_ppn] = stack_frame as u32 | 0x7;
    process.pages[stack_idx][1023] = id as u32;

    process.pd[1] = pt_frame | 0x07; // User, RW, Present
    processes.push_back(process);
}

pub fn current_process<'r>() -> &'r Process {
    locals().process.as_ref().unwrap()
}

pub fn current_process_mut<'r>() -> &'r mut Process {
    locals_mut().process.as_mut().unwrap()
}

pub fn switch_tasks<T: Contextable>(ctx: &mut T) {
    let locals = locals_mut();
    let mut lock = PROCESSES_LOCK.lock();
    let mut processes = lock.as_mut().unwrap();
    let mut current_process = locals.process.take().unwrap();
    ctx.save(&mut current_process.context);
    processes.push_back(current_process);
    let new_process = processes.pop_front().unwrap();
    ctx.load(&new_process.context);
    locals.process = Some(new_process);
}

pub fn kill_current_process<T: Contextable>(ctx: &mut T) {
    let locals = locals_mut();
    let mut current_process = locals.process.take().unwrap();
    ctx.save(&mut current_process.context);
    drop(current_process);
    let mut lock = PROCESSES_LOCK.lock();
    match lock.as_mut().unwrap().pop_front() {
        Some(p) => {
            ctx.load(&p.context);
            locals.process = Some(p);
        },
        None => {
            log!("No more processes on CPU {}\r\n", apic::id());
            drop(lock);
            loop {}
        }
    }
}
pub fn init() -> ! {
    {
        let mut lock = PROCESSES_LOCK.lock();
        if lock.is_none() {
            *lock = Some(VecDeque::new());
            PID.store(1, Ordering::SeqCst);
        }
    }
    match globals().the_code.as_ref() {
        Some(code) => {
            create_process(&code[..]);
            create_process(&code[..]);
            let mut lock = PROCESSES_LOCK.lock();
            let process = lock.as_mut().unwrap().pop_front().unwrap();
            let locals = locals_mut();
            locals.process = Some(process);
            drop(lock);
            locals.process.as_ref().unwrap().context.to_user_mode();
        }
        None => {
            console::puts("\r\nNo user mode (maybe no disk)\r\n");
            loop {}
        }
    }
}
<commit_msg>Don't initialize first code frame<commit_after>use paging::{PageTable, frame_for, PAGE_TABLE_SIZE, PAGE_SIZE};
use smp::{locals, locals_mut, globals};
use mutex::Mutex;
use interrupts::{Context,Contextable};

use interrupts::apic;
use tasks;
use console;
use malloc::must_allocate;

use core::prelude::*;
use core::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use core::mem::size_of;
use alloc::boxed::Box;
use collections::{Vec,VecDeque};

pub const USER_LOAD_ADDR: usize = 0x400_000;

pub type Page = Box<PageTable>;

fn new_user_page() -> Page {
    unsafe {
        Box::from_raw(must_allocate(size_of::<PageTable>(), PAGE_SIZE) as *mut PageTable)
    }
}

pub struct Process {
    pub id: u32,
    pub pd: Page,
    pub code_addr: usize,
    pub code_len: usize,
    pub pages: Vec<Page>,
    pub context: Context,
}

static PROCESSES_LOCK: Mutex<Option<VecDeque<Process>>> = mutex!(None);
static PID: AtomicUsize = ATOMIC_USIZE_INIT;

impl Process {
    // Adds a page to the process, returning its frame and index in the pages array
    pub fn add_page(&mut self) -> (usize, u32) {
        let mut page = new_user_page();
        page[0] = 0;
        let frame = frame_for(&page[0] as *const u32 as usize) as u32;
        let len = self.pages.len();
        self.pages.push(page);
        (len, frame)
    }
}

fn create_process(code: &[u32]) {
    let locals = locals_mut();
    let mut lock = PROCESSES_LOCK.lock();
    let mut processes = lock.as_mut().unwrap();
    let id = PID.fetch_add(1, Ordering::SeqCst);

    let code_addr = &code[0] as *const u32 as usize;
    let code_len = code.len();
    let mut pd = new_user_page();
    let system_pd = 0xFF_FF_F000 as *const u32;
    pd[0] = unsafe { *(system_pd) };
    let tss_pd = &locals.tss as *const tasks::Tss as usize >> 22;
    pd[tss_pd] = unsafe { *(system_pd.offset(tss_pd as isize)) };

    let mut limit = USER_LOAD_ADDR + code.len() * 4 + 32 * PAGE_TABLE_SIZE; // 32 pages away from end of code
    limit += PAGE_TABLE_SIZE - (limit % PAGE_TABLE_SIZE);
    let cr3 = frame_for(&*pd as *const PageTable as usize);

    let mut process = Process { id: id as u32, pd: pd, pages: Vec::new(),
                                code_addr: code_addr, code_len: code_len,
                                context: Context::new(USER_LOAD_ADDR,
                                                      limit - size_of::<u32>(),
                                                      cr3) };

    let (pt_idx, pt_frame) = process.add_page();
    let (stack_idx, stack_frame) = process.add_page();
    let stack_ppn = ((limit >> 12) - 1) & 0x3ff;
    process.pages[pt_idx][stack_ppn] = stack_frame as u32 | 0x7;
    process.pages[stack_idx][1023] = id as u32;

    process.pd[1] = pt_frame | 0x07; // User, RW, Present
    processes.push_back(process);
}

pub fn current_process<'r>() -> &'r Process {
    locals().process.as_ref().unwrap()
}

pub fn current_process_mut<'r>() -> &'r mut Process {
    locals_mut().process.as_mut().unwrap()
}

pub fn switch_tasks<T: Contextable>(ctx: &mut T) {
    let locals = locals_mut();
    let mut lock = PROCESSES_LOCK.lock();
    let mut processes = lock.as_mut().unwrap();
    let mut current_process = locals.process.take().unwrap();
    ctx.save(&mut current_process.context);
    processes.push_back(current_process);
    let new_process = processes.pop_front().unwrap();
    ctx.load(&new_process.context);
    locals.process = Some(new_process);
}

pub fn kill_current_process<T: Contextable>(ctx: &mut T) {
    let locals = locals_mut();
    let mut current_process = locals.process.take().unwrap();
    ctx.save(&mut current_process.context);
    drop(current_process);
    let mut lock = PROCESSES_LOCK.lock();
    match lock.as_mut().unwrap().pop_front() {
        Some(p) => {
            ctx.load(&p.context);
            locals.process = Some(p);
        },
        None => {
            log!("No more processes on CPU {}\r\n", apic::id());
            drop(lock);
            loop {}
        }
    }
}
pub fn init() -> ! {
    {
        let mut lock = PROCESSES_LOCK.lock();
        if lock.is_none() {
            *lock = Some(VecDeque::new());
            PID.store(1, Ordering::SeqCst);
        }
    }
    match globals().the_code.as_ref() {
        Some(code) => {
            create_process(&code[..]);
            create_process(&code[..]);
            let mut lock = PROCESSES_LOCK.lock();
            let process = lock.as_mut().unwrap().pop_front().unwrap();
            let locals = locals_mut();
            locals.process = Some(process);
            drop(lock);
            locals.process.as_ref().unwrap().context.to_user_mode();
        }
        None => {
            console::puts("\r\nNo user mode (maybe no disk)\r\n");
            loop {}
        }
    }
}
<|endoftext|>


<commit_before>extern crate thinlinelib;

use thinlinelib::analysis::Analysis;
use thinlinelib::c::analysis_c::{AnalysisC, C_FILE_EXTENSIONS};

#[test]
fn test_new() {
    // Given
    let analysis = AnalysisC::new();

    // Then
    assert_eq!(analysis.file_types(), C_FILE_EXTENSIONS);
    assert_eq!(analysis.project_files().len(), 0);
}

#[cfg(test)]
mod test_collect_sources {

    #[cfg(test)]
    mod should_succeed {

        use std::path::Path;
        use thinlinelib::analysis::Analysis;
        use thinlinelib::c::analysis_c::AnalysisC;

        #[test]
        fn when_directory_is_valid() {
            // Given
            let analysis = AnalysisC::new();

            // When
            let c_test_src_path = Path::new("tests").join("testdata").join("c_sources");
            assert!(analysis.collect_sources(&c_test_src_path, &["."]).is_ok());

            // Then
            assert_eq!(analysis.project_files().len(), 5);
        }
    }

    #[cfg(test)]
    mod should_fail {

        use std::path::Path;
        use thinlinelib::analysis::Analysis;
        use thinlinelib::c::analysis_c::AnalysisC;

        #[test]
        fn when_directory_not_existing() {
            // Given
            let analysis = AnalysisC::new();

            // When
            let c_test_src_path = Path::new("not").join("existing");

            // Then
            assert!(analysis.collect_sources(&c_test_src_path, &["."]).is_err());
        }

        #[test]
        fn when_path_is_no_directory() {
            // Given
            let analysis = AnalysisC::new();

            // When
            let c_test_src_path = Path::new("tests").join("lib.rs");

            // Then
            assert!(analysis.collect_sources(&c_test_src_path, &["."]).is_err());
        }
    }
}

#[cfg(test)]
mod test_extract_entities {

    use std::path::Path;
    use thinlinelib::analysis::Analysis;
    use thinlinelib::c::analysis_c::AnalysisC;

    #[test]
    fn should_succeed() {
        // Given
        let analysis = AnalysisC::new();
        let c_test_src_path = Path::new("tests").join("testdata").join("c_sources");

        // Then
        {
            assert!(analysis.extract_entities().is_ok());
        }
        {
            assert!(analysis.collect_sources(&c_test_src_path, &["."]).is_ok());
            assert!(analysis.extract_entities().is_ok());
        }
    }
}
<commit_msg>Fix test_extract_entities<commit_after>extern crate thinlinelib;

use thinlinelib::analysis::Analysis;
use thinlinelib::c::analysis_c::{AnalysisC, C_FILE_EXTENSIONS};

#[test]
fn test_new() {
    // Given
    let analysis = AnalysisC::new();

    // Then
    assert_eq!(analysis.file_types(), C_FILE_EXTENSIONS);
    assert_eq!(analysis.project_files().len(), 0);
}

#[cfg(test)]
mod test_collect_sources {

    #[cfg(test)]
    mod should_succeed {

        use std::path::Path;
        use thinlinelib::analysis::Analysis;
        use thinlinelib::c::analysis_c::AnalysisC;

        #[test]
        fn when_directory_is_valid() {
            // Given
            let analysis = AnalysisC::new();

            // When
            let c_test_src_path = Path::new("tests").join("testdata").join("c_sources");
            assert!(analysis.collect_sources(&c_test_src_path, &["."]).is_ok());

            // Then
            assert_eq!(analysis.project_files().len(), 5);
        }
    }

    #[cfg(test)]
    mod should_fail {

        use std::path::Path;
        use thinlinelib::analysis::Analysis;
        use thinlinelib::c::analysis_c::AnalysisC;

        #[test]
        fn when_directory_not_existing() {
            // Given
            let analysis = AnalysisC::new();

            // When
            let c_test_src_path = Path::new("not").join("existing");

            // Then
            assert!(analysis.collect_sources(&c_test_src_path, &["."]).is_err());
        }

        #[test]
        fn when_path_is_no_directory() {
            // Given
            let analysis = AnalysisC::new();

            // When
            let c_test_src_path = Path::new("tests").join("lib.rs");

            // Then
            assert!(analysis.collect_sources(&c_test_src_path, &["."]).is_err());
        }
    }
}

#[cfg(test)]
mod test_extract_entities {

    use std::path::Path;
    use thinlinelib::analysis::Analysis;
    use thinlinelib::c::analysis_c::AnalysisC;

    #[test]
    fn should_succeed() {
        {
            // Given
            let analysis = AnalysisC::new();

            // Then
            assert!(analysis.extract_entities().is_ok());
        }
        {
            // Given
            let analysis = AnalysisC::new();
            let c_test_src_path = Path::new("tests").join("testdata").join("c_sources");

            // Then
            assert!(analysis.extract_entities().is_ok());
            assert!(analysis.collect_sources(&c_test_src_path, &["."]).is_ok());
        }
    }
}
<|endoftext|>


<commit_before>#[cfg(not(all(
    feature = "derive",
    feature = "full",
    feature = "parsing",
    feature = "printing",
    feature = "visit",
    feature = "visit-mut",
    feature = "fold",
    feature = "clone-impls",
    feature = "extra-traits",
    feature = "proc-macro",
)))]
mod error;
<commit_msg>Hide the feature check parse error from rustfmt<commit_after>macro_rules! hide_from_rustfmt {
    ($($tt:tt)*) => {
        $($tt)*
    };
}

#[cfg(not(all(
    feature = "derive",
    feature = "full",
    feature = "parsing",
    feature = "printing",
    feature = "visit",
    feature = "visit-mut",
    feature = "fold",
    feature = "clone-impls",
    feature = "extra-traits",
    feature = "proc-macro",
)))]
hide_from_rustfmt! {
    mod error;
}
<|endoftext|>


<commit_before><commit_msg>Begin implementation of trim.<commit_after><|endoftext|>


<commit_before><commit_msg>Change crc8 to unchecked array bounds<commit_after><|endoftext|>


<commit_before>// use std::env;
use std::fs::File;
use std::io::Read;
use std::ptr;
use std::env;

#[macro_use]
extern crate syscall;

fn write(fd: usize, buf: &[u8]) {
    unsafe {
        syscall!(WRITE, fd, buf.as_ptr(), buf.len());
    }
}

fn open_as_fd_or_die(filename: &[u8]) -> usize {
    let o_rdonly = 0u64;
    let no_flags = 0u64;
    unsafe {
        let return_value = syscall!(OPEN, filename.as_ptr(), o_rdonly, no_flags);
        sanity_check_fd(return_value);
        return return_value;
    }
}

fn setns(fd: usize, nstype: usize) {
    unsafe {
        syscall!(SETNS, fd, nstype);
    }
}

fn close(fd: usize) {
    unsafe {
        syscall!(CLOSE, fd);
    }
}

fn sanity_check_fd(fd: usize) {
    // For some reason, syscall!(OPEN) returns usize, but I need to check its output against
    // -1. So I'm going to just check if it's >255.
    if fd > 255 {
        panic!("Failed to open a needed file. Bailing.");
    }
}

fn setgroups_zero() {
    // Clears auxilary groups. Probably not necessary, but whatever.
    unsafe {
        syscall!(SETGROUPS, 0);
    }
}

fn fchdir(fd: usize) {
    unsafe {
        syscall!(FCHDIR, fd);
    }
}

fn fork() -> usize {
    unsafe {
        syscall!(FORK)
    }
}

fn wait_all_children() {
    let all_children = -1isize;
    let no_options = 0usize;
    let nullptr = 0usize;
    unsafe {
        syscall!(WAIT4, all_children, no_options, nullptr, nullptr);
    }
}

fn setuid_setgid_1000() {
    // These are the right UID & GID because they are what Sandstorm
    // uses inside the user namespace.
    let one_thousand = 1000usize;
    unsafe {
        syscall!(SETUID, one_thousand);
        syscall!(SETGID, one_thousand);
    }
}

fn execve_bash(envp: std::vec::Vec<*const u8>) {
    let bash_path = "/bin/bash\0".as_bytes();
    let nullargv = 0usize;
    unsafe {
        syscall!(EXECVE, bash_path.as_ptr(), nullargv, envp.as_ptr());
    }
}

fn get_envp(pidStrRef: &str) -> std::vec::Vec<*const u8> {
    // Grab the environ from pid 1048 so that when we execve a shell
    // at the end, we can provide the environment.

    let path = "/proc/".to_string() + pidStrRef + &"/environ".to_string();
    match File::open(&path) {
        Err(why) => panic!("couldn't open {}: {}", path, why),
        Ok(mut file) => {
            let mut s = String::new();
            match file.read_to_string(&mut s) {
                Err(why) => panic!("couldn't read {}: {}", path, why),
                Ok(_) => {
                    let mut v: Vec<String> = s.split('\0').map(
                        |x| x.to_string() + "\0").collect();
                    v.push("__terminator".to_string());
                    let all_environ_arguments: Vec<*const u8> = v.iter().map(|x| (
                        if x == "__terminator" { ptr::null() }
                        else { x.as_ptr() }
                        )).collect();
                    return all_environ_arguments;
                }
            }
        }
    };
}

fn main() {
    let pidStrRef = &env::args().nth(1).expect("Panicking: expected argv to have 2 items.").to_string();
    // Grab the environ from pid 1048 so that when we execve a shell
    // at the end, we can provide the environment.
    let result = get_envp(pidStrRef);

    // let filename: &[u8] = b"/usr/bin/sensors\x00";     // <-- Make c strings like this
    // let argv1: &[u8] = b"/usr/bin/sensors\x00";
    // let argv2: &[u8] = b"-h\x00";
    // let argv: &[int] = [                               // <-- store them in this
    // ::core::intrinsics::transmute(argv1.as_ptr()), // <-- transmuting
    // ::core::intrinsics::transmute(argv2.as_ptr()),
    // 0                                              // <-- and NULL terminate
    // ];
    // let envp: &[int] = [0];let target_environ
    write(1,
          ("Attaching to process ID ".to_string() + pidStrRef + &"...\n".to_string()).as_bytes());
    let userns_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pidStrRef + "/ns/user\0").as_bytes());
    let ipc_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pidStrRef + "/ns/ipc\0").as_bytes());
    let uts_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pidStrRef + "/ns/uts\0").as_bytes());
    let net_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pidStrRef + "/ns/net\0").as_bytes());
    let pid_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pidStrRef + "/ns/pid\0").as_bytes());
    let mnt_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pidStrRef + "/ns/mnt\0").as_bytes());
    let cwd_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pidStrRef + "/cwd\0").as_bytes());
    setgroups_zero();
    setns(userns_fd, 0x10000000usize); // CLONE_NEWUSER
    close(userns_fd);
    setns(ipc_fd, 0x08000000usize); // CLONE_NEWIPC
    close(ipc_fd);
    setns(uts_fd, 0x04000000usize); // CLONE_NEWUTS
    close(uts_fd);
    setns(net_fd, 0x40000000usize); // CLONE_NEWNET
    close(net_fd);
    setns(pid_fd, 0x20000000usize); // CLONE_NEWPID
    close(pid_fd);
    setns(mnt_fd, 0x00020000usize); // CLONE_NEWNS which I guess is mount namespaces
    close(mnt_fd);
    fchdir(cwd_fd);
    close(9);
    // fork, and do a handful of things in the child before we execve bash.
    let fork_result = fork();
    if fork_result == 0 {
        // in the child
        setuid_setgid_1000();
        write(1, "About to start shell...\n\0".as_bytes());
        execve_bash(result);
    } else {
        // in the parent
        wait_all_children();
    }
}

// open("/proc/1048/ns/user", O_RDONLY)    = 3
// open("/proc/1048/ns/ipc", O_RDONLY)     = 4
// open("/proc/1048/ns/uts", O_RDONLY)     = 5
// open("/proc/1048/ns/net", O_RDONLY)     = 6
// open("/proc/1048/ns/pid", O_RDONLY)     = 7
// open("/proc/1048/ns/mnt", O_RDONLY)     = 8
// open("/proc/1048/cwd", O_RDONLY)        = 9
// setgroups(0, [])                        = 0
// setns(3, CLONE_NEWUSER)                 = 0
// close(3)                                = 0
// setns(4, CLONE_NEWIPC)                  = 0
// close(4)                                = 0
// setns(5, CLONE_NEWUTS)                  = 0
// close(5)                                = 0
// setns(6, CLONE_NEWNET)                  = 0
// close(6)                                = 0
// setns(7, CLONE_NEWPID)                  = 0
// close(7)                                = 0
// setns(8, CLONE_NEWNS)                   = 0
// close(8)                                = 0
// fchdir(9)                               = 0
// close(9)                                = 0
<commit_msg>Fix snake_case suggestion/warning by Rust<commit_after>// use std::env;
use std::fs::File;
use std::io::Read;
use std::ptr;
use std::env;

#[macro_use]
extern crate syscall;

fn write(fd: usize, buf: &[u8]) {
    unsafe {
        syscall!(WRITE, fd, buf.as_ptr(), buf.len());
    }
}

fn open_as_fd_or_die(filename: &[u8]) -> usize {
    let o_rdonly = 0u64;
    let no_flags = 0u64;
    unsafe {
        let return_value = syscall!(OPEN, filename.as_ptr(), o_rdonly, no_flags);
        sanity_check_fd(return_value);
        return return_value;
    }
}

fn setns(fd: usize, nstype: usize) {
    unsafe {
        syscall!(SETNS, fd, nstype);
    }
}

fn close(fd: usize) {
    unsafe {
        syscall!(CLOSE, fd);
    }
}

fn sanity_check_fd(fd: usize) {
    // For some reason, syscall!(OPEN) returns usize, but I need to check its output against
    // -1. So I'm going to just check if it's >255.
    if fd > 255 {
        panic!("Failed to open a needed file. Bailing.");
    }
}

fn setgroups_zero() {
    // Clears auxilary groups. Probably not necessary, but whatever.
    unsafe {
        syscall!(SETGROUPS, 0);
    }
}

fn fchdir(fd: usize) {
    unsafe {
        syscall!(FCHDIR, fd);
    }
}

fn fork() -> usize {
    unsafe {
        syscall!(FORK)
    }
}

fn wait_all_children() {
    let all_children = -1isize;
    let no_options = 0usize;
    let nullptr = 0usize;
    unsafe {
        syscall!(WAIT4, all_children, no_options, nullptr, nullptr);
    }
}

fn setuid_setgid_1000() {
    // These are the right UID & GID because they are what Sandstorm
    // uses inside the user namespace.
    let one_thousand = 1000usize;
    unsafe {
        syscall!(SETUID, one_thousand);
        syscall!(SETGID, one_thousand);
    }
}

fn execve_bash(envp: std::vec::Vec<*const u8>) {
    let bash_path = "/bin/bash\0".as_bytes();
    let nullargv = 0usize;
    unsafe {
        syscall!(EXECVE, bash_path.as_ptr(), nullargv, envp.as_ptr());
    }
}

fn get_envp(pid_str_ref: &str) -> std::vec::Vec<*const u8> {
    // Grab the environ from pid 1048 so that when we execve a shell
    // at the end, we can provide the environment.

    let path = "/proc/".to_string() + pid_str_ref + &"/environ".to_string();
    match File::open(&path) {
        Err(why) => panic!("couldn't open {}: {}", path, why),
        Ok(mut file) => {
            let mut s = String::new();
            match file.read_to_string(&mut s) {
                Err(why) => panic!("couldn't read {}: {}", path, why),
                Ok(_) => {
                    let mut v: Vec<String> = s.split('\0').map(
                        |x| x.to_string() + "\0").collect();
                    v.push("__terminator".to_string());
                    let all_environ_arguments: Vec<*const u8> = v.iter().map(|x| (
                        if x == "__terminator" { ptr::null() }
                        else { x.as_ptr() }
                        )).collect();
                    return all_environ_arguments;
                }
            }
        }
    };
}

fn main() {
    let pid_str_ref = &env::args().nth(1).expect("Panicking: expected argv to have 2 items.").to_string();
    // Grab the environ from pid 1048 so that when we execve a shell
    // at the end, we can provide the environment.
    let result = get_envp(pid_str_ref);

    // let filename: &[u8] = b"/usr/bin/sensors\x00";     // <-- Make c strings like this
    // let argv1: &[u8] = b"/usr/bin/sensors\x00";
    // let argv2: &[u8] = b"-h\x00";
    // let argv: &[int] = [                               // <-- store them in this
    // ::core::intrinsics::transmute(argv1.as_ptr()), // <-- transmuting
    // ::core::intrinsics::transmute(argv2.as_ptr()),
    // 0                                              // <-- and NULL terminate
    // ];
    // let envp: &[int] = [0];let target_environ
    write(1,
          ("Attaching to process ID ".to_string() + pid_str_ref + &"...\n".to_string()).as_bytes());
    let userns_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pid_str_ref + "/ns/user\0").as_bytes());
    let ipc_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pid_str_ref + "/ns/ipc\0").as_bytes());
    let uts_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pid_str_ref + "/ns/uts\0").as_bytes());
    let net_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pid_str_ref + "/ns/net\0").as_bytes());
    let pid_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pid_str_ref + "/ns/pid\0").as_bytes());
    let mnt_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pid_str_ref + "/ns/mnt\0").as_bytes());
    let cwd_fd = open_as_fd_or_die(
        ("/proc/".to_string() + pid_str_ref + "/cwd\0").as_bytes());
    setgroups_zero();
    setns(userns_fd, 0x10000000usize); // CLONE_NEWUSER
    close(userns_fd);
    setns(ipc_fd, 0x08000000usize); // CLONE_NEWIPC
    close(ipc_fd);
    setns(uts_fd, 0x04000000usize); // CLONE_NEWUTS
    close(uts_fd);
    setns(net_fd, 0x40000000usize); // CLONE_NEWNET
    close(net_fd);
    setns(pid_fd, 0x20000000usize); // CLONE_NEWPID
    close(pid_fd);
    setns(mnt_fd, 0x00020000usize); // CLONE_NEWNS which I guess is mount namespaces
    close(mnt_fd);
    fchdir(cwd_fd);
    close(9);
    // fork, and do a handful of things in the child before we execve bash.
    let fork_result = fork();
    if fork_result == 0 {
        // in the child
        setuid_setgid_1000();
        write(1, "About to start shell...\n\0".as_bytes());
        execve_bash(result);
    } else {
        // in the parent
        wait_all_children();
    }
}

// open("/proc/1048/ns/user", O_RDONLY)    = 3
// open("/proc/1048/ns/ipc", O_RDONLY)     = 4
// open("/proc/1048/ns/uts", O_RDONLY)     = 5
// open("/proc/1048/ns/net", O_RDONLY)     = 6
// open("/proc/1048/ns/pid", O_RDONLY)     = 7
// open("/proc/1048/ns/mnt", O_RDONLY)     = 8
// open("/proc/1048/cwd", O_RDONLY)        = 9
// setgroups(0, [])                        = 0
// setns(3, CLONE_NEWUSER)                 = 0
// close(3)                                = 0
// setns(4, CLONE_NEWIPC)                  = 0
// close(4)                                = 0
// setns(5, CLONE_NEWUTS)                  = 0
// close(5)                                = 0
// setns(6, CLONE_NEWNET)                  = 0
// close(6)                                = 0
// setns(7, CLONE_NEWPID)                  = 0
// close(7)                                = 0
// setns(8, CLONE_NEWNS)                   = 0
// close(8)                                = 0
// fchdir(9)                               = 0
// close(9)                                = 0
<|endoftext|>


<commit_before>use std::ffi::CString;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

// Unfortunately, on windows, it looks like msvcrt.dll is silently translating
// verbatim paths under the hood to non-verbatim paths! This manifests itself as
// gcc looking like it cannot accept paths of the form `\\?\C:\...`, but the
// real bug seems to lie in msvcrt.dll.
//
// Verbatim paths are generally pretty rare, but the implementation of
// `fs::canonicalize` currently generates paths of this form, meaning that we're
// going to be passing quite a few of these down to gcc, so we need to deal with
// this case.
//
// For now we just strip the "verbatim prefix" of `\\?\` from the path. This
// will probably lose information in some cases, but there's not a whole lot
// more we can do with a buggy msvcrt...
//
// For some more information, see this comment:
//   https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737
#[cfg(windows)]
pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
    use std::ffi::OsString;
    use std::path;
    let mut components = p.components();
    let prefix = match components.next() {
        Some(path::Component::Prefix(p)) => p,
        _ => return p.to_path_buf(),
    };
    match prefix.kind() {
        path::Prefix::VerbatimDisk(disk) => {
            let mut base = OsString::from(format!("{}:", disk as char));
            base.push(components.as_path());
            PathBuf::from(base)
        }
        path::Prefix::VerbatimUNC(server, share) => {
            let mut base = OsString::from(r"\\");
            base.push(server);
            base.push(r"\");
            base.push(share);
            base.push(components.as_path());
            PathBuf::from(base)
        }
        _ => p.to_path_buf(),
    }
}

#[cfg(not(windows))]
pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
    p.to_path_buf()
}

pub enum LinkOrCopy {
    Link,
    Copy,
}

/// Copies `p` into `q`, preferring to use hard-linking if possible. If
/// `q` already exists, it is removed first.
/// The result indicates which of the two operations has been performed.
pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<LinkOrCopy> {
    let p = p.as_ref();
    let q = q.as_ref();
    if q.exists() {
        fs::remove_file(&q)?;
    }

    match fs::hard_link(p, q) {
        Ok(()) => Ok(LinkOrCopy::Link),
        Err(_) => match fs::copy(p, q) {
            Ok(_) => Ok(LinkOrCopy::Copy),
            Err(e) => Err(e),
        },
    }
}

#[cfg(unix)]
pub fn path_to_c_string(p: &Path) -> CString {
    use std::ffi::OsStr;
    use std::os::unix::ffi::OsStrExt;
    let p: &OsStr = p.as_ref();
    CString::new(p.as_bytes()).unwrap()
}
#[cfg(windows)]
pub fn path_to_c_string(p: &Path) -> CString {
    CString::new(p.to_str().unwrap()).unwrap()
}
<commit_msg>Auto merge of #80754 - sunfishcode:path-cleanup/rustc-fs-util, r=davidtwco<commit_after>use std::ffi::CString;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

// Unfortunately, on windows, it looks like msvcrt.dll is silently translating
// verbatim paths under the hood to non-verbatim paths! This manifests itself as
// gcc looking like it cannot accept paths of the form `\\?\C:\...`, but the
// real bug seems to lie in msvcrt.dll.
//
// Verbatim paths are generally pretty rare, but the implementation of
// `fs::canonicalize` currently generates paths of this form, meaning that we're
// going to be passing quite a few of these down to gcc, so we need to deal with
// this case.
//
// For now we just strip the "verbatim prefix" of `\\?\` from the path. This
// will probably lose information in some cases, but there's not a whole lot
// more we can do with a buggy msvcrt...
//
// For some more information, see this comment:
//   https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737
#[cfg(windows)]
pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
    use std::ffi::OsString;
    use std::path;
    let mut components = p.components();
    let prefix = match components.next() {
        Some(path::Component::Prefix(p)) => p,
        _ => return p.to_path_buf(),
    };
    match prefix.kind() {
        path::Prefix::VerbatimDisk(disk) => {
            let mut base = OsString::from(format!("{}:", disk as char));
            base.push(components.as_path());
            PathBuf::from(base)
        }
        path::Prefix::VerbatimUNC(server, share) => {
            let mut base = OsString::from(r"\\");
            base.push(server);
            base.push(r"\");
            base.push(share);
            base.push(components.as_path());
            PathBuf::from(base)
        }
        _ => p.to_path_buf(),
    }
}

#[cfg(not(windows))]
pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
    p.to_path_buf()
}

pub enum LinkOrCopy {
    Link,
    Copy,
}

/// Copies `p` into `q`, preferring to use hard-linking if possible. If
/// `q` already exists, it is removed first.
/// The result indicates which of the two operations has been performed.
pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<LinkOrCopy> {
    let p = p.as_ref();
    let q = q.as_ref();
    match fs::remove_file(&q) {
        Ok(()) => (),
        Err(err) if err.kind() == io::ErrorKind::NotFound => (),
        Err(err) => return Err(err),
    }

    match fs::hard_link(p, q) {
        Ok(()) => Ok(LinkOrCopy::Link),
        Err(_) => match fs::copy(p, q) {
            Ok(_) => Ok(LinkOrCopy::Copy),
            Err(e) => Err(e),
        },
    }
}

#[cfg(unix)]
pub fn path_to_c_string(p: &Path) -> CString {
    use std::ffi::OsStr;
    use std::os::unix::ffi::OsStrExt;
    let p: &OsStr = p.as_ref();
    CString::new(p.as_bytes()).unwrap()
}
#[cfg(windows)]
pub fn path_to_c_string(p: &Path) -> CString {
    CString::new(p.to_str().unwrap()).unwrap()
}
<|endoftext|>


<commit_before>use alloc::prelude::v1::*;
use core::fmt;
use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub struct Ipv4Addr(pub [u8; 4]);

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub struct Ipv6Addr(pub [u8; 16]);

impl Ipv4Addr {
    pub const ZERO: Self = Self([0, 0, 0, 0]);
    pub const LOCALHOST: Self = Self([127, 0, 0, 1]);

    pub fn from_bytes(bytes: &[u8]) -> Self {
        assert!(bytes.len() == 4);
        let mut data = [0; 4];
        data.copy_from_slice(bytes);
        Ipv4Addr(data)
    }
}

impl Ipv6Addr {
    pub fn from_bytes(bytes: &[u8]) -> Self {
        assert!(bytes.len() == 16);
        let mut data = [0; 16];
        data.copy_from_slice(bytes);
        Ipv6Addr(data)
    }
}

impl fmt::Debug for Ipv4Addr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let parts: Vec<_> = self.0.iter().map(|c| format!("{}", c)).collect();
        write!(f, "Ipv4Addr({})", parts.join("."))
    }
}

impl fmt::Debug for Ipv6Addr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let parts: Vec<_> = self.0.iter().map(|c| format!("{:02x}", c)).collect();
        write!(f, "Ipv6Addr({})", parts.join(":"))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub enum IpAddr {
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}
impl IpAddr {
    pub(crate) fn from_bytes(bytes: &[u8]) -> Self {
        match bytes.len() {
            4 => Self::V4(Ipv4Addr::from_bytes(bytes)),
            16 => Self::V6(Ipv6Addr::from_bytes(bytes)),
            _ => panic!("Invalid ip address byte count"),
        }
    }
}
<commit_msg>Add SocketAddr to d7net<commit_after>use alloc::prelude::v1::*;
use core::fmt;
use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub struct Ipv4Addr(pub [u8; 4]);

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub struct Ipv6Addr(pub [u8; 16]);

impl Ipv4Addr {
    pub const ZERO: Self = Self([0, 0, 0, 0]);
    pub const LOCALHOST: Self = Self([127, 0, 0, 1]);

    pub fn from_bytes(bytes: &[u8]) -> Self {
        assert!(bytes.len() == 4);
        let mut data = [0; 4];
        data.copy_from_slice(bytes);
        Ipv4Addr(data)
    }
}

impl Ipv6Addr {
    pub fn from_bytes(bytes: &[u8]) -> Self {
        assert!(bytes.len() == 16);
        let mut data = [0; 16];
        data.copy_from_slice(bytes);
        Ipv6Addr(data)
    }
}

impl fmt::Debug for Ipv4Addr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let parts: Vec<_> = self.0.iter().map(|c| format!("{}", c)).collect();
        write!(f, "Ipv4Addr({})", parts.join("."))
    }
}

impl fmt::Debug for Ipv6Addr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let parts: Vec<_> = self.0.iter().map(|c| format!("{:02x}", c)).collect();
        write!(f, "Ipv6Addr({})", parts.join(":"))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub enum IpAddr {
    V4(Ipv4Addr),
    V6(Ipv6Addr),
}
impl IpAddr {
    pub(crate) fn from_bytes(bytes: &[u8]) -> Self {
        match bytes.len() {
            4 => Self::V4(Ipv4Addr::from_bytes(bytes)),
            16 => Self::V6(Ipv6Addr::from_bytes(bytes)),
            _ => panic!("Invalid ip address byte count"),
        }
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SocketAddr {
    pub host: IpAddr,
    pub port: u16,
}
<|endoftext|>


<commit_before>#![cfg(not(loom))]

//! Utilities for tracking time.
//!
//! This module provides a number of types for executing code after a set period
//! of time.
//!
//! * [`Delay`][Delay] is a future that does no work and completes at a specific `Instant`
//!   in time.
//!
//! * [`Interval`][Interval] is a stream yielding a value at a fixed period. It
//!   is initialized with a `Duration` and repeatedly yields each time the
//!   duration elapses.
//!
//! * [`Timeout`][Timeout]: Wraps a future or stream, setting an upper bound to the
//!   amount of time it is allowed to execute. If the future or stream does not
//!   complete in time, then it is canceled and an error is returned.
//!
//! * [`DelayQueue`]: A queue where items are returned once the requested delay
//!   has expired.
//!
//! These types are sufficient for handling a large number of scenarios
//! involving time.
//!
//! These types must be used from within the context of the
//! [`Runtime`][runtime].
//!
//! # Examples
//!
//! Wait 100ms and print "Hello World!"
//!
//! ```
//! use tokio::time::delay_for;
//!
//! use std::time::Duration;
//!
//!
//! #[tokio::main]
//! async fn main() {
//!     delay_for(Duration::from_millis(100)).await;
//!     println!("100 ms have elapsed");
//! }
//! ```
//!
//! Require that an operation takes no more than 300ms. Note that this uses the
//! [`timeout`][ext] function on the [`FutureExt`][ext] trait. This trait is
//! included in the prelude.
//!
//! ```
//! use tokio::time::{timeout, Duration};
//!
//! async fn long_future() {
//!     // do work here
//! }
//!
//! # async fn dox() {
//! let res = timeout(Duration::from_secs(1), long_future()).await;
//!
//! if res.is_err() {
//!     println!("operation timed out");
//! }
//! # }
//! ```
//!
//! [runtime]: ../runtime/struct.Runtime.html
//! [ext]: ../util/trait.FutureExt.html#method.timeout
//! [Timeout]: struct.Timeout.html
//! [Delay]: struct.Delay.html
//! [Interval]: struct.Interval.html
//! [`DelayQueue`]: struct.DelayQueue.html

mod clock;
pub(crate) use self::clock::Clock;
#[cfg(feature = "test-util")]
pub use clock::{advance, pause, resume};

pub mod delay_queue;
#[doc(inline)]
pub use delay_queue::DelayQueue;

mod delay;
pub use delay::{delay_for, delay_until, Delay};

pub(crate) mod driver;

mod error;
pub use error::Error;

mod instant;
pub use self::instant::Instant;

mod interval;
pub use interval::{interval, interval_at, Interval};

mod timeout;
#[doc(inline)]
pub use timeout::{timeout, timeout_at, Timeout};

mod wheel;

#[cfg(test)]
#[cfg(not(loom))]
mod tests;

// Re-export for convenience
pub use std::time::Duration;

// ===== Internal utils =====

enum Round {
    Up,
    Down,
}

/// Convert a `Duration` to milliseconds, rounding up and saturating at
/// `u64::MAX`.
///
/// The saturating is fine because `u64::MAX` milliseconds are still many
/// million years.
#[inline]
fn ms(duration: Duration, round: Round) -> u64 {
    const NANOS_PER_MILLI: u32 = 1_000_000;
    const MILLIS_PER_SEC: u64 = 1_000;

    // Round up.
    let millis = match round {
        Round::Up => (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI,
        Round::Down => duration.subsec_millis(),
    };

    duration
        .as_secs()
        .saturating_mul(MILLIS_PER_SEC)
        .saturating_add(u64::from(millis))
}
<commit_msg>time: reexport Elapsed (#1826)<commit_after>#![cfg(not(loom))]

//! Utilities for tracking time.
//!
//! This module provides a number of types for executing code after a set period
//! of time.
//!
//! * [`Delay`][Delay] is a future that does no work and completes at a specific `Instant`
//!   in time.
//!
//! * [`Interval`][Interval] is a stream yielding a value at a fixed period. It
//!   is initialized with a `Duration` and repeatedly yields each time the
//!   duration elapses.
//!
//! * [`Timeout`][Timeout]: Wraps a future or stream, setting an upper bound to the
//!   amount of time it is allowed to execute. If the future or stream does not
//!   complete in time, then it is canceled and an error is returned.
//!
//! * [`DelayQueue`]: A queue where items are returned once the requested delay
//!   has expired.
//!
//! These types are sufficient for handling a large number of scenarios
//! involving time.
//!
//! These types must be used from within the context of the
//! [`Runtime`][runtime].
//!
//! # Examples
//!
//! Wait 100ms and print "Hello World!"
//!
//! ```
//! use tokio::time::delay_for;
//!
//! use std::time::Duration;
//!
//!
//! #[tokio::main]
//! async fn main() {
//!     delay_for(Duration::from_millis(100)).await;
//!     println!("100 ms have elapsed");
//! }
//! ```
//!
//! Require that an operation takes no more than 300ms. Note that this uses the
//! [`timeout`][ext] function on the [`FutureExt`][ext] trait. This trait is
//! included in the prelude.
//!
//! ```
//! use tokio::time::{timeout, Duration};
//!
//! async fn long_future() {
//!     // do work here
//! }
//!
//! # async fn dox() {
//! let res = timeout(Duration::from_secs(1), long_future()).await;
//!
//! if res.is_err() {
//!     println!("operation timed out");
//! }
//! # }
//! ```
//!
//! [runtime]: ../runtime/struct.Runtime.html
//! [ext]: ../util/trait.FutureExt.html#method.timeout
//! [Timeout]: struct.Timeout.html
//! [Delay]: struct.Delay.html
//! [Interval]: struct.Interval.html
//! [`DelayQueue`]: struct.DelayQueue.html

mod clock;
pub(crate) use self::clock::Clock;
#[cfg(feature = "test-util")]
pub use clock::{advance, pause, resume};

pub mod delay_queue;
#[doc(inline)]
pub use delay_queue::DelayQueue;

mod delay;
pub use delay::{delay_for, delay_until, Delay};

pub(crate) mod driver;

mod error;
pub use error::Error;

mod instant;
pub use self::instant::Instant;

mod interval;
pub use interval::{interval, interval_at, Interval};

mod timeout;
#[doc(inline)]
pub use timeout::{timeout, timeout_at, Timeout, Elapsed};

mod wheel;

#[cfg(test)]
#[cfg(not(loom))]
mod tests;

// Re-export for convenience
pub use std::time::Duration;

// ===== Internal utils =====

enum Round {
    Up,
    Down,
}

/// Convert a `Duration` to milliseconds, rounding up and saturating at
/// `u64::MAX`.
///
/// The saturating is fine because `u64::MAX` milliseconds are still many
/// million years.
#[inline]
fn ms(duration: Duration, round: Round) -> u64 {
    const NANOS_PER_MILLI: u32 = 1_000_000;
    const MILLIS_PER_SEC: u64 = 1_000;

    // Round up.
    let millis = match round {
        Round::Up => (duration.subsec_nanos() + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI,
        Round::Down => duration.subsec_millis(),
    };

    duration
        .as_secs()
        .saturating_mul(MILLIS_PER_SEC)
        .saturating_add(u64::from(millis))
}
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// 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.

#![feature(test)]
#![allow(dead_code)]
extern crate test;
extern crate rand;
extern crate tempdir;
extern crate exonum;

#[cfg(all(test, feature = "long_benchmarks"))]
mod tests {
    use std::collections::HashSet;
    use test::Bencher;
    use rand::{Rng, thread_rng, XorShiftRng, SeedableRng};
    use tempdir::TempDir;
    use exonum::storage::{Database, MemoryDB};
    use exonum::storage::{RocksDB, RocksDBOptions};
    use exonum::storage::{ProofMapIndex, ProofListIndex};
    use exonum::storage::proof_map_index::PROOF_MAP_KEY_SIZE as KEY_SIZE;

    const NAME: &'static str = "name";

    fn generate_random_kv(len: usize) -> Vec<([u8; KEY_SIZE], Vec<u8>)> {
        let mut rng = thread_rng();
        let mut exists_keys = HashSet::new();
        let mut base = [0; KEY_SIZE];
        rng.fill_bytes(&mut base);
        let base = base;

        let kv_generator = |_| {
            let mut v = vec![0; 8];

            // Generate only unique keys
            let mut k = base;
            let byte: usize = rng.gen_range(0, 31);
            k[byte] = rng.gen::<u8>();

            rng.fill_bytes(&mut v);
            while exists_keys.contains(&k) {
                rng.fill_bytes(&mut k);
            }
            exists_keys.insert(k);
            (k, v)
        };

        (0..len).map(kv_generator).collect::<Vec<_>>()
    }

    fn merkle_table_insertion<T: Database>(b: &mut Bencher, db: &T) {
        let mut rng = XorShiftRng::from_seed([192, 168, 56, 1]);
        let mut storage = db.fork();
        let mut table = ProofListIndex::new(NAME, &mut storage);

        b.iter(|| {
            let v_generator = |_| {
                let mut chunk = vec![0; 10];
                rng.fill_bytes(&mut chunk);
                chunk
            };

            for item in (0..1000).map(v_generator) {
                table.push(item);
            }
        });
    }

    fn merkle_patricia_table_insertion<T: Database>(b: &mut Bencher, db: &T) {
        let data = generate_random_kv(200);
        let mut storage = db.fork();
        let mut table = ProofMapIndex::new(NAME, &mut storage);

        b.iter(|| for item in &data {
            table.put(&item.0, item.1.clone());
        });
    }

    fn merkle_patricia_table_insertion_fork<T: Database>(b: &mut Bencher, db: &T) {
        let data = generate_random_kv(200);

        b.iter(|| {
            let patch;
            {
                let mut fork = db.fork();
                {
                    let mut table = ProofMapIndex::new(NAME, &mut fork);
                    for item in &data {
                        table.put(&item.0, item.1.clone());
                    }
                }
                patch = fork.into_patch();
            }
            db.fork().merge(patch);
        });
    }

    fn merkle_patricia_table_insertion_large_map<T: Database>(b: &mut Bencher, db: &T) {
        let data = generate_random_kv(200);
        let mut storage = db.fork();
        let mut table = ProofMapIndex::new(NAME, &mut storage);

        for item in &data {
            table.put(&item.0, item.1.clone());
        }

        b.iter(|| for item in &data {
            table.put(&item.0, item.1.clone());
        });
    }

    fn create_rocksdb(tempdir: &TempDir) -> RocksDB {
        let mut options = RocksDBOptions::default();
        options.create_if_missing(true);
        RocksDB::open(tempdir.path(), &options).unwrap()
    }

    #[bench]
    fn bench_merkle_table_append_memorydb(b: &mut Bencher) {
        let db = MemoryDB::new();
        merkle_table_insertion(b, &db);
    }

    #[bench]
    fn bench_merkle_table_append_rocksdb(b: &mut Bencher) {
        let tempdir = TempDir::new("exonum").unwrap();
        let db = create_rocksdb(&tempdir);
        merkle_table_insertion(b, &db);
    }

    #[bench]
    fn bench_merkle_patricia_table_insertion_memorydb(b: &mut Bencher) {
        let db = MemoryDB::new();
        merkle_patricia_table_insertion(b, &db);
    }

    #[bench]
    fn bench_merkle_patricia_table_insertion_fork_memorydb(b: &mut Bencher) {
        let db = MemoryDB::new();
        merkle_patricia_table_insertion_fork(b, &db);
    }

    #[bench]
    fn bench_merkle_patricia_table_insertion_rocksdb(b: &mut Bencher) {
        let tempdir = TempDir::new("exonum").unwrap();
        let db = create_rocksdb(&tempdir);
        merkle_patricia_table_insertion(b, &db);
    }

    #[bench]
    fn bench_merkle_patricia_table_insertion_fork_rocksdb(b: &mut Bencher) {
        let tempdir = TempDir::new("exonum").unwrap();
        let db = create_rocksdb(&tempdir);
        merkle_patricia_table_insertion_fork(b, &db);
    }

    #[bench]
    fn long_bench_merkle_patricia_table_insertion_memorydb(b: &mut Bencher) {
        let db = MemoryDB::new();
        merkle_patricia_table_insertion_large_map(b, &db);
    }

    #[bench]
    fn long_bench_merkle_patricia_table_insertion_rocksdb(b: &mut Bencher) {
        let tempdir = TempDir::new("exonum").unwrap();
        let db = create_rocksdb(&tempdir);
        merkle_patricia_table_insertion_large_map(b, &db);
    }
}
<commit_msg>Removed a redundant static lifetime from const<commit_after>// Copyright 2017 The Exonum Team
//
// 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.

#![feature(test)]
#![allow(dead_code)]
extern crate test;
extern crate rand;
extern crate tempdir;
extern crate exonum;

#[cfg(all(test, feature = "long_benchmarks"))]
mod tests {
    use std::collections::HashSet;
    use test::Bencher;
    use rand::{Rng, thread_rng, XorShiftRng, SeedableRng};
    use tempdir::TempDir;
    use exonum::storage::{Database, MemoryDB};
    use exonum::storage::{RocksDB, RocksDBOptions};
    use exonum::storage::{ProofMapIndex, ProofListIndex};
    use exonum::storage::proof_map_index::PROOF_MAP_KEY_SIZE as KEY_SIZE;

    const NAME: &str = "name";

    fn generate_random_kv(len: usize) -> Vec<([u8; KEY_SIZE], Vec<u8>)> {
        let mut rng = thread_rng();
        let mut exists_keys = HashSet::new();
        let mut base = [0; KEY_SIZE];
        rng.fill_bytes(&mut base);
        let base = base;

        let kv_generator = |_| {
            let mut v = vec![0; 8];

            // Generate only unique keys
            let mut k = base;
            let byte: usize = rng.gen_range(0, 31);
            k[byte] = rng.gen::<u8>();

            rng.fill_bytes(&mut v);
            while exists_keys.contains(&k) {
                rng.fill_bytes(&mut k);
            }
            exists_keys.insert(k);
            (k, v)
        };

        (0..len).map(kv_generator).collect::<Vec<_>>()
    }

    fn merkle_table_insertion<T: Database>(b: &mut Bencher, db: &T) {
        let mut rng = XorShiftRng::from_seed([192, 168, 56, 1]);
        let mut storage = db.fork();
        let mut table = ProofListIndex::new(NAME, &mut storage);

        b.iter(|| {
            let v_generator = |_| {
                let mut chunk = vec![0; 10];
                rng.fill_bytes(&mut chunk);
                chunk
            };

            for item in (0..1000).map(v_generator) {
                table.push(item);
            }
        });
    }

    fn merkle_patricia_table_insertion<T: Database>(b: &mut Bencher, db: &T) {
        let data = generate_random_kv(200);
        let mut storage = db.fork();
        let mut table = ProofMapIndex::new(NAME, &mut storage);

        b.iter(|| for item in &data {
            table.put(&item.0, item.1.clone());
        });
    }

    fn merkle_patricia_table_insertion_fork<T: Database>(b: &mut Bencher, db: &T) {
        let data = generate_random_kv(200);

        b.iter(|| {
            let patch;
            {
                let mut fork = db.fork();
                {
                    let mut table = ProofMapIndex::new(NAME, &mut fork);
                    for item in &data {
                        table.put(&item.0, item.1.clone());
                    }
                }
                patch = fork.into_patch();
            }
            db.fork().merge(patch);
        });
    }

    fn merkle_patricia_table_insertion_large_map<T: Database>(b: &mut Bencher, db: &T) {
        let data = generate_random_kv(200);
        let mut storage = db.fork();
        let mut table = ProofMapIndex::new(NAME, &mut storage);

        for item in &data {
            table.put(&item.0, item.1.clone());
        }

        b.iter(|| for item in &data {
            table.put(&item.0, item.1.clone());
        });
    }

    fn create_rocksdb(tempdir: &TempDir) -> RocksDB {
        let mut options = RocksDBOptions::default();
        options.create_if_missing(true);
        RocksDB::open(tempdir.path(), &options).unwrap()
    }

    #[bench]
    fn bench_merkle_table_append_memorydb(b: &mut Bencher) {
        let db = MemoryDB::new();
        merkle_table_insertion(b, &db);
    }

    #[bench]
    fn bench_merkle_table_append_rocksdb(b: &mut Bencher) {
        let tempdir = TempDir::new("exonum").unwrap();
        let db = create_rocksdb(&tempdir);
        merkle_table_insertion(b, &db);
    }

    #[bench]
    fn bench_merkle_patricia_table_insertion_memorydb(b: &mut Bencher) {
        let db = MemoryDB::new();
        merkle_patricia_table_insertion(b, &db);
    }

    #[bench]
    fn bench_merkle_patricia_table_insertion_fork_memorydb(b: &mut Bencher) {
        let db = MemoryDB::new();
        merkle_patricia_table_insertion_fork(b, &db);
    }

    #[bench]
    fn bench_merkle_patricia_table_insertion_rocksdb(b: &mut Bencher) {
        let tempdir = TempDir::new("exonum").unwrap();
        let db = create_rocksdb(&tempdir);
        merkle_patricia_table_insertion(b, &db);
    }

    #[bench]
    fn bench_merkle_patricia_table_insertion_fork_rocksdb(b: &mut Bencher) {
        let tempdir = TempDir::new("exonum").unwrap();
        let db = create_rocksdb(&tempdir);
        merkle_patricia_table_insertion_fork(b, &db);
    }

    #[bench]
    fn long_bench_merkle_patricia_table_insertion_memorydb(b: &mut Bencher) {
        let db = MemoryDB::new();
        merkle_patricia_table_insertion_large_map(b, &db);
    }

    #[bench]
    fn long_bench_merkle_patricia_table_insertion_rocksdb(b: &mut Bencher) {
        let tempdir = TempDir::new("exonum").unwrap();
        let db = create_rocksdb(&tempdir);
        merkle_patricia_table_insertion_large_map(b, &db);
    }
}
<|endoftext|>


<commit_before>use super::stylesheets::parse_stylesheet;

#[test]
fn test_bootstrap() {
    // Test that parsing bootstrap does not trigger an assertion or otherwise fail.
    let stylesheet = parse_stylesheet(include_str!("bootstrap-v3.0.0.css"));
    assert!(stylesheet.rules.len() > 100);  // This depends on whet selectors are supported.
}
<commit_msg>Fix missing license header.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use super::stylesheets::parse_stylesheet;

#[test]
fn test_bootstrap() {
    // Test that parsing bootstrap does not trigger an assertion or otherwise fail.
    let stylesheet = parse_stylesheet(include_str!("bootstrap-v3.0.0.css"));
    assert!(stylesheet.rules.len() > 100);  // This depends on whet selectors are supported.
}
<|endoftext|>


<commit_before>//! A simple tool for creating a new nannou project.
//!
//! 1. Determines whether the user is just sketching or wants an App (with model and event `fn`s).
//! 2. Asks for a sketch/app name.

extern crate names;
extern crate rand;

use std::env;
use std::io::{self, BufRead, Write};
use std::fs::{self, File};
use std::path::Path;
use std::process::{Command, Stdio};
use std::sync::mpsc;
use std::thread;

enum Goal { Sketch, App }

const TEMPLATE_SKETCH: &[u8] = include_bytes!("../../examples/template_sketch.rs");
const TEMPLATE_APP: &[u8] = include_bytes!("../../examples/template_app.rs");

impl Goal {
    fn template_bytes(&self) -> &[u8] {
        match *self {
            Goal::Sketch => TEMPLATE_SKETCH,
            Goal::App => TEMPLATE_APP,
        }
    }
}

// Ask the user the given question, get a trimmed response.
fn ask_user(question: &str) -> io::Result<String> {
    print!("{}", question);
    io::stdout().flush()?;
    let mut response = String::new();
    io::stdin().read_line(&mut response)?;
    Ok(response.trim().to_string())
}

enum Response { Yes, No }

fn yes_or_no(s: &str) -> Option<Response> {
    let s = s.to_ascii_lowercase();
    match &s[..] {
        "" | "y" | "yes" | "yeah" | "yep" | "flip yes" => Some(Response::Yes),
        "n" | "no" | "nah" | "nope" | "flip no" => Some(Response::No),
        _ => None,
    }
}

fn random_beverage() -> &'static str {
    if rand::random() {
        "cup of coffee"
    } else {
        "cup of tea"
    }
}

fn main() {
    // Retrieve the name of the exe that the user wishes to package.
    let response = ask_user("Are you sketching? (Y/n): ").expect("failed to get user input");
    let goal = match yes_or_no(&response) {
        Some(Response::Yes) => Goal::Sketch,
        Some(Response::No) => Goal::App,
        _ => {
            println!("I don't understand \"{}\", I was expecting \"y\" or \"n\". Exiting", response);
            return;
        }
    };

    // Get a name for the sketch.
    let name = loop {
        let response = ask_user("Name your sketch: ").expect("failed to get user input");
        if !response.is_empty() {
            break response;
        }
        let random_name = names::Generator::default().next().expect("failed to generate name");
        let question = format!("Hmmm... How about the name, \"{}\"? (Y/n): ", random_name);
        let response = ask_user(&question).expect("failed to get user input");
        if let Some(Response::Yes) = yes_or_no(&response) {
            break random_name;
        }
    };

    // TODO: Ask the user for additional cargo args.

    // TODO: Find the current version of nannou.
    let nannou_version = "0.4";
    let nannou_dependency = format!("nannou = \"{}\"", nannou_version);

    // TODO: Load the template example or fallback to compiled template.
    let template_bytes = goal.template_bytes();

    // Get the current directory.
    let current_directory = env::current_dir()
        .expect("could not retrieve current directory");

    // Create the project path.
    let project_path = current_directory.join(&name);
    println!("Creating cargo project: \"{}\"", project_path.display());
    Command::new("cargo")
        .arg("new")
        .arg("--bin")
        .arg(&name)
        .output()
        .expect("failed to create cargo project");

    // Assert the path now exists.
    assert!(project_path.exists());
    assert!(project_path.is_dir());

    // Remove the existing main file.
    let src_path = project_path.join("src");
    let main_path = src_path.join(Path::new("main").with_extension("rs"));
    fs::remove_file(&main_path).expect("failed to remove existing \"main.rs\" file");

    // Create the file from the template string.
    {
        println!("Writing template file \"{}\"", main_path.display());
        let mut file = File::create(main_path).expect("failed to create new main file");
        file.write_all(template_bytes).expect("failed to write to new main file");
    }

    // Append the nannou dependency to the "Cargo.toml" file.
    {
        println!("Adding nannou dependency \"{}\"", nannou_dependency);
        let cargo_toml_path = project_path.join("Cargo").with_extension("toml");
        let mut file = fs::OpenOptions::new()
            .write(true)
            .append(true)
            .open(&cargo_toml_path)
            .expect("failed to open \"Cargo.toml\" to add nannou dependency");
        writeln!(file, "\n{}", nannou_dependency).expect("failed to append nannou dependency");
    }

    // Change the directory to the newly created path.
    println!("Changing the current directory to \"{}\"", project_path.display());
    env::set_current_dir(&project_path).expect("failed to change directories");

    // Building and running.
    let bev = random_beverage();
    println!("Building `{}`. This might take a while for the first time. Grab a {}?", name, bev);
    let mut child = Command::new("cargo")
        .arg("build")
        .arg("--release")
        .stderr(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("failed to spawn cargo build and run process");

    // Read from cargo's stdout and stderr.
    let err = io::BufReader::new(child.stderr.take().unwrap());
    let out = io::BufReader::new(child.stdout.take().unwrap());
    let (tx, rx) = mpsc::channel();
    let tx_err = tx.clone();

    let err_handle = thread::spawn(move || {
        for line in err.lines().filter_map(|l| l.ok()) {
            tx_err.send(Err(line)).expect("failed to send piped stderr");
        }
    });

    let out_handle = thread::spawn(move || {
        for line in out.lines().filter_map(|l| l.ok()) {
            tx.send(Ok(line)).expect("failed to send piped stdout");
        }
    });

    // Print the stdout and stderr from cargo.
    for result in rx {
        match result {
            Ok(line) => println!("[cargo] {}", line),
            Err(line) => eprintln!("[cargo] {}", line),
        }
    }

    err_handle.join().unwrap();
    out_handle.join().unwrap();

    // If the exe is where it should be, assume the build succeeded.
    let exe_path = project_path.join("target").join("release").join(&name);
    if exe_path.exists() {
        println!("Successfully built \"{}\"! Go forth and create!", name);
    }
}
<commit_msg>Update generated nannou dependency version.<commit_after>//! A simple tool for creating a new nannou project.
//!
//! 1. Determines whether the user is just sketching or wants an App (with model and event `fn`s).
//! 2. Asks for a sketch/app name.

extern crate names;
extern crate rand;

use std::env;
use std::io::{self, BufRead, Write};
use std::fs::{self, File};
use std::path::Path;
use std::process::{Command, Stdio};
use std::sync::mpsc;
use std::thread;

enum Goal { Sketch, App }

const TEMPLATE_SKETCH: &[u8] = include_bytes!("../../examples/template_sketch.rs");
const TEMPLATE_APP: &[u8] = include_bytes!("../../examples/template_app.rs");

impl Goal {
    fn template_bytes(&self) -> &[u8] {
        match *self {
            Goal::Sketch => TEMPLATE_SKETCH,
            Goal::App => TEMPLATE_APP,
        }
    }
}

// Ask the user the given question, get a trimmed response.
fn ask_user(question: &str) -> io::Result<String> {
    print!("{}", question);
    io::stdout().flush()?;
    let mut response = String::new();
    io::stdin().read_line(&mut response)?;
    Ok(response.trim().to_string())
}

enum Response { Yes, No }

fn yes_or_no(s: &str) -> Option<Response> {
    let s = s.to_ascii_lowercase();
    match &s[..] {
        "" | "y" | "yes" | "yeah" | "yep" | "flip yes" => Some(Response::Yes),
        "n" | "no" | "nah" | "nope" | "flip no" => Some(Response::No),
        _ => None,
    }
}

fn random_beverage() -> &'static str {
    if rand::random() {
        "cup of coffee"
    } else {
        "cup of tea"
    }
}

fn main() {
    // Retrieve the name of the exe that the user wishes to package.
    let response = ask_user("Are you sketching? (Y/n): ").expect("failed to get user input");
    let goal = match yes_or_no(&response) {
        Some(Response::Yes) => Goal::Sketch,
        Some(Response::No) => Goal::App,
        _ => {
            println!("I don't understand \"{}\", I was expecting \"y\" or \"n\". Exiting", response);
            return;
        }
    };

    // Get a name for the sketch.
    let name = loop {
        let response = ask_user("Name your sketch: ").expect("failed to get user input");
        if !response.is_empty() {
            break response;
        }
        let random_name = names::Generator::default().next().expect("failed to generate name");
        let question = format!("Hmmm... How about the name, \"{}\"? (Y/n): ", random_name);
        let response = ask_user(&question).expect("failed to get user input");
        if let Some(Response::Yes) = yes_or_no(&response) {
            break random_name;
        }
    };

    // TODO: Ask the user for additional cargo args.

    // TODO: Find the current version of nannou.
    let nannou_version = "0.5";
    let nannou_dependency = format!("nannou = \"{}\"", nannou_version);

    // TODO: Load the template example or fallback to compiled template.
    let template_bytes = goal.template_bytes();

    // Get the current directory.
    let current_directory = env::current_dir()
        .expect("could not retrieve current directory");

    // Create the project path.
    let project_path = current_directory.join(&name);
    println!("Creating cargo project: \"{}\"", project_path.display());
    Command::new("cargo")
        .arg("new")
        .arg("--bin")
        .arg(&name)
        .output()
        .expect("failed to create cargo project");

    // Assert the path now exists.
    assert!(project_path.exists());
    assert!(project_path.is_dir());

    // Remove the existing main file.
    let src_path = project_path.join("src");
    let main_path = src_path.join(Path::new("main").with_extension("rs"));
    fs::remove_file(&main_path).expect("failed to remove existing \"main.rs\" file");

    // Create the file from the template string.
    {
        println!("Writing template file \"{}\"", main_path.display());
        let mut file = File::create(main_path).expect("failed to create new main file");
        file.write_all(template_bytes).expect("failed to write to new main file");
    }

    // Append the nannou dependency to the "Cargo.toml" file.
    {
        println!("Adding nannou dependency \"{}\"", nannou_dependency);
        let cargo_toml_path = project_path.join("Cargo").with_extension("toml");
        let mut file = fs::OpenOptions::new()
            .write(true)
            .append(true)
            .open(&cargo_toml_path)
            .expect("failed to open \"Cargo.toml\" to add nannou dependency");
        writeln!(file, "\n{}", nannou_dependency).expect("failed to append nannou dependency");
    }

    // Change the directory to the newly created path.
    println!("Changing the current directory to \"{}\"", project_path.display());
    env::set_current_dir(&project_path).expect("failed to change directories");

    // Building and running.
    let bev = random_beverage();
    println!("Building `{}`. This might take a while for the first time. Grab a {}?", name, bev);
    let mut child = Command::new("cargo")
        .arg("build")
        .arg("--release")
        .stderr(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("failed to spawn cargo build and run process");

    // Read from cargo's stdout and stderr.
    let err = io::BufReader::new(child.stderr.take().unwrap());
    let out = io::BufReader::new(child.stdout.take().unwrap());
    let (tx, rx) = mpsc::channel();
    let tx_err = tx.clone();

    let err_handle = thread::spawn(move || {
        for line in err.lines().filter_map(|l| l.ok()) {
            tx_err.send(Err(line)).expect("failed to send piped stderr");
        }
    });

    let out_handle = thread::spawn(move || {
        for line in out.lines().filter_map(|l| l.ok()) {
            tx.send(Ok(line)).expect("failed to send piped stdout");
        }
    });

    // Print the stdout and stderr from cargo.
    for result in rx {
        match result {
            Ok(line) => println!("[cargo] {}", line),
            Err(line) => eprintln!("[cargo] {}", line),
        }
    }

    err_handle.join().unwrap();
    out_handle.join().unwrap();

    // If the exe is where it should be, assume the build succeeded.
    let exe_path = project_path.join("target").join("release").join(&name);
    if exe_path.exists() {
        println!("Successfully built \"{}\"! Go forth and create!", name);
    }
}
<|endoftext|>


<commit_before>extern crate polydraw;

use polydraw::{Application, Renderer, RenderFrame};
use polydraw::geom::line::{LineSegment, LineIntersection};
use polydraw::draw::{RGB, bresenham, hline, vline};

struct IntersectionRenderer {
   l1: LineSegment<f64>,
   l2: LineSegment<f64>
}

impl IntersectionRenderer {
   fn new() -> Self {
      IntersectionRenderer {
         l1: LineSegment::default(),
         l2: LineSegment::default()
      }
   }

   fn point_rect(&self, frame: &mut RenderFrame, x: i32, y: i32, color: &RGB) {
      let half = 12;
      let right_x = x + half;
      let left_x = x - half;
      let top_y = y + half;
      let bottom_y = y - half;

      hline(frame, left_x, right_x, top_y, color);
      hline(frame, left_x, right_x, bottom_y, color);

      vline(frame, left_x, bottom_y, top_y, color);
      vline(frame, right_x, bottom_y, top_y, color);
   }
}

impl Renderer for IntersectionRenderer {
   fn init(&mut self, frame: &RenderFrame) {
      self.l1.update(
         100_f64, 120_f64,
         frame.width as f64 - 100_f64, frame.height as f64 - 100_f64
      );

      self.l2.update(
         140_f64, frame.height as f64 - 90_f64,
         frame.width as f64 - 140_f64, 100_f64
      );
   }

   fn render(&mut self, frame: &mut RenderFrame) {
      frame.clear();

      let l1_color = RGB::new(127, 223, 255);
      let l2_color = RGB::new(127, 255, 223);
      let intersection_color = RGB::new(255, 223, 191);

      let l1_p1_x = self.l1.x1() as i32;
      let l1_p1_y = self.l1.y1() as i32;

      let l1_p2_x = self.l1.x2() as i32;
      let l1_p2_y = self.l1.y2() as i32;

      let l2_p1_x = self.l2.x1() as i32;
      let l2_p1_y = self.l2.y1() as i32;

      let l2_p2_x = self.l2.x2() as i32;
      let l2_p2_y = self.l2.y2() as i32;

      bresenham(frame, l1_p1_x, l1_p1_y, l1_p2_x, l1_p2_y, &l1_color);
      bresenham(frame, l2_p1_x, l2_p1_y, l2_p2_x, l2_p2_y, &l2_color);

      self.point_rect(frame, l1_p1_x, l1_p1_y, &l1_color);
      self.point_rect(frame, l1_p2_x, l1_p2_y, &l1_color);
      self.point_rect(frame, l2_p1_x, l2_p1_y, &l2_color);
      self.point_rect(frame, l2_p2_x, l2_p2_y, &l2_color);

      let intersection = self.l1.line().intersect(self.l2.line());
      match intersection {
         LineIntersection::Point(p) => {
            self.point_rect(frame, p.x as i32, p.y as i32, &intersection_color);
         },
         _ => {}
      }
   }
}

fn main() {
   let mut renderer = IntersectionRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Intersection")
      .run();
}
<commit_msg>Advancing the intersection example with resizing support<commit_after>extern crate polydraw;

use polydraw::{Application, Renderer, RenderFrame};
use polydraw::geom::line::{LineSegment, LineIntersection};
use polydraw::geom::point::Point;
use polydraw::draw::{RGB, bresenham, hline, vline};

struct IntersectionRenderer {
   intersection: Option<Point<f64>>,

   l1: LineSegment<f64>,
   l2: LineSegment<f64>,

   top_left: Point<f64>,
   top_right: Point<f64>,
   bottom_left: Point<f64>,
   bottom_right: Point<f64>,

   width: u32,
   height: u32,
}

impl IntersectionRenderer {
   fn new() -> Self {
      IntersectionRenderer {
         intersection: None,

         l1: LineSegment::default(),
         l2: LineSegment::default(),

         top_left: Point::default(),
         top_right: Point::default(),
         bottom_left: Point::default(),
         bottom_right: Point::default(),

         width: 0,
         height: 0,
      }
   }

   fn point_rect(&self, frame: &mut RenderFrame, x: i32, y: i32, color: &RGB) {
      let half = 12;
      let right_x = x + half;
      let left_x = x - half;
      let top_y = y + half;
      let bottom_y = y - half;

      hline(frame, left_x, right_x, top_y, color);
      hline(frame, left_x, right_x, bottom_y, color);

      vline(frame, left_x, bottom_y, top_y, color);
      vline(frame, right_x, bottom_y, top_y, color);
   }

   fn recalc(&mut self) {
      self.l1.update(
         self.bottom_left.x, self.bottom_left.y,
         self.width as f64 - self.top_right.x, self.height as f64 - self.top_right.y
      );

      self.l2.update(
         self.top_left.x, self.height as f64 - self.top_left.y,
         self.width as f64 - self.bottom_right.x, self.bottom_right.y
      );

      let intersection = self.l1.line().intersect(self.l2.line());
      match intersection {
         LineIntersection::Point(p) => {
            self.intersection = Some(p);
         },
         _ => {
            self.intersection = None;
         }
      }
   }
}

impl Renderer for IntersectionRenderer {
   fn init(&mut self, frame: &RenderFrame) {
      self.bottom_left.update(100_f64, 120_f64);
      self.top_right.update(100_f64, 100_f64);

      self.top_left.update(140_f64, 90_f64);
      self.bottom_right.update(140_f64, 100_f64);

      self.width = frame.width;
      self.height = frame.height;

      self.recalc();
   }

   fn resized(&mut self, width: u32, height: u32) {
      self.width = width;
      self.height = height;

      self.recalc();
   }

   fn render(&mut self, frame: &mut RenderFrame) {
      frame.clear();

      let l1_color = RGB::new(127, 223, 255);
      let l2_color = RGB::new(127, 255, 223);
      let intersection_color = RGB::new(255, 223, 191);

      let l1_p1_x = self.l1.x1() as i32;
      let l1_p1_y = self.l1.y1() as i32;

      let l1_p2_x = self.l1.x2() as i32;
      let l1_p2_y = self.l1.y2() as i32;

      let l2_p1_x = self.l2.x1() as i32;
      let l2_p1_y = self.l2.y1() as i32;

      let l2_p2_x = self.l2.x2() as i32;
      let l2_p2_y = self.l2.y2() as i32;

      bresenham(frame, l1_p1_x, l1_p1_y, l1_p2_x, l1_p2_y, &l1_color);
      bresenham(frame, l2_p1_x, l2_p1_y, l2_p2_x, l2_p2_y, &l2_color);

      self.point_rect(frame, l1_p1_x, l1_p1_y, &l1_color);
      self.point_rect(frame, l1_p2_x, l1_p2_y, &l1_color);
      self.point_rect(frame, l2_p1_x, l2_p1_y, &l2_color);
      self.point_rect(frame, l2_p2_x, l2_p2_y, &l2_color);

      match self.intersection {
         Some(ref p) => {
            self.point_rect(frame, p.x as i32, p.y as i32, &intersection_color);
         },
         _ => {}
      }
   }
}

fn main() {
   let mut renderer = IntersectionRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Intersection")
      .run();
}
<|endoftext|>


<commit_before><commit_msg>Fix tests<commit_after><|endoftext|>