<commit_before>extern crate sputnikvm;
extern crate serde_json;

mod blockchain;

pub use self::blockchain::{JSONBlock, create_block, create_context};

use serde_json::Value;
use std::str::FromStr;
use sputnikvm::{Gas, M256, U256, Address, read_hex};
use sputnikvm::vm::errors::RequireError;
use sputnikvm::vm::{VM, SeqVM, AccountCommitment, Context, Account, HashMapStorage, Patch, VMStatus};

pub fn fire_with_block(machine: &mut SeqVM, block: &JSONBlock) {
    loop {
        match machine.fire() {
            Err(RequireError::Account(address)) => {
                let account = block.request_account(address);
                machine.commit_account(account);
            },
            Err(RequireError::AccountCode(address)) => {
                let account = block.request_account_code(address);
                machine.commit_account(account);
            },
            Err(RequireError::Blockhash(number)) => {
                // The test JSON file doesn't expose any block
                // information. So those numbers are crafted by hand.
                let hash1 = M256::from_str("0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6").unwrap();
                let hash2 = M256::from_str("0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5").unwrap();
                let hash256 = M256::from_str("0x6ca54da2c4784ea43fd88b3402de07ae4bced597cbb19f323b7595857a6720ae").unwrap();

                let hash = if number == M256::from(1u64) {
                    hash1
                } else if number == M256::from(2u64) {
                    hash2
                } else if number == M256::from(256u64) {
                    hash256
                } else {
                    panic!();
                };

                machine.commit_blockhash(number, hash);
            },
            Ok(()) => return,
        }
    }
}

pub fn apply_to_block(machine: &SeqVM, block: &mut JSONBlock) {
    for account in machine.accounts() {
        let account = (*account).clone();
        block.apply_account(account);
    }
    for log in machine.logs() {
        let log = (*log).clone();
        block.apply_log(log);
    }
}

pub fn create_machine(v: &Value, block: &JSONBlock) -> SeqVM {
    let transaction = create_context(v);

    SeqVM::new(transaction, block.block_header(), Patch::None)
}

pub fn test_machine(v: &Value, machine: &SeqVM, block: &JSONBlock, debug: bool) -> bool {
    let ref callcreates = v["callcreates"];

    if callcreates.as_array().is_some() {
        let mut i = 0;
        for callcreate in callcreates.as_array().unwrap() {
            let data = read_hex(callcreate["data"].as_str().unwrap()).unwrap();
            let destination = {
                let destination = callcreate["destination"].as_str().unwrap();
                if destination == "" {
                    None
                } else {
                    Some(Address::from_str(destination).unwrap())
                }
            };
            let gas_limit = Gas::from_str(callcreate["gasLimit"].as_str().unwrap()).unwrap();
            let value = U256::from_str(callcreate["value"].as_str().unwrap()).unwrap();

            if i >= machine.history().len() {
                if debug {
                    print!("\n");
                    println!("Transaction check failed, expected more than {} items.", i);
                }
                return false;
            }
            let ref transaction = machine.history()[i];
            if destination.is_some() {
                if transaction.address != destination.unwrap() {
                    if debug {
                        print!("\n");
                        println!("Transaction address mismatch. 0x{:x} != 0x{:x}.", transaction.address, destination.unwrap());
                    }
                    return false;
                }
            }
            if transaction.gas_limit != gas_limit || transaction.value != value || transaction.data != data {
                if debug {
                    print!("\n");
                    println!("Transaction mismatch. gas limit 0x{:x} =?= 0x{:x}, value 0x{:x} =?= 0x{:x}", transaction.gas_limit, gas_limit, transaction.value, value);
                }
                return false;
            }

            i = i + 1;
        }
    }

    let out = v["out"].as_str();
    let gas = v["gas"].as_str();

    if out.is_some() {
        let out = read_hex(out.unwrap()).unwrap();
        let out_ref: &[u8] = out.as_ref();
        if machine.out() != out_ref {
            if debug {
                print!("\n");
                println!("Return value check failed. {:?} != {:?}", machine.out(), out_ref);
            }

            return false;
        }
    }

    if gas.is_some() {
        let gas = Gas::from_str(gas.unwrap()).unwrap();
        if machine.available_gas() != gas {
            if debug {
                print!("\n");
                println!("Gas check failed, VM returned: 0x{:x}, expected: 0x{:x}",
                         machine.available_gas(), gas);
            }

            return false;
        }
    }

    let ref post_addresses = v["post"];

    for (address, data) in post_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();
        let code_ref: &[u8] = code.as_ref();

        if code_ref != block.account_code(address) {
            if debug {
                print!("\n");
                println!("Account code check failed for address 0x{:x}.", address);
            }

            return false;
        }
        if balance != block.balance(address) {
            if debug {
                print!("\n");
                println!("Balance check failed for address 0x{:x}.", address);
            }

            return false;
        }

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = M256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            if value != block.account_storage(address, index) {
                if debug {
                    print!("\n");
                    println!("Storage check failed for address 0x{:x} in storage index 0x{:x}",
                             address, index);
                    println!("Expected: 0x{:x}", value);
                    println!("Actual:   0x{:x}", block.account_storage(address, index));
                }
                return false;
            }
        }
    }

    let ref expect = v["expect"];

    if expect.as_object().is_some() {
        for (address, data) in expect.as_object().unwrap() {
            let address = Address::from_str(address.as_str()).unwrap();

            let storage = data["storage"].as_object().unwrap();
            for (index, value) in storage {
                let index = M256::from_str(index.as_str()).unwrap();
                let value = M256::from_str(value.as_str().unwrap()).unwrap();
                if value != block.account_storage(address, index) {
                    if debug {
                        print!("\n");
                        println!("Storage check (expect) failed for address 0x{:x} in storage index 0x{:x}",
                                 address, index);
                        println!("Expected: 0x{:x}", value);
                        println!("Actual:   0x{:x}", block.account_storage(address, index));
                    }
                    return false;
                }
            }
        }
    }

    let ref logs = v["logs"].as_array();

    if logs.is_some() {
        let logs = logs.unwrap();

        for log in logs {
            let log = log.as_object().unwrap();

            let address = Address::from_str(log["address"].as_str().unwrap()).unwrap();
            let data = read_hex(log["data"].as_str().unwrap()).unwrap();
            let mut topics: Vec<M256> = Vec::new();

            for topic in log["topics"].as_array().unwrap() {
                topics.push(M256::from_str(topic.as_str().unwrap()).unwrap());
            }

            if !block.find_log(address, data.as_slice(), topics.as_slice()) {
                if debug {
                    print!("\n");
                    println!("Log match failed.");
                }
                return false;
            }
        }
    }

    return true;
}

fn is_ok(status: VMStatus) -> bool {
    match status {
        VMStatus::ExitedOk => true,
        _ => false,
    }
}

pub fn test_transaction(name: &str, v: &Value, debug: bool) -> bool {
    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    println!("status: {:?}", machine.status());
    let out = v["out"].as_str();

    if out.is_some() {
        if is_ok(machine.status()) {
            if test_machine(v, &machine, &block, debug) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        if !is_ok(machine.status()) {
            return true;
        } else {
            return false;
        }
    }
}
<commit_msg>Problem: debug information for transaction check is incomplete Solution: add data<commit_after>extern crate sputnikvm;
extern crate serde_json;

mod blockchain;

pub use self::blockchain::{JSONBlock, create_block, create_context};

use serde_json::Value;
use std::str::FromStr;
use sputnikvm::{Gas, M256, U256, Address, read_hex};
use sputnikvm::vm::errors::RequireError;
use sputnikvm::vm::{VM, SeqVM, AccountCommitment, Context, Account, HashMapStorage, Patch, VMStatus};

pub fn fire_with_block(machine: &mut SeqVM, block: &JSONBlock) {
    loop {
        match machine.fire() {
            Err(RequireError::Account(address)) => {
                let account = block.request_account(address);
                machine.commit_account(account);
            },
            Err(RequireError::AccountCode(address)) => {
                let account = block.request_account_code(address);
                machine.commit_account(account);
            },
            Err(RequireError::Blockhash(number)) => {
                // The test JSON file doesn't expose any block
                // information. So those numbers are crafted by hand.
                let hash1 = M256::from_str("0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6").unwrap();
                let hash2 = M256::from_str("0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5").unwrap();
                let hash256 = M256::from_str("0x6ca54da2c4784ea43fd88b3402de07ae4bced597cbb19f323b7595857a6720ae").unwrap();

                let hash = if number == M256::from(1u64) {
                    hash1
                } else if number == M256::from(2u64) {
                    hash2
                } else if number == M256::from(256u64) {
                    hash256
                } else {
                    panic!();
                };

                machine.commit_blockhash(number, hash);
            },
            Ok(()) => return,
        }
    }
}

pub fn apply_to_block(machine: &SeqVM, block: &mut JSONBlock) {
    for account in machine.accounts() {
        let account = (*account).clone();
        block.apply_account(account);
    }
    for log in machine.logs() {
        let log = (*log).clone();
        block.apply_log(log);
    }
}

pub fn create_machine(v: &Value, block: &JSONBlock) -> SeqVM {
    let transaction = create_context(v);

    SeqVM::new(transaction, block.block_header(), Patch::None)
}

pub fn test_machine(v: &Value, machine: &SeqVM, block: &JSONBlock, debug: bool) -> bool {
    let ref callcreates = v["callcreates"];

    if callcreates.as_array().is_some() {
        let mut i = 0;
        for callcreate in callcreates.as_array().unwrap() {
            let data = read_hex(callcreate["data"].as_str().unwrap()).unwrap();
            let destination = {
                let destination = callcreate["destination"].as_str().unwrap();
                if destination == "" {
                    None
                } else {
                    Some(Address::from_str(destination).unwrap())
                }
            };
            let gas_limit = Gas::from_str(callcreate["gasLimit"].as_str().unwrap()).unwrap();
            let value = U256::from_str(callcreate["value"].as_str().unwrap()).unwrap();

            if i >= machine.history().len() {
                if debug {
                    print!("\n");
                    println!("Transaction check failed, expected more than {} items.", i);
                }
                return false;
            }
            let ref transaction = machine.history()[i];
            if destination.is_some() {
                if transaction.address != destination.unwrap() {
                    if debug {
                        print!("\n");
                        println!("Transaction address mismatch. 0x{:x} != 0x{:x}.", transaction.address, destination.unwrap());
                    }
                    return false;
                }
            }
            if transaction.gas_limit != gas_limit || transaction.value != value || transaction.data != data {
                if debug {
                    print!("\n");
                    println!("Transaction mismatch. gas limit 0x{:x} =?= 0x{:x}, value 0x{:x} =?= 0x{:x}, data {:?} =?= {:?}", transaction.gas_limit, gas_limit, transaction.value, value, transaction.data, data);
                }
                return false;
            }

            i = i + 1;
        }
    }

    let out = v["out"].as_str();
    let gas = v["gas"].as_str();

    if out.is_some() {
        let out = read_hex(out.unwrap()).unwrap();
        let out_ref: &[u8] = out.as_ref();
        if machine.out() != out_ref {
            if debug {
                print!("\n");
                println!("Return value check failed. {:?} != {:?}", machine.out(), out_ref);
            }

            return false;
        }
    }

    if gas.is_some() {
        let gas = Gas::from_str(gas.unwrap()).unwrap();
        if machine.available_gas() != gas {
            if debug {
                print!("\n");
                println!("Gas check failed, VM returned: 0x{:x}, expected: 0x{:x}",
                         machine.available_gas(), gas);
            }

            return false;
        }
    }

    let ref post_addresses = v["post"];

    for (address, data) in post_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();
        let code_ref: &[u8] = code.as_ref();

        if code_ref != block.account_code(address) {
            if debug {
                print!("\n");
                println!("Account code check failed for address 0x{:x}.", address);
            }

            return false;
        }
        if balance != block.balance(address) {
            if debug {
                print!("\n");
                println!("Balance check failed for address 0x{:x}.", address);
            }

            return false;
        }

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = M256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            if value != block.account_storage(address, index) {
                if debug {
                    print!("\n");
                    println!("Storage check failed for address 0x{:x} in storage index 0x{:x}",
                             address, index);
                    println!("Expected: 0x{:x}", value);
                    println!("Actual:   0x{:x}", block.account_storage(address, index));
                }
                return false;
            }
        }
    }

    let ref expect = v["expect"];

    if expect.as_object().is_some() {
        for (address, data) in expect.as_object().unwrap() {
            let address = Address::from_str(address.as_str()).unwrap();

            let storage = data["storage"].as_object().unwrap();
            for (index, value) in storage {
                let index = M256::from_str(index.as_str()).unwrap();
                let value = M256::from_str(value.as_str().unwrap()).unwrap();
                if value != block.account_storage(address, index) {
                    if debug {
                        print!("\n");
                        println!("Storage check (expect) failed for address 0x{:x} in storage index 0x{:x}",
                                 address, index);
                        println!("Expected: 0x{:x}", value);
                        println!("Actual:   0x{:x}", block.account_storage(address, index));
                    }
                    return false;
                }
            }
        }
    }

    let ref logs = v["logs"].as_array();

    if logs.is_some() {
        let logs = logs.unwrap();

        for log in logs {
            let log = log.as_object().unwrap();

            let address = Address::from_str(log["address"].as_str().unwrap()).unwrap();
            let data = read_hex(log["data"].as_str().unwrap()).unwrap();
            let mut topics: Vec<M256> = Vec::new();

            for topic in log["topics"].as_array().unwrap() {
                topics.push(M256::from_str(topic.as_str().unwrap()).unwrap());
            }

            if !block.find_log(address, data.as_slice(), topics.as_slice()) {
                if debug {
                    print!("\n");
                    println!("Log match failed.");
                }
                return false;
            }
        }
    }

    return true;
}

fn is_ok(status: VMStatus) -> bool {
    match status {
        VMStatus::ExitedOk => true,
        _ => false,
    }
}

pub fn test_transaction(name: &str, v: &Value, debug: bool) -> bool {
    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    println!("status: {:?}", machine.status());
    let out = v["out"].as_str();

    if out.is_some() {
        if is_ok(machine.status()) {
            if test_machine(v, &machine, &block, debug) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        if !is_ok(machine.status()) {
            return true;
        } else {
            return false;
        }
    }
}
<|endoftext|>


<commit_before>// BatWarn
// Low Battery Warning Utility
// Polls battery status and pops up warning when low.

#![allow(unstable)]
extern crate collections;
extern crate regex;
use std::io::IoResult;
use std::io::timer::sleep;
use std::io::fs::File;
use std::io::process::{Command, Process, ProcessOutput};
use std::time::duration::Duration;
use std::num::from_str_radix;
use collections::string::String;
use regex::Regex;

static PERCENT_DANGER:     i32 = 94;
static PERCENT_CRITICAL:   i32 = 8;

#[derive(Debug)]
struct BatteryState {
    discharging: bool,
    percent: i32,
}

fn main() {
    // let poll_delay: Duration = Duration::minutes(5);
    let poll_delay: Duration = Duration::seconds(1);

    let mut nagproc: Option<Process> = None;

    loop {
        // Kill existing warnings
        nagproc = nagproc.and_then(|mut nagproc| {
            match nagproc.signal_kill() {
                Err(err) => {
                    println!("ERROR: {}", err);
                    Some(nagproc)
                },
                Ok(()) => None
            }
        });

        // Check battery status
        match acpi_battery_state() {
            Err(err) => {
                println!("ERROR: {}", err)
            },
            Ok(batstat) => {
                println!("{:?}", batstat);

                if !batstat.discharging {
                    // Do nothing
                } else if batstat.percent <= PERCENT_CRITICAL {
                    // Battery critically low.
                    match Command::new("i3-nagbar").arg("10").spawn() {
                        Err(err) =>
                            println!("ERROR: {}", err),
                        Ok(child) =>
                            nagproc = Some(child),
                    };
                } else if batstat.percent <= PERCENT_DANGER {
                    // Battery low.
                    let message = "WARNING: Battery low!";
                    let child = Command::new("i3-nagbar")
                        .arg("-t warning")
                        .arg(format!("-m {}", message))
                        .arg("10")
                        .spawn();
                    match child {
                        Err(err) =>
                            println!("ERROR: {}", err),
                        Ok(child) =>
                            nagproc = Some(child),
                    };
                } else {
                    // Battery discharging normally.
                }

            },
        }

        sleep(poll_delay);
    }
}

// Parse output from `acpi --battery`
fn acpi_battery_state() -> Result<BatteryState, String> {
    // ACPI output format: "Battery #{number}: #{state}, #{percent}%..."
    match acpi_battery_string() {
        Err(err) => Err(err),
        Ok(s) => {
            let re = Regex::new(r"Battery \d+: (\w+), (\d+)%.*").unwrap();
            match re.captures(s.as_slice()) {
                None => Err(String::from_str("malformed acpi output")),
                Some(captures) => {
                    let state = captures.at(1).unwrap();
                    let percent_str = captures.at(2).unwrap();
                    let percent = from_str_radix::<i32>(percent_str, 10).unwrap();
                    Ok(BatteryState {
                        discharging: state == "Discharging",
                        percent: percent,})
                }
            }
        },
    }
}

// Get output from `acpi --battery`
fn acpi_battery_string() -> Result<String, String> {
    let mut cmd = Command::new("acpi");
    cmd.arg("--battery");
    match cmd.output() {
        Err(err) => Err(String::from_str(err.desc)),
        Ok(ProcessOutput { status: exit, output: stdout, error: _ }) => {
            match exit.success() {
                false => Err(String::from_str("acpi returned with non-zero exit status")),
                true => {
                    let stdout = String::from_utf8(stdout).unwrap();
                    Ok(stdout)
                },
            }
        },
    }
}

// Read battery state from /proc.
#[allow(dead_code)]
fn read_battery_state_string() -> IoResult<String> {
    let path = Path::new("/proc/acpi/battery/BAT0/state");
    match File::open(&path) {
        Err(err) => Err(err),
        Ok(mut file) => file.read_to_string(),
    }
}

<commit_msg>factor out<commit_after>// BatWarn
// Low Battery Warning Utility
// Polls battery status and pops up warning when low.

#![allow(unstable)]
extern crate collections;
extern crate regex;
use std::io::{IoResult, IoError};
use std::io::timer::sleep;
use std::io::fs::File;
use std::io::process::{Command, Process, ProcessOutput};
use std::time::duration::Duration;
use std::num::from_str_radix;
use collections::string::String;
use regex::Regex;

static PERCENT_DANGER:     i32 = 20;
static PERCENT_CRITICAL:   i32 = 8;

#[derive(Debug)]
struct BatteryState {
    discharging: bool,
    percent: i32,
}

fn main() {
    // let poll_delay: Duration = Duration::minutes(5);
    let poll_delay: Duration = Duration::seconds(1);

    let mut nagproc: Option<Process> = None;

    loop {
        // Kill existing warnings
        nagproc = nagproc.and_then(|mut nagproc| {
            match nagproc.signal_kill() {
                Err(err) => {
                    println!("ERROR: {}", err);
                    Some(nagproc)
                },
                Ok(()) => None
            }
        });

        // Check battery status
        match acpi_battery_state() {
            Err(err) => {
                println!("ERROR: {}", err)
            },
            Ok(batstat) => {
                println!("{:?}", batstat);

                if !batstat.discharging {
                    // Do nothing
                } else if batstat.percent <= PERCENT_CRITICAL {
                    // Battery critically low.
                    let msg = format!("WARNING: Battery critically low!");
                    match show_warning(msg, true) {
                        Err(err) =>
                            println!("ERROR: {}", err),
                        Ok(child) =>
                            nagproc = Some(child),
                    };
                } else if batstat.percent <= PERCENT_DANGER {
                    // Battery low.
                    let msg = format!("WARNING: Battery low!");
                    match show_warning(msg, false) {
                        Err(err) =>
                            println!("ERROR: {}", err),
                        Ok(child) =>
                            nagproc = Some(child),
                    };
                } else {
                    // Battery discharging normally.
                }

            },
        }

        sleep(poll_delay);
    }
}

fn show_warning(msg: String, critical: bool) -> Result<Process, IoError> {
    let warning_level = match critical {
        false => "warning",
        true => "error",
    };
    Command::new("i3-nagbar")
        .arg("-t")
        .arg(warning_level)
        .arg(format!("-m {}", msg))
        .spawn()
}

// Parse output from `acpi --battery`
fn acpi_battery_state() -> Result<BatteryState, String> {
    // ACPI output format: "Battery #{number}: #{state}, #{percent}%..."
    match acpi_battery_string() {
        Err(err) => Err(err),
        Ok(s) => {
            let re = Regex::new(r"Battery \d+: (\w+), (\d+)%.*").unwrap();
            match re.captures(s.as_slice()) {
                None => Err(String::from_str("malformed acpi output")),
                Some(captures) => {
                    let state = captures.at(1).unwrap();
                    let percent_str = captures.at(2).unwrap();
                    let percent = from_str_radix::<i32>(percent_str, 10).unwrap();
                    Ok(BatteryState {
                        discharging: state == "Discharging",
                        percent: percent,})
                }
            }
        },
    }
}

// Get output from `acpi --battery`
fn acpi_battery_string() -> Result<String, String> {
    let mut cmd = Command::new("acpi");
    cmd.arg("--battery");
    match cmd.output() {
        Err(err) => Err(String::from_str(err.desc)),
        Ok(ProcessOutput { status: exit, output: stdout, error: _ }) => {
            match exit.success() {
                false => Err(String::from_str("acpi returned with non-zero exit status")),
                true => {
                    let stdout = String::from_utf8(stdout).unwrap();
                    Ok(stdout)
                },
            }
        },
    }
}

// Read battery state from /proc.
#[allow(dead_code)]
fn read_battery_state_string() -> IoResult<String> {
    let path = Path::new("/proc/acpi/battery/BAT0/state");
    match File::open(&path) {
        Err(err) => Err(err),
        Ok(mut file) => file.read_to_string(),
    }
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate bencher;
extern crate variable_size_byte_writer;

use std::io::prelude::*;
use bencher::Bencher;
use variable_size_byte_writer::*;

fn write_32_vec(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new(8192);
    let mut target = std::io::Cursor::new(vec![]);

    bench.iter(|| {
        writer.write_32(&mut target, 0x7F1F0, 21)
    });
}

fn write_32_file(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new(8192);
    let mut file = std::fs::File::create("benches/temp/write_32_file.temp").unwrap();
    bench.iter(|| {
        writer.write_32(&mut file, 0x7F1F0, 21)
    });
    std::fs::remove_file("benches/temp/write_32_file.temp").unwrap();
}

benchmark_group!(benches, write_32_vec, write_32_file);
benchmark_main!(benches);<commit_msg>added benches for 16bit restricted writes<commit_after>#[macro_use]
extern crate bencher;
extern crate variable_size_byte_writer;

use std::io::prelude::*;
use bencher::Bencher;
use variable_size_byte_writer::*;

fn write_32_vec(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new(8192);
    let mut target = std::io::Cursor::new(vec![]);

    bench.iter(|| {
        writer.write_32(&mut target, 0x7F1F0, 21)
    });
}

fn write_32_file(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new(8192);
    let mut file = std::fs::File::create("benches/temp/write_32_file.temp").unwrap();
    bench.iter(|| {
        writer.write_32(&mut file, 0x7F1F0, 21)
    });
    std::fs::remove_file("benches/temp/write_32_file.temp").unwrap();
}

fn write_16_vec(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new(8192);
    let mut target = std::io::Cursor::new(vec![]);

    bench.iter(|| {
        writer.write_16(&mut target, 0x1A, 9)
    });
}

fn write_16_file(bench: &mut Bencher) {
    let mut writer = VariableSizeByteWriter::new(8192);
    let mut file = std::fs::File::create("benches/temp/write_16_file.temp").unwrap();
    bench.iter(|| {
        writer.write_16(&mut file, 0x1A, 9)
    });
    std::fs::remove_file("benches/temp/write_16_file.temp").unwrap();
}

benchmark_group!(benches,
    write_32_vec,
    write_32_file,
    write_16_vec,
    write_16_file
);
benchmark_main!(benches);<|endoftext|>


<commit_before>//! This module is used to store stuff from Rust's AST in a more convenient
//! manner (and with prettier names) before cleaning.
pub use self::StructType::*;

use syntax::ast;
use syntax::ast::Name;
use syntax_expand::base::MacroKind;
use syntax_pos::{self, Span};

use rustc::hir;
use rustc::hir::def_id::CrateNum;
use rustc::hir::ptr::P;

pub struct Module<'hir> {
    pub name: Option<Name>,
    pub attrs: &'hir [ast::Attribute],
    pub where_outer: Span,
    pub where_inner: Span,
    pub extern_crates: Vec<ExternCrate<'hir>>,
    pub imports: Vec<Import<'hir>>,
    pub structs: Vec<Struct<'hir>>,
    pub unions: Vec<Union<'hir>>,
    pub enums: Vec<Enum<'hir>>,
    pub fns: Vec<Function<'hir>>,
    pub mods: Vec<Module<'hir>>,
    pub id: hir::HirId,
    pub typedefs: Vec<Typedef<'hir>>,
    pub opaque_tys: Vec<OpaqueTy<'hir>>,
    pub statics: Vec<Static<'hir>>,
    pub constants: Vec<Constant<'hir>>,
    pub traits: Vec<Trait<'hir>>,
    pub vis: &'hir hir::Visibility,
    pub impls: Vec<Impl<'hir>>,
    pub foreigns: Vec<ForeignItem<'hir>>,
    pub macros: Vec<Macro<'hir>>,
    pub proc_macros: Vec<ProcMacro<'hir>>,
    pub trait_aliases: Vec<TraitAlias<'hir>>,
    pub is_crate: bool,
}

impl Module<'hir> {
    pub fn new(
        name: Option<Name>,
        attrs: &'hir [ast::Attribute],
        vis: &'hir hir::Visibility,
    ) -> Module<'hir> {
        Module {
            name       : name,
            id: hir::CRATE_HIR_ID,
            vis,
            where_outer: syntax_pos::DUMMY_SP,
            where_inner: syntax_pos::DUMMY_SP,
            attrs,
            extern_crates: Vec::new(),
            imports    :   Vec::new(),
            structs    :   Vec::new(),
            unions     :   Vec::new(),
            enums      :   Vec::new(),
            fns        :   Vec::new(),
            mods       :   Vec::new(),
            typedefs   :   Vec::new(),
            opaque_tys :  Vec::new(),
            statics    :   Vec::new(),
            constants  :   Vec::new(),
            traits     :   Vec::new(),
            impls      :   Vec::new(),
            foreigns   :   Vec::new(),
            macros     :   Vec::new(),
            proc_macros:   Vec::new(),
            trait_aliases: Vec::new(),
            is_crate   : false,
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub enum StructType {
    /// A braced struct
    Plain,
    /// A tuple struct
    Tuple,
    /// A unit struct
    Unit,
}

pub struct Struct<'hir> {
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
    pub struct_type: StructType,
    pub name: Name,
    pub generics: &'hir hir::Generics,
    pub attrs: &'hir [ast::Attribute],
    pub fields: &'hir [hir::StructField],
    pub whence: Span,
}

pub struct Union<'hir> {
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
    pub struct_type: StructType,
    pub name: Name,
    pub generics: &'hir hir::Generics,
    pub attrs: &'hir [ast::Attribute],
    pub fields: &'hir [hir::StructField],
    pub whence: Span,
}

pub struct Enum<'hir> {
    pub vis: &'hir hir::Visibility,
    pub variants: Vec<Variant<'hir>>,
    pub generics: &'hir hir::Generics,
    pub attrs: &'hir [ast::Attribute],
    pub id: hir::HirId,
    pub whence: Span,
    pub name: Name,
}

pub struct Variant<'hir> {
    pub name: Name,
    pub id: hir::HirId,
    pub attrs: &'hir [ast::Attribute],
    pub def: &'hir hir::VariantData,
    pub whence: Span,
}

pub struct Function<'hir> {
    pub decl: &'hir hir::FnDecl,
    pub attrs: &'hir [ast::Attribute],
    pub id: hir::HirId,
    pub name: Name,
    pub vis: &'hir hir::Visibility,
    pub header: hir::FnHeader,
    pub whence: Span,
    pub generics: &'hir hir::Generics,
    pub body: hir::BodyId,
}

pub struct Typedef<'hir> {
    pub ty: &'hir P<hir::Ty>,
    pub gen: &'hir hir::Generics,
    pub name: Name,
    pub id: hir::HirId,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
    pub vis: &'hir hir::Visibility,
}

pub struct OpaqueTy<'hir> {
    pub opaque_ty: &'hir hir::OpaqueTy,
    pub name: Name,
    pub id: hir::HirId,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
    pub vis: &'hir hir::Visibility,
}

#[derive(Debug)]
pub struct Static<'hir> {
    pub type_: &'hir P<hir::Ty>,
    pub mutability: hir::Mutability,
    pub expr: hir::BodyId,
    pub name: Name,
    pub attrs: &'hir [ast::Attribute],
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
    pub whence: Span,
}

pub struct Constant<'hir> {
    pub type_: &'hir P<hir::Ty>,
    pub expr: hir::BodyId,
    pub name: Name,
    pub attrs: &'hir [ast::Attribute],
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
    pub whence: Span,
}

pub struct Trait<'hir> {
    pub is_auto: hir::IsAuto,
    pub unsafety: hir::Unsafety,
    pub name: Name,
    pub items: Vec<&'hir hir::TraitItem>,
    pub generics: &'hir hir::Generics,
    pub bounds: &'hir [hir::GenericBound],
    pub attrs: &'hir [ast::Attribute],
    pub id: hir::HirId,
    pub whence: Span,
    pub vis: &'hir hir::Visibility,
}

pub struct TraitAlias<'hir> {
    pub name: Name,
    pub generics: &'hir hir::Generics,
    pub bounds: &'hir [hir::GenericBound],
    pub attrs: &'hir [ast::Attribute],
    pub id: hir::HirId,
    pub whence: Span,
    pub vis: &'hir hir::Visibility,
}

#[derive(Debug)]
pub struct Impl<'hir> {
    pub unsafety: hir::Unsafety,
    pub polarity: hir::ImplPolarity,
    pub defaultness: hir::Defaultness,
    pub generics: &'hir hir::Generics,
    pub trait_: &'hir Option<hir::TraitRef>,
    pub for_: &'hir P<hir::Ty>,
    pub items: Vec<&'hir hir::ImplItem>,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
}

pub struct ForeignItem<'hir> {
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
    pub name: Name,
    pub kind: &'hir hir::ForeignItemKind,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
}

// For Macro we store the DefId instead of the NodeId, since we also create
// these imported macro_rules (which only have a DUMMY_NODE_ID).
pub struct Macro<'hir> {
    pub name: Name,
    pub hid: hir::HirId,
    pub def_id: hir::def_id::DefId,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
    pub matchers: hir::HirVec<Span>,
    pub imported_from: Option<Name>,
}

pub struct ExternCrate<'hir> {
    pub name: Name,
    pub cnum: CrateNum,
    pub path: Option<String>,
    pub vis: &'hir hir::Visibility,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
}

pub struct Import<'hir> {
    pub name: Name,
    pub id: hir::HirId,
    pub vis: &'hir hir::Visibility,
    pub attrs: &'hir [ast::Attribute],
    pub path: &'hir hir::Path,
    pub glob: bool,
    pub whence: Span,
}

pub struct ProcMacro<'hir> {
    pub name: Name,
    pub id: hir::HirId,
    pub kind: MacroKind,
    pub helpers: Vec<Name>,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
}

pub fn struct_type_from_def(vdata: &hir::VariantData) -> StructType {
    match *vdata {
        hir::VariantData::Struct(..) => Plain,
        hir::VariantData::Tuple(..) => Tuple,
        hir::VariantData::Unit(..) => Unit,
    }
}
<commit_msg>Add missing space in librustdoc<commit_after>//! This module is used to store stuff from Rust's AST in a more convenient
//! manner (and with prettier names) before cleaning.
pub use self::StructType::*;

use syntax::ast;
use syntax::ast::Name;
use syntax_expand::base::MacroKind;
use syntax_pos::{self, Span};

use rustc::hir;
use rustc::hir::def_id::CrateNum;
use rustc::hir::ptr::P;

pub struct Module<'hir> {
    pub name: Option<Name>,
    pub attrs: &'hir [ast::Attribute],
    pub where_outer: Span,
    pub where_inner: Span,
    pub extern_crates: Vec<ExternCrate<'hir>>,
    pub imports: Vec<Import<'hir>>,
    pub structs: Vec<Struct<'hir>>,
    pub unions: Vec<Union<'hir>>,
    pub enums: Vec<Enum<'hir>>,
    pub fns: Vec<Function<'hir>>,
    pub mods: Vec<Module<'hir>>,
    pub id: hir::HirId,
    pub typedefs: Vec<Typedef<'hir>>,
    pub opaque_tys: Vec<OpaqueTy<'hir>>,
    pub statics: Vec<Static<'hir>>,
    pub constants: Vec<Constant<'hir>>,
    pub traits: Vec<Trait<'hir>>,
    pub vis: &'hir hir::Visibility,
    pub impls: Vec<Impl<'hir>>,
    pub foreigns: Vec<ForeignItem<'hir>>,
    pub macros: Vec<Macro<'hir>>,
    pub proc_macros: Vec<ProcMacro<'hir>>,
    pub trait_aliases: Vec<TraitAlias<'hir>>,
    pub is_crate: bool,
}

impl Module<'hir> {
    pub fn new(
        name: Option<Name>,
        attrs: &'hir [ast::Attribute],
        vis: &'hir hir::Visibility,
    ) -> Module<'hir> {
        Module {
            name       : name,
            id: hir::CRATE_HIR_ID,
            vis,
            where_outer: syntax_pos::DUMMY_SP,
            where_inner: syntax_pos::DUMMY_SP,
            attrs,
            extern_crates: Vec::new(),
            imports    :   Vec::new(),
            structs    :   Vec::new(),
            unions     :   Vec::new(),
            enums      :   Vec::new(),
            fns        :   Vec::new(),
            mods       :   Vec::new(),
            typedefs   :   Vec::new(),
            opaque_tys :   Vec::new(),
            statics    :   Vec::new(),
            constants  :   Vec::new(),
            traits     :   Vec::new(),
            impls      :   Vec::new(),
            foreigns   :   Vec::new(),
            macros     :   Vec::new(),
            proc_macros:   Vec::new(),
            trait_aliases: Vec::new(),
            is_crate   : false,
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub enum StructType {
    /// A braced struct
    Plain,
    /// A tuple struct
    Tuple,
    /// A unit struct
    Unit,
}

pub struct Struct<'hir> {
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
    pub struct_type: StructType,
    pub name: Name,
    pub generics: &'hir hir::Generics,
    pub attrs: &'hir [ast::Attribute],
    pub fields: &'hir [hir::StructField],
    pub whence: Span,
}

pub struct Union<'hir> {
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
    pub struct_type: StructType,
    pub name: Name,
    pub generics: &'hir hir::Generics,
    pub attrs: &'hir [ast::Attribute],
    pub fields: &'hir [hir::StructField],
    pub whence: Span,
}

pub struct Enum<'hir> {
    pub vis: &'hir hir::Visibility,
    pub variants: Vec<Variant<'hir>>,
    pub generics: &'hir hir::Generics,
    pub attrs: &'hir [ast::Attribute],
    pub id: hir::HirId,
    pub whence: Span,
    pub name: Name,
}

pub struct Variant<'hir> {
    pub name: Name,
    pub id: hir::HirId,
    pub attrs: &'hir [ast::Attribute],
    pub def: &'hir hir::VariantData,
    pub whence: Span,
}

pub struct Function<'hir> {
    pub decl: &'hir hir::FnDecl,
    pub attrs: &'hir [ast::Attribute],
    pub id: hir::HirId,
    pub name: Name,
    pub vis: &'hir hir::Visibility,
    pub header: hir::FnHeader,
    pub whence: Span,
    pub generics: &'hir hir::Generics,
    pub body: hir::BodyId,
}

pub struct Typedef<'hir> {
    pub ty: &'hir P<hir::Ty>,
    pub gen: &'hir hir::Generics,
    pub name: Name,
    pub id: hir::HirId,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
    pub vis: &'hir hir::Visibility,
}

pub struct OpaqueTy<'hir> {
    pub opaque_ty: &'hir hir::OpaqueTy,
    pub name: Name,
    pub id: hir::HirId,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
    pub vis: &'hir hir::Visibility,
}

#[derive(Debug)]
pub struct Static<'hir> {
    pub type_: &'hir P<hir::Ty>,
    pub mutability: hir::Mutability,
    pub expr: hir::BodyId,
    pub name: Name,
    pub attrs: &'hir [ast::Attribute],
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
    pub whence: Span,
}

pub struct Constant<'hir> {
    pub type_: &'hir P<hir::Ty>,
    pub expr: hir::BodyId,
    pub name: Name,
    pub attrs: &'hir [ast::Attribute],
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
    pub whence: Span,
}

pub struct Trait<'hir> {
    pub is_auto: hir::IsAuto,
    pub unsafety: hir::Unsafety,
    pub name: Name,
    pub items: Vec<&'hir hir::TraitItem>,
    pub generics: &'hir hir::Generics,
    pub bounds: &'hir [hir::GenericBound],
    pub attrs: &'hir [ast::Attribute],
    pub id: hir::HirId,
    pub whence: Span,
    pub vis: &'hir hir::Visibility,
}

pub struct TraitAlias<'hir> {
    pub name: Name,
    pub generics: &'hir hir::Generics,
    pub bounds: &'hir [hir::GenericBound],
    pub attrs: &'hir [ast::Attribute],
    pub id: hir::HirId,
    pub whence: Span,
    pub vis: &'hir hir::Visibility,
}

#[derive(Debug)]
pub struct Impl<'hir> {
    pub unsafety: hir::Unsafety,
    pub polarity: hir::ImplPolarity,
    pub defaultness: hir::Defaultness,
    pub generics: &'hir hir::Generics,
    pub trait_: &'hir Option<hir::TraitRef>,
    pub for_: &'hir P<hir::Ty>,
    pub items: Vec<&'hir hir::ImplItem>,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
}

pub struct ForeignItem<'hir> {
    pub vis: &'hir hir::Visibility,
    pub id: hir::HirId,
    pub name: Name,
    pub kind: &'hir hir::ForeignItemKind,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
}

// For Macro we store the DefId instead of the NodeId, since we also create
// these imported macro_rules (which only have a DUMMY_NODE_ID).
pub struct Macro<'hir> {
    pub name: Name,
    pub hid: hir::HirId,
    pub def_id: hir::def_id::DefId,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
    pub matchers: hir::HirVec<Span>,
    pub imported_from: Option<Name>,
}

pub struct ExternCrate<'hir> {
    pub name: Name,
    pub cnum: CrateNum,
    pub path: Option<String>,
    pub vis: &'hir hir::Visibility,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
}

pub struct Import<'hir> {
    pub name: Name,
    pub id: hir::HirId,
    pub vis: &'hir hir::Visibility,
    pub attrs: &'hir [ast::Attribute],
    pub path: &'hir hir::Path,
    pub glob: bool,
    pub whence: Span,
}

pub struct ProcMacro<'hir> {
    pub name: Name,
    pub id: hir::HirId,
    pub kind: MacroKind,
    pub helpers: Vec<Name>,
    pub attrs: &'hir [ast::Attribute],
    pub whence: Span,
}

pub fn struct_type_from_def(vdata: &hir::VariantData) -> StructType {
    match *vdata {
        hir::VariantData::Struct(..) => Plain,
        hir::VariantData::Tuple(..) => Tuple,
        hir::VariantData::Unit(..) => Unit,
    }
}
<|endoftext|>


<commit_before>extern crate glium;
extern crate image;
extern crate zip;
extern crate cgmath;
extern crate notify;
extern crate lightfield_loader;

use std::io::Read;
use std::fs::File;
use std::io::Cursor;

use lightfield_loader::{Lightfield, LightfieldView};

use glium::backend::Facade;
use glium::texture::{UncompressedUintFormat, MipmapsOption};
use glium::texture::pixel_buffer::PixelBuffer;
use glium::texture::unsigned_texture2d_array::UnsignedTexture2dArray;

use image::{DynamicImage, GenericImage, ImageFormat, Pixel, Rgb};

pub struct LightfieldTexture {
    pub tex: UnsignedTexture2dArray,
}

impl LightfieldTexture {
    #![allow(dead_code)]
    pub fn new<F: Facade>(facade: &F, zip_filename: &str) -> LightfieldTexture {
        let lf = Lightfield::from_zip(zip_filename).unwrap();

        // FIXME n's and sizes
        let nx = 1;
        let ny = 1;
        let n = nx*ny;
        let img0 = &lf.views[0].image;
        let width = img0.width();
        let height = img0.height();
        let buffer_size = (width * height * 3) as usize;

        let tex = UnsignedTexture2dArray::empty_with_format(
            facade,
            UncompressedUintFormat::U8U8U8,
            MipmapsOption::NoMipmap,
            width, height, n).unwrap();

        for view in &lf.views {
            let image= &view.image;
            assert!(image.width() == width);
            assert!(image.height() == height);
            let layer = 0; // iy*nx+ix;
            println!("loading layer {}", layer);
            assert!(layer<n);
            // TODO: due to wrong pixelbuffer format, texture upload uses format = GL_RED_INTEGER
            // how can i write() to a pixelbuffer with T=(u8,u8,u8,u8) from a [u8] src?
            //let buffer = PixelBuffer::<(u8, u8, u8, u8)>::new_empty(facade, buffer_size);
            let buffer = PixelBuffer::<u8>::new_empty(facade, buffer_size);
            buffer.write(&image.raw_pixels());
            tex.main_level().raw_upload_from_pixel_buffer(buffer.as_slice(),
            0..width,
            0..height,
            layer..layer+1);
            break; // XXX debug
        }
        LightfieldTexture {tex: tex}
    }
}
<commit_msg>Make sure we have an image format we can actually handle.<commit_after>extern crate glium;
extern crate image;
extern crate zip;
extern crate cgmath;
extern crate notify;
extern crate lightfield_loader;

use std::io::Read;
use std::fs::File;
use std::io::Cursor;

use lightfield_loader::{Lightfield, LightfieldView};

use glium::backend::Facade;
use glium::texture::{UncompressedUintFormat, MipmapsOption};
use glium::texture::pixel_buffer::PixelBuffer;
use glium::texture::unsigned_texture2d_array::UnsignedTexture2dArray;

use image::{DynamicImage, GenericImage, ImageFormat, Pixel, Rgb};

pub struct LightfieldTexture {
    pub tex: UnsignedTexture2dArray,
}

impl LightfieldTexture {
    #![allow(dead_code)]
    pub fn new<F: Facade>(facade: &F, zip_filename: &str) -> LightfieldTexture {
        let lf = Lightfield::from_zip(zip_filename).unwrap();

        // FIXME n's and sizes
        let nx = 1;
        let ny = 1;
        let n = nx*ny;
        let img0 = &lf.views[0].image;
        let width = img0.width();
        let height = img0.height();
        let buffer_size = (width * height * 3) as usize;

        let tex = UnsignedTexture2dArray::empty_with_format(
            facade,
            UncompressedUintFormat::U8U8U8,
            MipmapsOption::NoMipmap,
            width, height, n).unwrap();

        for view in &lf.views {
            let image= &view.image;
            assert!(image.width() == width);
            assert!(image.height() == height);
            match image {
                &DynamicImage::ImageRgb8(_) => {},
                _ => { panic!("Cannot handle this image type"); },
            }
            let layer = 0; // iy*nx+ix;
            println!("loading layer {}", layer);
            assert!(layer<n);
            // TODO: due to wrong pixelbuffer format, texture upload uses format = GL_RED_INTEGER
            // how can i write() to a pixelbuffer with T=(u8,u8,u8,u8) from a [u8] src?
            //let buffer = PixelBuffer::<(u8, u8, u8, u8)>::new_empty(facade, buffer_size);
            let buffer = PixelBuffer::<u8>::new_empty(facade, buffer_size);
            buffer.write(&image.raw_pixels());
            tex.main_level().raw_upload_from_pixel_buffer(buffer.as_slice(),
            0..width,
            0..height,
            layer..layer+1);
            break; // XXX debug
        }
        LightfieldTexture {tex: tex}
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use chrono::NaiveDateTime;
use diesel::prelude::*;

use crate::util::errors::{cargo_err, AppResult};

use crate::models::{Crate, Dependency, User, VersionOwnerAction};
use crate::schema::*;
use crate::views::{EncodableAuditAction, EncodableVersion, EncodableVersionLinks};

// Queryable has a custom implementation below
#[derive(Clone, Identifiable, Associations, Debug, Queryable, Deserialize, Serialize)]
#[belongs_to(Crate)]
pub struct Version {
    pub id: i32,
    pub crate_id: i32,
    pub num: semver::Version,
    pub updated_at: NaiveDateTime,
    pub created_at: NaiveDateTime,
    pub downloads: i32,
    pub features: serde_json::Value,
    pub yanked: bool,
    pub license: Option<String>,
    pub crate_size: Option<i32>,
    pub published_by: Option<i32>,
}

#[derive(Insertable, Debug)]
#[table_name = "versions"]
pub struct NewVersion {
    crate_id: i32,
    num: String,
    features: serde_json::Value,
    license: Option<String>,
    crate_size: Option<i32>,
    published_by: i32,
}

/// The highest version (semver order) and the most recently updated version.
/// Typically used for a single crate.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct TopVersions {
    pub highest: semver::Version,
    pub newest: semver::Version,
}

impl TopVersions {
    /// Return both the newest (most recently updated) and the
    /// highest version (in semver order) for a list of `Version` instances.
    pub fn from_versions(versions: Vec<Version>) -> Self {
        Self::from_date_version_pairs(versions.into_iter().map(|v| (v.created_at, v.num)))
    }

    /// Return both the newest (most recently updated) and the
    /// highest version (in semver order) for a collection of date/version pairs.
    pub fn from_date_version_pairs<T>(pairs: T) -> Self
    where
        T: Clone + IntoIterator<Item = (NaiveDateTime, semver::Version)>,
    {
        let newest = pairs
            .clone()
            .into_iter()
            .max()
            .unwrap_or((
                NaiveDateTime::from_timestamp(0, 0),
                default_semver_version(),
            ))
            .1;

        let highest = pairs
            .into_iter()
            .map(|(_, v)| v)
            .max()
            .unwrap_or_else(default_semver_version);

        Self { newest, highest }
    }
}

/// A default semver value, "0.0.0", for use in TopVersions
fn default_semver_version() -> semver::Version {
    semver::Version {
        major: 0,
        minor: 0,
        patch: 0,
        pre: vec![],
        build: vec![],
    }
}

impl Version {
    pub fn encodable(
        self,
        crate_name: &str,
        published_by: Option<User>,
        audit_actions: Vec<(VersionOwnerAction, User)>,
    ) -> EncodableVersion {
        let Version {
            id,
            num,
            updated_at,
            created_at,
            downloads,
            features,
            yanked,
            license,
            crate_size,
            ..
        } = self;
        let num = num.to_string();
        EncodableVersion {
            dl_path: format!("/api/v1/crates/{}/{}/download", crate_name, num),
            readme_path: format!("/api/v1/crates/{}/{}/readme", crate_name, num),
            num: num.clone(),
            id,
            krate: crate_name.to_string(),
            updated_at,
            created_at,
            downloads,
            features,
            yanked,
            license,
            links: EncodableVersionLinks {
                dependencies: format!("/api/v1/crates/{}/{}/dependencies", crate_name, num),
                version_downloads: format!("/api/v1/crates/{}/{}/downloads", crate_name, num),
                authors: format!("/api/v1/crates/{}/{}/authors", crate_name, num),
            },
            crate_size,
            published_by: published_by.map(User::into),
            audit_actions: audit_actions
                .into_iter()
                .map(|(audit_action, user)| EncodableAuditAction {
                    action: audit_action.action.into(),
                    user: user.into(),
                    time: audit_action.time,
                })
                .collect(),
        }
    }

    /// Returns (dependency, crate dependency name)
    pub fn dependencies(&self, conn: &PgConnection) -> QueryResult<Vec<(Dependency, String)>> {
        Dependency::belonging_to(self)
            .inner_join(crates::table)
            .select((dependencies::all_columns, crates::name))
            .order((dependencies::optional, crates::name))
            .load(conn)
    }

    pub fn record_readme_rendering(version_id_: i32, conn: &PgConnection) -> QueryResult<usize> {
        use crate::schema::readme_renderings::dsl::*;
        use diesel::dsl::now;

        diesel::insert_into(readme_renderings)
            .values(version_id.eq(version_id_))
            .on_conflict(version_id)
            .do_update()
            .set(rendered_at.eq(now))
            .execute(conn)
    }

    /// Gets the User who ran `cargo publish` for this version, if recorded.
    /// Not for use when you have a group of versions you need the publishers for.
    pub fn published_by(&self, conn: &PgConnection) -> Option<User> {
        match self.published_by {
            Some(pb) => users::table.find(pb).first(conn).ok(),
            None => None,
        }
    }
}

impl NewVersion {
    pub fn new(
        crate_id: i32,
        num: &semver::Version,
        features: &HashMap<String, Vec<String>>,
        license: Option<String>,
        license_file: Option<&str>,
        crate_size: i32,
        published_by: i32,
    ) -> AppResult<Self> {
        let features = serde_json::to_value(features)?;

        let mut new_version = NewVersion {
            crate_id,
            num: num.to_string(),
            features,
            license,
            crate_size: Some(crate_size),
            published_by,
        };

        new_version.validate_license(license_file)?;

        Ok(new_version)
    }

    pub fn save(
        &self,
        conn: &PgConnection,
        authors: &[String],
        published_by_email: &str,
    ) -> AppResult<Version> {
        use crate::schema::version_authors::{name, version_id};
        use crate::schema::versions::dsl::*;
        use diesel::dsl::exists;
        use diesel::{insert_into, select};

        conn.transaction(|| {
            let already_uploaded = versions
                .filter(crate_id.eq(self.crate_id))
                .filter(num.eq(&self.num));
            if select(exists(already_uploaded)).get_result(conn)? {
                return Err(cargo_err(&format_args!(
                    "crate version `{}` is already \
                     uploaded",
                    self.num
                )));
            }

            let version: Version = insert_into(versions).values(self).get_result(conn)?;

            insert_into(versions_published_by::table)
                .values((
                    versions_published_by::version_id.eq(version.id),
                    versions_published_by::email.eq(published_by_email),
                ))
                .execute(conn)?;

            let new_authors = authors
                .iter()
                .map(|s| (version_id.eq(version.id), name.eq(s)))
                .collect::<Vec<_>>();

            insert_into(version_authors::table)
                .values(&new_authors)
                .execute(conn)?;
            Ok(version)
        })
    }

    fn validate_license(&mut self, license_file: Option<&str>) -> AppResult<()> {
        if let Some(ref license) = self.license {
            for part in license.split('/') {
                license_exprs::validate_license_expr(part).map_err(|e| {
                    cargo_err(&format_args!(
                        "{}; see http://opensource.org/licenses \
                         for options, and http://spdx.org/licenses/ \
                         for their identifiers",
                        e
                    ))
                })?;
            }
        } else if license_file.is_some() {
            // If no license is given, but a license file is given, flag this
            // crate as having a nonstandard license. Note that we don't
            // actually do anything else with license_file currently.
            self.license = Some(String::from("non-standard"));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::TopVersions;
    use chrono::NaiveDateTime;

    #[track_caller]
    fn date(str: &str) -> NaiveDateTime {
        str.parse().unwrap()
    }

    #[track_caller]
    fn version(str: &str) -> semver::Version {
        semver::Version::parse(str).unwrap()
    }

    #[test]
    fn top_versions_empty() {
        let versions = vec![];
        assert_eq!(
            TopVersions::from_date_version_pairs(versions),
            TopVersions {
                highest: version("0.0.0"),
                newest: version("0.0.0"),
            }
        );
    }

    #[test]
    fn top_versions_single() {
        let versions = vec![(date("2020-12-03T12:34:56"), version("1.0.0"))];
        assert_eq!(
            TopVersions::from_date_version_pairs(versions),
            TopVersions {
                highest: version("1.0.0"),
                newest: version("1.0.0"),
            }
        );
    }

    #[test]
    fn top_versions_multiple() {
        let versions = vec![
            (date("2018-12-03T12:34:56"), version("1.0.0")),
            (date("2019-12-03T12:34:56"), version("2.0.0-alpha.1")),
            (date("2020-12-03T12:34:56"), version("1.1.0")),
        ];
        assert_eq!(
            TopVersions::from_date_version_pairs(versions),
            TopVersions {
                highest: version("2.0.0-alpha.1"),
                newest: version("1.1.0"),
            }
        );
    }
}
<commit_msg>models/version: Add doc comments to `TopVersions` fields<commit_after>use std::collections::HashMap;

use chrono::NaiveDateTime;
use diesel::prelude::*;

use crate::util::errors::{cargo_err, AppResult};

use crate::models::{Crate, Dependency, User, VersionOwnerAction};
use crate::schema::*;
use crate::views::{EncodableAuditAction, EncodableVersion, EncodableVersionLinks};

// Queryable has a custom implementation below
#[derive(Clone, Identifiable, Associations, Debug, Queryable, Deserialize, Serialize)]
#[belongs_to(Crate)]
pub struct Version {
    pub id: i32,
    pub crate_id: i32,
    pub num: semver::Version,
    pub updated_at: NaiveDateTime,
    pub created_at: NaiveDateTime,
    pub downloads: i32,
    pub features: serde_json::Value,
    pub yanked: bool,
    pub license: Option<String>,
    pub crate_size: Option<i32>,
    pub published_by: Option<i32>,
}

#[derive(Insertable, Debug)]
#[table_name = "versions"]
pub struct NewVersion {
    crate_id: i32,
    num: String,
    features: serde_json::Value,
    license: Option<String>,
    crate_size: Option<i32>,
    published_by: i32,
}

/// The highest version (semver order) and the most recently updated version.
/// Typically used for a single crate.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct TopVersions {
    /// The "highest" version in terms of semver
    pub highest: semver::Version,
    /// The "newest" version in terms of publishing date
    pub newest: semver::Version,
}

impl TopVersions {
    /// Return both the newest (most recently updated) and the
    /// highest version (in semver order) for a list of `Version` instances.
    pub fn from_versions(versions: Vec<Version>) -> Self {
        Self::from_date_version_pairs(versions.into_iter().map(|v| (v.created_at, v.num)))
    }

    /// Return both the newest (most recently updated) and the
    /// highest version (in semver order) for a collection of date/version pairs.
    pub fn from_date_version_pairs<T>(pairs: T) -> Self
    where
        T: Clone + IntoIterator<Item = (NaiveDateTime, semver::Version)>,
    {
        let newest = pairs
            .clone()
            .into_iter()
            .max()
            .unwrap_or((
                NaiveDateTime::from_timestamp(0, 0),
                default_semver_version(),
            ))
            .1;

        let highest = pairs
            .into_iter()
            .map(|(_, v)| v)
            .max()
            .unwrap_or_else(default_semver_version);

        Self { newest, highest }
    }
}

/// A default semver value, "0.0.0", for use in TopVersions
fn default_semver_version() -> semver::Version {
    semver::Version {
        major: 0,
        minor: 0,
        patch: 0,
        pre: vec![],
        build: vec![],
    }
}

impl Version {
    pub fn encodable(
        self,
        crate_name: &str,
        published_by: Option<User>,
        audit_actions: Vec<(VersionOwnerAction, User)>,
    ) -> EncodableVersion {
        let Version {
            id,
            num,
            updated_at,
            created_at,
            downloads,
            features,
            yanked,
            license,
            crate_size,
            ..
        } = self;
        let num = num.to_string();
        EncodableVersion {
            dl_path: format!("/api/v1/crates/{}/{}/download", crate_name, num),
            readme_path: format!("/api/v1/crates/{}/{}/readme", crate_name, num),
            num: num.clone(),
            id,
            krate: crate_name.to_string(),
            updated_at,
            created_at,
            downloads,
            features,
            yanked,
            license,
            links: EncodableVersionLinks {
                dependencies: format!("/api/v1/crates/{}/{}/dependencies", crate_name, num),
                version_downloads: format!("/api/v1/crates/{}/{}/downloads", crate_name, num),
                authors: format!("/api/v1/crates/{}/{}/authors", crate_name, num),
            },
            crate_size,
            published_by: published_by.map(User::into),
            audit_actions: audit_actions
                .into_iter()
                .map(|(audit_action, user)| EncodableAuditAction {
                    action: audit_action.action.into(),
                    user: user.into(),
                    time: audit_action.time,
                })
                .collect(),
        }
    }

    /// Returns (dependency, crate dependency name)
    pub fn dependencies(&self, conn: &PgConnection) -> QueryResult<Vec<(Dependency, String)>> {
        Dependency::belonging_to(self)
            .inner_join(crates::table)
            .select((dependencies::all_columns, crates::name))
            .order((dependencies::optional, crates::name))
            .load(conn)
    }

    pub fn record_readme_rendering(version_id_: i32, conn: &PgConnection) -> QueryResult<usize> {
        use crate::schema::readme_renderings::dsl::*;
        use diesel::dsl::now;

        diesel::insert_into(readme_renderings)
            .values(version_id.eq(version_id_))
            .on_conflict(version_id)
            .do_update()
            .set(rendered_at.eq(now))
            .execute(conn)
    }

    /// Gets the User who ran `cargo publish` for this version, if recorded.
    /// Not for use when you have a group of versions you need the publishers for.
    pub fn published_by(&self, conn: &PgConnection) -> Option<User> {
        match self.published_by {
            Some(pb) => users::table.find(pb).first(conn).ok(),
            None => None,
        }
    }
}

impl NewVersion {
    pub fn new(
        crate_id: i32,
        num: &semver::Version,
        features: &HashMap<String, Vec<String>>,
        license: Option<String>,
        license_file: Option<&str>,
        crate_size: i32,
        published_by: i32,
    ) -> AppResult<Self> {
        let features = serde_json::to_value(features)?;

        let mut new_version = NewVersion {
            crate_id,
            num: num.to_string(),
            features,
            license,
            crate_size: Some(crate_size),
            published_by,
        };

        new_version.validate_license(license_file)?;

        Ok(new_version)
    }

    pub fn save(
        &self,
        conn: &PgConnection,
        authors: &[String],
        published_by_email: &str,
    ) -> AppResult<Version> {
        use crate::schema::version_authors::{name, version_id};
        use crate::schema::versions::dsl::*;
        use diesel::dsl::exists;
        use diesel::{insert_into, select};

        conn.transaction(|| {
            let already_uploaded = versions
                .filter(crate_id.eq(self.crate_id))
                .filter(num.eq(&self.num));
            if select(exists(already_uploaded)).get_result(conn)? {
                return Err(cargo_err(&format_args!(
                    "crate version `{}` is already \
                     uploaded",
                    self.num
                )));
            }

            let version: Version = insert_into(versions).values(self).get_result(conn)?;

            insert_into(versions_published_by::table)
                .values((
                    versions_published_by::version_id.eq(version.id),
                    versions_published_by::email.eq(published_by_email),
                ))
                .execute(conn)?;

            let new_authors = authors
                .iter()
                .map(|s| (version_id.eq(version.id), name.eq(s)))
                .collect::<Vec<_>>();

            insert_into(version_authors::table)
                .values(&new_authors)
                .execute(conn)?;
            Ok(version)
        })
    }

    fn validate_license(&mut self, license_file: Option<&str>) -> AppResult<()> {
        if let Some(ref license) = self.license {
            for part in license.split('/') {
                license_exprs::validate_license_expr(part).map_err(|e| {
                    cargo_err(&format_args!(
                        "{}; see http://opensource.org/licenses \
                         for options, and http://spdx.org/licenses/ \
                         for their identifiers",
                        e
                    ))
                })?;
            }
        } else if license_file.is_some() {
            // If no license is given, but a license file is given, flag this
            // crate as having a nonstandard license. Note that we don't
            // actually do anything else with license_file currently.
            self.license = Some(String::from("non-standard"));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::TopVersions;
    use chrono::NaiveDateTime;

    #[track_caller]
    fn date(str: &str) -> NaiveDateTime {
        str.parse().unwrap()
    }

    #[track_caller]
    fn version(str: &str) -> semver::Version {
        semver::Version::parse(str).unwrap()
    }

    #[test]
    fn top_versions_empty() {
        let versions = vec![];
        assert_eq!(
            TopVersions::from_date_version_pairs(versions),
            TopVersions {
                highest: version("0.0.0"),
                newest: version("0.0.0"),
            }
        );
    }

    #[test]
    fn top_versions_single() {
        let versions = vec![(date("2020-12-03T12:34:56"), version("1.0.0"))];
        assert_eq!(
            TopVersions::from_date_version_pairs(versions),
            TopVersions {
                highest: version("1.0.0"),
                newest: version("1.0.0"),
            }
        );
    }

    #[test]
    fn top_versions_multiple() {
        let versions = vec![
            (date("2018-12-03T12:34:56"), version("1.0.0")),
            (date("2019-12-03T12:34:56"), version("2.0.0-alpha.1")),
            (date("2020-12-03T12:34:56"), version("1.1.0")),
        ];
        assert_eq!(
            TopVersions::from_date_version_pairs(versions),
            TopVersions {
                highest: version("2.0.0-alpha.1"),
                newest: version("1.1.0"),
            }
        );
    }
}
<|endoftext|>


<commit_before>use std::{io, path, ptr, mem, ffi, slice, time};
use libc::{c_void, c_int, c_schar, c_uchar, size_t, uid_t, sysctl, sysctlnametomib, timeval, statfs};
use data::*;
use super::common::*;
use super::unix;

pub struct PlatformImpl;

macro_rules! sysctl_mib {
    ($len:expr, $name:expr) => {
        {
            let mut mib: [c_int; $len] = [0; $len];
            let mut sz: size_t = mib.len();
            let s = ffi::CString::new($name).unwrap();
            unsafe { sysctlnametomib(s.as_ptr(), &mut mib[0], &mut sz) };
            mib
        }
    }
}

macro_rules! sysctl {
    ($mib:expr, $dataptr:expr, $size:expr, $shouldcheck:expr) => {
        {
            let mib = &$mib;
            let mut size = $size;
            if unsafe { sysctl(&mib[0] as *const _ as *mut _, mib.len() as u32,
                               $dataptr as *mut _ as *mut c_void, &mut size, ptr::null_mut(), 0) } != 0 && $shouldcheck {
                return Err(io::Error::new(io::ErrorKind::Other, "sysctl() failed"))
            }
            size
        }
    };
    ($mib:expr, $dataptr:expr, $size:expr) => {
        sysctl!($mib, $dataptr, $size, true)
    }
}

lazy_static! {
    static ref KERN_BOOTTIME: [c_int; 2] = sysctl_mib!(2, "kern.boottime");
}

/// An implementation of `Platform` for macOS.
/// See `Platform` for documentation.
impl Platform for PlatformImpl {
    #[inline(always)]
    fn new() -> Self {
        PlatformImpl
    }

    fn cpu_load(&self) -> io::Result<DelayedMeasurement<Vec<CPULoad>>> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn load_average(&self) -> io::Result<LoadAverage> {
        unix::load_average()
    }

    fn memory(&self) -> io::Result<Memory> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn boot_time(&self) -> io::Result<DateTime<Utc>> {
        let mut data: timeval = unsafe { mem::zeroed() };
        sysctl!(KERN_BOOTTIME, &mut data, mem::size_of::<timeval>());
        Ok(DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(data.tv_sec.into(), data.tv_usec as u32), Utc))
    }

    fn battery_life(&self) -> io::Result<BatteryLife> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn on_ac_power(&self) -> io::Result<bool> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn mounts(&self) -> io::Result<Vec<Filesystem>> {
        let mut mptr: *mut statfs = ptr::null_mut();
        let len = unsafe { getmntinfo(&mut mptr, 2 as i32) };
        if len < 1 {
            return Err(io::Error::new(io::ErrorKind::Other, "getmntinfo() failed"))
        }
        let mounts = unsafe { slice::from_raw_parts(mptr, len as usize) };
        Ok(mounts.iter().map(statfs_to_fs).collect::<Vec<_>>())
    }

    fn block_device_statistics(&self) -> io::Result<BTreeMap<String, BlockDeviceStats>> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn networks(&self) -> io::Result<BTreeMap<String, Network>> {
        unix::networks()
    }

    fn network_stats(&self, interface: &str) -> io::Result<NetworkStats> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn cpu_temp(&self) -> io::Result<f32> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn socket_stats(&self) -> io::Result<SocketStats> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }
}

fn statfs_to_fs(x: &statfs) -> Filesystem {
    Filesystem {
        files: (x.f_files as usize.saturating_sub(x.f_ffree as usize),
        files_total: x.f_files as usize,
        files_avail: x.f_ffree as usize,
        free: ByteSize::b(x.f_bfree * x.f_bsize as u64),
        avail: ByteSize::b(x.f_bavail * x.f_bsize as u64),
        total: ByteSize::b(x.f_blocks * x.f_bsize as u64),
        name_max: 256,
        fs_type: unsafe { ffi::CStr::from_ptr(&x.f_fstypename[0]).to_string_lossy().into_owned() },
        fs_mounted_from: unsafe { ffi::CStr::from_ptr(&x.f_mntfromname[0]).to_string_lossy().into_owned() },
        fs_mounted_on: unsafe { ffi::CStr::from_ptr(&x.f_mntonname[0]).to_string_lossy().into_owned() },
    }
}

#[link(name = "c")]
extern "C" {
    #[link_name = "getmntinfo$INODE64"]
    fn getmntinfo(mntbufp: *mut *mut statfs, flags: c_int) -> c_int;
}
<commit_msg>macos: fix syntax error<commit_after>use std::{io, path, ptr, mem, ffi, slice, time};
use libc::{c_void, c_int, c_schar, c_uchar, size_t, uid_t, sysctl, sysctlnametomib, timeval, statfs};
use data::*;
use super::common::*;
use super::unix;

pub struct PlatformImpl;

macro_rules! sysctl_mib {
    ($len:expr, $name:expr) => {
        {
            let mut mib: [c_int; $len] = [0; $len];
            let mut sz: size_t = mib.len();
            let s = ffi::CString::new($name).unwrap();
            unsafe { sysctlnametomib(s.as_ptr(), &mut mib[0], &mut sz) };
            mib
        }
    }
}

macro_rules! sysctl {
    ($mib:expr, $dataptr:expr, $size:expr, $shouldcheck:expr) => {
        {
            let mib = &$mib;
            let mut size = $size;
            if unsafe { sysctl(&mib[0] as *const _ as *mut _, mib.len() as u32,
                               $dataptr as *mut _ as *mut c_void, &mut size, ptr::null_mut(), 0) } != 0 && $shouldcheck {
                return Err(io::Error::new(io::ErrorKind::Other, "sysctl() failed"))
            }
            size
        }
    };
    ($mib:expr, $dataptr:expr, $size:expr) => {
        sysctl!($mib, $dataptr, $size, true)
    }
}

lazy_static! {
    static ref KERN_BOOTTIME: [c_int; 2] = sysctl_mib!(2, "kern.boottime");
}

/// An implementation of `Platform` for macOS.
/// See `Platform` for documentation.
impl Platform for PlatformImpl {
    #[inline(always)]
    fn new() -> Self {
        PlatformImpl
    }

    fn cpu_load(&self) -> io::Result<DelayedMeasurement<Vec<CPULoad>>> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn load_average(&self) -> io::Result<LoadAverage> {
        unix::load_average()
    }

    fn memory(&self) -> io::Result<Memory> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn boot_time(&self) -> io::Result<DateTime<Utc>> {
        let mut data: timeval = unsafe { mem::zeroed() };
        sysctl!(KERN_BOOTTIME, &mut data, mem::size_of::<timeval>());
        Ok(DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(data.tv_sec.into(), data.tv_usec as u32), Utc))
    }

    fn battery_life(&self) -> io::Result<BatteryLife> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn on_ac_power(&self) -> io::Result<bool> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn mounts(&self) -> io::Result<Vec<Filesystem>> {
        let mut mptr: *mut statfs = ptr::null_mut();
        let len = unsafe { getmntinfo(&mut mptr, 2 as i32) };
        if len < 1 {
            return Err(io::Error::new(io::ErrorKind::Other, "getmntinfo() failed"))
        }
        let mounts = unsafe { slice::from_raw_parts(mptr, len as usize) };
        Ok(mounts.iter().map(statfs_to_fs).collect::<Vec<_>>())
    }

    fn block_device_statistics(&self) -> io::Result<BTreeMap<String, BlockDeviceStats>> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn networks(&self) -> io::Result<BTreeMap<String, Network>> {
        unix::networks()
    }

    fn network_stats(&self, interface: &str) -> io::Result<NetworkStats> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn cpu_temp(&self) -> io::Result<f32> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }

    fn socket_stats(&self) -> io::Result<SocketStats> {
        Err(io::Error::new(io::ErrorKind::Other, "Not supported"))
    }
}

fn statfs_to_fs(x: &statfs) -> Filesystem {
    Filesystem {
        files: (x.f_files as usize).saturating_sub(x.f_ffree as usize),
        files_total: x.f_files as usize,
        files_avail: x.f_ffree as usize,
        free: ByteSize::b(x.f_bfree * x.f_bsize as u64),
        avail: ByteSize::b(x.f_bavail * x.f_bsize as u64),
        total: ByteSize::b(x.f_blocks * x.f_bsize as u64),
        name_max: 256,
        fs_type: unsafe { ffi::CStr::from_ptr(&x.f_fstypename[0]).to_string_lossy().into_owned() },
        fs_mounted_from: unsafe { ffi::CStr::from_ptr(&x.f_mntfromname[0]).to_string_lossy().into_owned() },
        fs_mounted_on: unsafe { ffi::CStr::from_ptr(&x.f_mntonname[0]).to_string_lossy().into_owned() },
    }
}

#[link(name = "c")]
extern "C" {
    #[link_name = "getmntinfo$INODE64"]
    fn getmntinfo(mntbufp: *mut *mut statfs, flags: c_int) -> c_int;
}
<|endoftext|>


<commit_before>use iron::Request;
use std::path::{PathBuf, Path};
use std::fs::{self, Metadata};
use std::convert::AsRef;
use url::percent_encoding::percent_decode;

pub struct RequestedPath {
    pub path: PathBuf,
}

#[inline]
fn decode_percents(string: &&str) -> String {
    percent_decode(string.as_bytes()).decode_utf8().unwrap().into_owned()
}

impl RequestedPath {
    pub fn new<P: AsRef<Path>>(root_path: P, request: &Request) -> RequestedPath {
        let mut result = root_path.as_ref().to_path_buf();
        let path = request.url.path();
        let decoded_req_path = path.iter().map(decode_percents);
        result.extend(decoded_req_path);

        RequestedPath { path: result }
    }

    pub fn should_redirect(&self, metadata: &Metadata, request: &Request) -> bool {
        // As per servo/rust-url/serialize_path, URLs ending in a slash have an
        // empty string stored as the last component of their path. Rust-url
        // even ensures that url.path() is non-empty by appending a forward slash
        // to URLs like http://example.com
        // Some middleware may mutate the URL's path to violate this property,
        // so the empty list case is handled as a redirect.
        let has_trailing_slash = match request.url.path().last() {
            Some(&"") => true,
            _ => false,
        };

        metadata.is_dir() && !has_trailing_slash
    }

    pub fn get_file(self, metadata: &Metadata) -> Option<PathBuf> {
        if metadata.is_file() {
            return Some(self.path);
        }

        let index_path = self.path.join("index.html");

        match fs::metadata(&index_path) {
            Ok(m) =>
                if m.is_file() {
                    Some(index_path)
                } else {
                    None
                },
            Err(_) => None,
        }
    }
}
<commit_msg>(fix) Avoid extension with empty strings<commit_after>use iron::Request;
use std::path::{PathBuf, Path};
use std::fs::{self, Metadata};
use std::convert::AsRef;
use url::percent_encoding::percent_decode;

pub struct RequestedPath {
    pub path: PathBuf,
}

#[inline]
fn decode_percents(string: &&str) -> String {
    percent_decode(string.as_bytes()).decode_utf8().unwrap().into_owned()
}

impl RequestedPath {
    pub fn new<P: AsRef<Path>>(root_path: P, request: &Request) -> RequestedPath {
        let mut result = root_path.as_ref().to_path_buf();
        let path = request.url.path();
        let decoded_req_path = path.iter()
          .map(decode_percents)
          .filter(|x| x.len() != 0);
        result.extend(decoded_req_path);

        RequestedPath { path: result }
    }

    pub fn should_redirect(&self, metadata: &Metadata, request: &Request) -> bool {
        // As per servo/rust-url/serialize_path, URLs ending in a slash have an
        // empty string stored as the last component of their path. Rust-url
        // even ensures that url.path() is non-empty by appending a forward slash
        // to URLs like http://example.com
        // Some middleware may mutate the URL's path to violate this property,
        // so the empty list case is handled as a redirect.
        let has_trailing_slash = match request.url.path().last() {
            Some(&"") => true,
            _ => false,
        };

        metadata.is_dir() && !has_trailing_slash
    }

    pub fn get_file(self, metadata: &Metadata) -> Option<PathBuf> {
        if metadata.is_file() {
            return Some(self.path);
        }

        let index_path = self.path.join("index.html");

        match fs::metadata(&index_path) {
            Ok(m) =>
                if m.is_file() {
                    Some(index_path)
                } else {
                    None
                },
            Err(_) => None,
        }
    }
}
<|endoftext|>


<commit_before>use std::{
    cell::RefCell,
    rc::Rc,
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc, Mutex,
    },
};

use smithay::{
    reexports::{
        calloop::{generic::Generic, Interest, LoopHandle, Mode, PostAction},
        wayland_server::{protocol::wl_surface::WlSurface, Display},
    },
    utils::{Logical, Point},
    wayland::{
        data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
        output::xdg::init_xdg_output_manager,
        seat::{CursorImageStatus, KeyboardHandle, PointerHandle, Seat, XkbConfig},
        shm::init_shm_global,
        tablet_manager::{init_tablet_manager_global, TabletSeatTrait},
        xdg_activation::{init_xdg_activation_global, XdgActivationEvent},
    },
};

#[cfg(feature = "xwayland")]
use smithay::xwayland::{XWayland, XWaylandEvent};

use crate::{output_map::OutputMap, shell::init_shell, window_map::WindowMap};

#[derive(Debug)]
pub struct AnvilState<BackendData> {
    pub backend_data: BackendData,
    pub socket_name: Option<String>,
    pub running: Arc<AtomicBool>,
    pub display: Rc<RefCell<Display>>,
    pub handle: LoopHandle<'static, AnvilState<BackendData>>,
    pub window_map: Rc<RefCell<crate::window_map::WindowMap>>,
    pub output_map: Rc<RefCell<crate::output_map::OutputMap>>,
    pub dnd_icon: Arc<Mutex<Option<WlSurface>>>,
    pub log: slog::Logger,
    // input-related fields
    pub pointer: PointerHandle,
    pub keyboard: KeyboardHandle,
    pub suppressed_keys: Vec<u32>,
    pub pointer_location: Point<f64, Logical>,
    pub cursor_status: Arc<Mutex<CursorImageStatus>>,
    pub seat_name: String,
    pub seat: Seat,
    pub start_time: std::time::Instant,
    // things we must keep alive
    #[cfg(feature = "xwayland")]
    pub xwayland: XWayland<AnvilState<BackendData>>,
}

impl<BackendData: Backend + 'static> AnvilState<BackendData> {
    pub fn init(
        display: Rc<RefCell<Display>>,
        handle: LoopHandle<'static, AnvilState<BackendData>>,
        backend_data: BackendData,
        log: slog::Logger,
        listen_on_socket: bool,
    ) -> AnvilState<BackendData> {
        // init the wayland connection
        handle
            .insert_source(
                Generic::from_fd(display.borrow().get_poll_fd(), Interest::READ, Mode::Level),
                move |_, _, state: &mut AnvilState<BackendData>| {
                    let display = state.display.clone();
                    let mut display = display.borrow_mut();
                    match display.dispatch(std::time::Duration::from_millis(0), state) {
                        Ok(_) => Ok(PostAction::Continue),
                        Err(e) => {
                            error!(state.log, "I/O error on the Wayland display: {}", e);
                            state.running.store(false, Ordering::SeqCst);
                            Err(e)
                        }
                    }
                },
            )
            .expect("Failed to init the wayland event source.");

        // Init a window map, to track the location of our windows
        let window_map = Rc::new(RefCell::new(WindowMap::default()));
        let output_map = Rc::new(RefCell::new(OutputMap::new(
            display.clone(),
            window_map.clone(),
            log.clone(),
        )));

        // Init the basic compositor globals

        init_shm_global(&mut (*display).borrow_mut(), vec![], log.clone());

        // Init the shell states
        init_shell::<BackendData>(display.clone(), log.clone());

        init_xdg_output_manager(&mut display.borrow_mut(), log.clone());
        init_xdg_activation_global(
            &mut display.borrow_mut(),
            |state, req, mut ddata| {
                let anvil_state = ddata.get::<AnvilState<BackendData>>().unwrap();
                match req {
                    XdgActivationEvent::RequestActivation {
                        token,
                        token_data,
                        surface,
                    } => {
                        if token_data.timestamp.elapsed().as_secs() < 10 {
                            // Just grant the wish
                            anvil_state.window_map.borrow_mut().bring_surface_to_top(&surface);
                        } else {
                            // Discard the request
                            state.lock().unwrap().remove_request(&token);
                        }
                    }
                    XdgActivationEvent::DestroyActivationRequest { .. } => {}
                }
            },
            log.clone(),
        );

        let socket_name = if listen_on_socket {
            let socket_name = display
                .borrow_mut()
                .add_socket_auto()
                .unwrap()
                .into_string()
                .unwrap();
            info!(log, "Listening on wayland socket"; "name" => socket_name.clone());
            ::std::env::set_var("WAYLAND_DISPLAY", &socket_name);
            Some(socket_name)
        } else {
            None
        };

        // init data device

        let dnd_icon = Arc::new(Mutex::new(None));

        let dnd_icon2 = dnd_icon.clone();
        init_data_device(
            &mut display.borrow_mut(),
            move |event| match event {
                DataDeviceEvent::DnDStarted { icon, .. } => {
                    *dnd_icon2.lock().unwrap() = icon;
                }
                DataDeviceEvent::DnDDropped => {
                    *dnd_icon2.lock().unwrap() = None;
                }
                _ => {}
            },
            default_action_chooser,
            log.clone(),
        );

        // init input
        let seat_name = backend_data.seat_name();

        let (mut seat, _) = Seat::new(&mut display.borrow_mut(), seat_name.clone(), log.clone());

        let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));

        let cursor_status2 = cursor_status.clone();
        let pointer = seat.add_pointer(move |new_status| {
            // TODO: hide winit system cursor when relevant
            *cursor_status2.lock().unwrap() = new_status
        });

        init_tablet_manager_global(&mut display.borrow_mut());

        let cursor_status3 = cursor_status.clone();
        seat.tablet_seat().on_cursor_surface(move |_tool, new_status| {
            // TODO: tablet tools should have their own cursors
            *cursor_status3.lock().unwrap() = new_status;
        });

        let keyboard = seat
            .add_keyboard(XkbConfig::default(), 200, 25, |seat, focus| {
                set_data_device_focus(seat, focus.and_then(|s| s.as_ref().client()))
            })
            .expect("Failed to initialize the keyboard");

        #[cfg(feature = "xwayland")]
        let xwayland = {
            let (xwayland, channel) = XWayland::new(handle.clone(), display.clone(), log.clone());
            let ret = handle.insert_source(channel, |event, _, anvil_state| match event {
                XWaylandEvent::Ready { connection, client } => anvil_state.xwayland_ready(connection, client),
                XWaylandEvent::Exited => anvil_state.xwayland_exited(),
            });
            if let Err(e) = ret {
                error!(
                    log,
                    "Failed to insert the XWaylandSource into the event loop: {}", e
                );
            }
            xwayland
        };

        AnvilState {
            backend_data,
            running: Arc::new(AtomicBool::new(true)),
            display,
            handle,
            window_map,
            output_map,
            dnd_icon,
            log,
            socket_name,
            pointer,
            keyboard,
            suppressed_keys: Vec::new(),
            cursor_status,
            pointer_location: (0.0, 0.0).into(),
            seat_name,
            seat,
            start_time: std::time::Instant::now(),
            #[cfg(feature = "xwayland")]
            xwayland,
        }
    }
}

pub trait Backend {
    fn seat_name(&self) -> String;
}
<commit_msg>Anvil XDG Decoration<commit_after>use std::{
    cell::RefCell,
    rc::Rc,
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc, Mutex,
    },
};

use smithay::{
    reexports::{
        calloop::{generic::Generic, Interest, LoopHandle, Mode, PostAction},
        wayland_protocols::unstable::xdg_decoration,
        wayland_server::{protocol::wl_surface::WlSurface, Display},
    },
    utils::{Logical, Point},
    wayland::{
        data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
        output::xdg::init_xdg_output_manager,
        seat::{CursorImageStatus, KeyboardHandle, PointerHandle, Seat, XkbConfig},
        shell::xdg::decoration::{init_xdg_decoration_manager, XdgDecorationRequest},
        shm::init_shm_global,
        tablet_manager::{init_tablet_manager_global, TabletSeatTrait},
        xdg_activation::{init_xdg_activation_global, XdgActivationEvent},
    },
};

#[cfg(feature = "xwayland")]
use smithay::xwayland::{XWayland, XWaylandEvent};

use crate::{output_map::OutputMap, shell::init_shell, window_map::WindowMap};

#[derive(Debug)]
pub struct AnvilState<BackendData> {
    pub backend_data: BackendData,
    pub socket_name: Option<String>,
    pub running: Arc<AtomicBool>,
    pub display: Rc<RefCell<Display>>,
    pub handle: LoopHandle<'static, AnvilState<BackendData>>,
    pub window_map: Rc<RefCell<crate::window_map::WindowMap>>,
    pub output_map: Rc<RefCell<crate::output_map::OutputMap>>,
    pub dnd_icon: Arc<Mutex<Option<WlSurface>>>,
    pub log: slog::Logger,
    // input-related fields
    pub pointer: PointerHandle,
    pub keyboard: KeyboardHandle,
    pub suppressed_keys: Vec<u32>,
    pub pointer_location: Point<f64, Logical>,
    pub cursor_status: Arc<Mutex<CursorImageStatus>>,
    pub seat_name: String,
    pub seat: Seat,
    pub start_time: std::time::Instant,
    // things we must keep alive
    #[cfg(feature = "xwayland")]
    pub xwayland: XWayland<AnvilState<BackendData>>,
}

impl<BackendData: Backend + 'static> AnvilState<BackendData> {
    pub fn init(
        display: Rc<RefCell<Display>>,
        handle: LoopHandle<'static, AnvilState<BackendData>>,
        backend_data: BackendData,
        log: slog::Logger,
        listen_on_socket: bool,
    ) -> AnvilState<BackendData> {
        // init the wayland connection
        handle
            .insert_source(
                Generic::from_fd(display.borrow().get_poll_fd(), Interest::READ, Mode::Level),
                move |_, _, state: &mut AnvilState<BackendData>| {
                    let display = state.display.clone();
                    let mut display = display.borrow_mut();
                    match display.dispatch(std::time::Duration::from_millis(0), state) {
                        Ok(_) => Ok(PostAction::Continue),
                        Err(e) => {
                            error!(state.log, "I/O error on the Wayland display: {}", e);
                            state.running.store(false, Ordering::SeqCst);
                            Err(e)
                        }
                    }
                },
            )
            .expect("Failed to init the wayland event source.");

        // Init a window map, to track the location of our windows
        let window_map = Rc::new(RefCell::new(WindowMap::default()));
        let output_map = Rc::new(RefCell::new(OutputMap::new(
            display.clone(),
            window_map.clone(),
            log.clone(),
        )));

        // Init the basic compositor globals

        init_shm_global(&mut (*display).borrow_mut(), vec![], log.clone());

        // Init the shell states
        init_shell::<BackendData>(display.clone(), log.clone());

        init_xdg_output_manager(&mut display.borrow_mut(), log.clone());
        init_xdg_activation_global(
            &mut display.borrow_mut(),
            |state, req, mut ddata| {
                let anvil_state = ddata.get::<AnvilState<BackendData>>().unwrap();
                match req {
                    XdgActivationEvent::RequestActivation {
                        token,
                        token_data,
                        surface,
                    } => {
                        if token_data.timestamp.elapsed().as_secs() < 10 {
                            // Just grant the wish
                            anvil_state.window_map.borrow_mut().bring_surface_to_top(&surface);
                        } else {
                            // Discard the request
                            state.lock().unwrap().remove_request(&token);
                        }
                    }
                    XdgActivationEvent::DestroyActivationRequest { .. } => {}
                }
            },
            log.clone(),
        );

        init_xdg_decoration_manager(
            &mut display.borrow_mut(),
            |req, _ddata| match req {
                XdgDecorationRequest::NewToplevelDecoration { toplevel } => {
                    use xdg_decoration::v1::server::zxdg_toplevel_decoration_v1::Mode;

                    let res = toplevel.with_pending_state(|state| {
                        state.decoration_mode = Some(Mode::ClientSide);
                    });

                    if res.is_ok() {
                        toplevel.send_configure();
                    }
                }
                XdgDecorationRequest::SetMode { .. } => {}
                XdgDecorationRequest::UnsetMode { .. } => {}
            },
            log.clone(),
        );

        let socket_name = if listen_on_socket {
            let socket_name = display
                .borrow_mut()
                .add_socket_auto()
                .unwrap()
                .into_string()
                .unwrap();
            info!(log, "Listening on wayland socket"; "name" => socket_name.clone());
            ::std::env::set_var("WAYLAND_DISPLAY", &socket_name);
            Some(socket_name)
        } else {
            None
        };

        // init data device

        let dnd_icon = Arc::new(Mutex::new(None));

        let dnd_icon2 = dnd_icon.clone();
        init_data_device(
            &mut display.borrow_mut(),
            move |event| match event {
                DataDeviceEvent::DnDStarted { icon, .. } => {
                    *dnd_icon2.lock().unwrap() = icon;
                }
                DataDeviceEvent::DnDDropped => {
                    *dnd_icon2.lock().unwrap() = None;
                }
                _ => {}
            },
            default_action_chooser,
            log.clone(),
        );

        // init input
        let seat_name = backend_data.seat_name();

        let (mut seat, _) = Seat::new(&mut display.borrow_mut(), seat_name.clone(), log.clone());

        let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));

        let cursor_status2 = cursor_status.clone();
        let pointer = seat.add_pointer(move |new_status| {
            // TODO: hide winit system cursor when relevant
            *cursor_status2.lock().unwrap() = new_status
        });

        init_tablet_manager_global(&mut display.borrow_mut());

        let cursor_status3 = cursor_status.clone();
        seat.tablet_seat().on_cursor_surface(move |_tool, new_status| {
            // TODO: tablet tools should have their own cursors
            *cursor_status3.lock().unwrap() = new_status;
        });

        let keyboard = seat
            .add_keyboard(XkbConfig::default(), 200, 25, |seat, focus| {
                set_data_device_focus(seat, focus.and_then(|s| s.as_ref().client()))
            })
            .expect("Failed to initialize the keyboard");

        #[cfg(feature = "xwayland")]
        let xwayland = {
            let (xwayland, channel) = XWayland::new(handle.clone(), display.clone(), log.clone());
            let ret = handle.insert_source(channel, |event, _, anvil_state| match event {
                XWaylandEvent::Ready { connection, client } => anvil_state.xwayland_ready(connection, client),
                XWaylandEvent::Exited => anvil_state.xwayland_exited(),
            });
            if let Err(e) = ret {
                error!(
                    log,
                    "Failed to insert the XWaylandSource into the event loop: {}", e
                );
            }
            xwayland
        };

        AnvilState {
            backend_data,
            running: Arc::new(AtomicBool::new(true)),
            display,
            handle,
            window_map,
            output_map,
            dnd_icon,
            log,
            socket_name,
            pointer,
            keyboard,
            suppressed_keys: Vec::new(),
            cursor_status,
            pointer_location: (0.0, 0.0).into(),
            seat_name,
            seat,
            start_time: std::time::Instant::now(),
            #[cfg(feature = "xwayland")]
            xwayland,
        }
    }
}

pub trait Backend {
    fn seat_name(&self) -> String;
}
<|endoftext|>