<commit_before>extern crate sputnikvm;
extern crate serde_json;
extern crate hexutil;
extern crate bigint;
extern crate env_logger;
extern crate sha3;
extern crate rlp;
extern crate criterion;

mod blockchain;
pub mod util;

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

use serde_json::Value;
use std::str::FromStr;
use std::ops::Deref;
use std::sync::{Arc, Mutex};
use bigint::{Gas, M256, U256, H256, Address};
use hexutil::*;
use sputnikvm::errors::RequireError;
use sputnikvm::{VM, SeqContextVM, Context, VMStatus, Patch};

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

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

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

pub fn apply_to_block<P: Patch>(machine: &SeqContextVM<P>, 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<P: Patch>(v: &Value, block: &JSONBlock) -> SeqContextVM<P> {
    let transaction = create_context(v);

    SeqContextVM::<P>::new(transaction, block.block_header())
}

// TODO: consider refactoring
#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
#[cfg_attr(feature = "cargo-clippy", allow(collapsible_if))]
pub fn test_machine<P: Patch>(v: &Value, machine: &SeqContextVM<P>, block: &JSONBlock, history: &[Context], debug: bool) -> bool {
    let callcreates = &v["callcreates"];

    if callcreates.as_array().is_some() {
        for (i, callcreate) in callcreates.as_array().unwrap().into_iter().enumerate() {
            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(read_u256(callcreate["gasLimit"].as_str().unwrap()));
            let value = read_u256(callcreate["value"].as_str().unwrap());

            if i >= history.len() {
                if debug {
                    println!();
                    println!("Transaction check failed, expected more than {} items.", i);
                }
                return false;
            }
            let transaction = &history[i];
            if destination.is_some() {
                if transaction.address != destination.unwrap() {
                    if debug {
                        println!();
                        println!("Transaction address mismatch. 0x{:x} != 0x{:x}.", transaction.address, destination.unwrap());
                    }
                    return false;
                }
            }
            if transaction.gas_limit != gas_limit || transaction.value != value || if destination.is_some() { transaction.data.deref() != &data } else { transaction.code.deref() != &data } {
                if debug {
                    println!();
                    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;
            }
        }
    }

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

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

            return false;
        }
    }

    if let Some(gas) = gas {
        let gas = Gas::from(read_u256(gas));
        if machine.available_gas() != gas {
            if debug {
                println!();
                println!("Gas check failed, VM returned: 0x{:x}, expected: 0x{:x}",
                         machine.available_gas(), gas);
            }

            return false;
        }
    }

    let post_addresses = &v["post"];

    for (address, data) in post_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = read_u256(data["balance"].as_str().unwrap());
        let nonce = read_u256(data["nonce"].as_str().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 {
                println!();
                println!("Account code check failed for address 0x{:x}.", address);
            }

            return false;
        }

        if balance != block.balance(address) {
            if debug {
                println!();
                println!("Balance check failed for address 0x{:x}.", address);
                println!("Expected: 0x{:x}", balance);
                println!("Actual:   0x{:x}", block.balance(address));
            }

            return false;
        }

        if nonce != block.nonce(address) {
            if debug {
                println!();
                println!("Nonce check failed for address 0x{:x}.", address);
                println!("Expected: 0x{:x}", nonce);
                println!("Actual:   0x{:x}", block.nonce(address));
            }

            return false;
        }

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = read_u256(index.as_str());
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            if value != block.account_storage(address, index) {
                if debug {
                    println!();
                    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 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 = read_u256(index.as_str());
                let value = M256::from_str(value.as_str().unwrap()).unwrap();
                if value != block.account_storage(address, index) {
                    if debug {
                        println!();
                        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 logs_hash = v["logs"].as_str().map(read_u256);

    if logs_hash.is_some() {
        let logs_hash = logs_hash.unwrap();
        let vm_logs_hash = block.logs_rlp_hash();
        if logs_hash != vm_logs_hash {
            if debug {
                println!();
                println!("Logs check failed (hashes mismatch)");
                println!("Expected: 0x{:x}", logs_hash);
                println!("Actual: 0x{:x}", vm_logs_hash);
            }
            return false;
        }
    }

    true
}

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

pub fn test_transaction<P: Patch>(_name: &str, v: &Value, debug: bool) -> Result<bool, VMStatus> {
    let _ = env_logger::try_init();

    let mut block = create_block(v);
    let history: Arc<Mutex<Vec<Context>>> = Arc::new(Mutex::new(Vec::new()));
    let history_closure = history.clone();
    let mut machine = create_machine::<P>(v, &block);
    machine.add_context_history_hook(move |context| {
        history_closure.lock().unwrap().push(context.clone());
    });
    fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    if debug {
        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, &history.lock().unwrap(), debug) {
                Ok(true)
            } else {
                Ok(false)
            }
        } else {
            Err(machine.status())
        }
    } else if !is_ok(&machine.status()) {
        Ok(true)
    } else {
        Ok(false)
    }
}

use criterion::Criterion;

pub fn bench_transaction<P: Patch>(_name: &str, v: Value, c: &mut Criterion) {
    c.bench_function(_name, move |b| {
        b.iter_with_large_setup(|| {
            let block = create_block(&v);
            let history: Arc<Mutex<Vec<Context>>> = Arc::new(Mutex::new(Vec::new()));
            let history_closure = history.clone();
            let mut machine = create_machine::<P>(&v, &block);
            machine.add_context_history_hook(move |context| {
                history_closure.lock().unwrap().push(context.clone());
            });
            (machine, block)
        }, |(mut machine, block)| {
            fire_with_block(&mut machine, &block);
        })
    });
}

/// Read U256 number exactly the way go big.Int parses strings
/// except for base 2 and 8 which are not used in tests
pub fn read_u256(number: &str) -> U256 {
    if number.starts_with("0x") {
        U256::from_str(number).unwrap()
    } else {
        U256::from_dec_str(number).unwrap()
    }
}
<commit_msg>more verbose code mismatch message<commit_after>extern crate sputnikvm;
extern crate serde_json;
extern crate hexutil;
extern crate bigint;
extern crate env_logger;
extern crate sha3;
extern crate rlp;
extern crate criterion;

mod blockchain;
pub mod util;

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

use serde_json::Value;
use std::str::FromStr;
use std::ops::Deref;
use std::sync::{Arc, Mutex};
use bigint::{Gas, M256, U256, H256, Address};
use hexutil::*;
use sputnikvm::errors::RequireError;
use sputnikvm::{VM, SeqContextVM, Context, VMStatus, Patch};

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

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

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

pub fn apply_to_block<P: Patch>(machine: &SeqContextVM<P>, 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<P: Patch>(v: &Value, block: &JSONBlock) -> SeqContextVM<P> {
    let transaction = create_context(v);

    SeqContextVM::<P>::new(transaction, block.block_header())
}

// TODO: consider refactoring
#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
#[cfg_attr(feature = "cargo-clippy", allow(collapsible_if))]
pub fn test_machine<P: Patch>(v: &Value, machine: &SeqContextVM<P>, block: &JSONBlock, history: &[Context], debug: bool) -> bool {
    let callcreates = &v["callcreates"];

    if callcreates.as_array().is_some() {
        for (i, callcreate) in callcreates.as_array().unwrap().into_iter().enumerate() {
            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(read_u256(callcreate["gasLimit"].as_str().unwrap()));
            let value = read_u256(callcreate["value"].as_str().unwrap());

            if i >= history.len() {
                if debug {
                    println!();
                    println!("Transaction check failed, expected more than {} items.", i);
                }
                return false;
            }
            let transaction = &history[i];
            if destination.is_some() {
                if transaction.address != destination.unwrap() {
                    if debug {
                        println!();
                        println!("Transaction address mismatch. 0x{:x} != 0x{:x}.", transaction.address, destination.unwrap());
                    }
                    return false;
                }
            }
            if transaction.gas_limit != gas_limit || transaction.value != value || if destination.is_some() { transaction.data.deref() != &data } else { transaction.code.deref() != &data } {
                if debug {
                    println!();
                    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;
            }
        }
    }

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

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

            return false;
        }
    }

    if let Some(gas) = gas {
        let gas = Gas::from(read_u256(gas));
        if machine.available_gas() != gas {
            if debug {
                println!();
                println!("Gas check failed, VM returned: 0x{:x}, expected: 0x{:x}",
                         machine.available_gas(), gas);
            }

            return false;
        }
    }

    let post_addresses = &v["post"];

    for (address, data) in post_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = read_u256(data["balance"].as_str().unwrap());
        let nonce = read_u256(data["nonce"].as_str().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 {
                println!();
                println!("Account code check failed for address 0x{:x}.", address);
                println!("Expected: {:x?}", block.account_code(address));
                println!("Actual:   {:x?}", code_ref);
            }

            return false;
        }

        if balance != block.balance(address) {
            if debug {
                println!();
                println!("Balance check failed for address 0x{:x}.", address);
                println!("Expected: 0x{:x}", balance);
                println!("Actual:   0x{:x}", block.balance(address));
            }

            return false;
        }

        if nonce != block.nonce(address) {
            if debug {
                println!();
                println!("Nonce check failed for address 0x{:x}.", address);
                println!("Expected: 0x{:x}", nonce);
                println!("Actual:   0x{:x}", block.nonce(address));
            }

            return false;
        }

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = read_u256(index.as_str());
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            if value != block.account_storage(address, index) {
                if debug {
                    println!();
                    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 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 = read_u256(index.as_str());
                let value = M256::from_str(value.as_str().unwrap()).unwrap();
                if value != block.account_storage(address, index) {
                    if debug {
                        println!();
                        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 logs_hash = v["logs"].as_str().map(read_u256);

    if logs_hash.is_some() {
        let logs_hash = logs_hash.unwrap();
        let vm_logs_hash = block.logs_rlp_hash();
        if logs_hash != vm_logs_hash {
            if debug {
                println!();
                println!("Logs check failed (hashes mismatch)");
                println!("Expected: 0x{:x}", logs_hash);
                println!("Actual: 0x{:x}", vm_logs_hash);
            }
            return false;
        }
    }

    true
}

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

pub fn test_transaction<P: Patch>(_name: &str, v: &Value, debug: bool) -> Result<bool, VMStatus> {
    let _ = env_logger::try_init();

    let mut block = create_block(v);
    let history: Arc<Mutex<Vec<Context>>> = Arc::new(Mutex::new(Vec::new()));
    let history_closure = history.clone();
    let mut machine = create_machine::<P>(v, &block);
    machine.add_context_history_hook(move |context| {
        history_closure.lock().unwrap().push(context.clone());
    });
    fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    if debug {
        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, &history.lock().unwrap(), debug) {
                Ok(true)
            } else {
                Ok(false)
            }
        } else {
            Err(machine.status())
        }
    } else if !is_ok(&machine.status()) {
        Ok(true)
    } else {
        Ok(false)
    }
}

use criterion::Criterion;

pub fn bench_transaction<P: Patch>(_name: &str, v: Value, c: &mut Criterion) {
    c.bench_function(_name, move |b| {
        b.iter_with_large_setup(|| {
            let block = create_block(&v);
            let history: Arc<Mutex<Vec<Context>>> = Arc::new(Mutex::new(Vec::new()));
            let history_closure = history.clone();
            let mut machine = create_machine::<P>(&v, &block);
            machine.add_context_history_hook(move |context| {
                history_closure.lock().unwrap().push(context.clone());
            });
            (machine, block)
        }, |(mut machine, block)| {
            fire_with_block(&mut machine, &block);
        })
    });
}

/// Read U256 number exactly the way go big.Int parses strings
/// except for base 2 and 8 which are not used in tests
pub fn read_u256(number: &str) -> U256 {
    if number.starts_with("0x") {
        U256::from_str(number).unwrap()
    } else {
        U256::from_dec_str(number).unwrap()
    }
}
<|endoftext|>


<commit_before>use anyhow::{bail, Context};
use serde::Deserialize;
use std::{
    collections::BTreeMap,
    fs::File,
    io::Write,
    process::{Command, Output, Stdio},
    str,
    time::SystemTime,
};
use structopt::StructOpt;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
use vcpkg::{find_vcpkg_root, Config};

// settings for a specific Rust target
#[derive(Debug, Deserialize)]
struct Target {
    triplet: Option<String>,
    // this install key for a specific target overrides the main entry
    // so a the target can opt out of installing packages
    // #[serde(default = "Vec::new")]
    install: Option<Vec<String>>,
}

#[derive(Debug, Deserialize)]
struct Vcpkg {
    vcpkg_root: Option<String>,
    #[serde(default = "BTreeMap::new")]
    target: BTreeMap<String, Target>,
    branch: Option<String>,
    rev: Option<String>,
    git: Option<String>,
    tag: Option<String>,
    #[serde(default = "Vec::new")]
    install: Vec<String>,
}
#[derive(Debug, Deserialize)]
struct Metadata {
    vcpkg: Vcpkg,
}
#[derive(Debug, PartialEq, StructOpt)]
/// Install vcpkg and build packages
///
/// This program clones vcpkg from the specified source and
/// compiles it. It then builds packages required by crates
/// that are depended on by the top level crate being built.
#[structopt(rename_all = "kebab-case")]
struct Opt {
    ///
    #[structopt(short, long)]
    verbose: bool,

    // #[structopt(long)]
    // manifest_path: Option<String>,
    #[structopt(subcommand)]
    sub: Subcommands,
}

#[derive(Debug, PartialEq, StructOpt)]
enum Subcommands {
    /// Build packages
    ///
    /// This command will clone or update a vcpkg tree to the version specified
    /// in Cargo.toml and build the required packages.
    Build {
        #[structopt(long)]
        /// Path to Cargo.toml
        manifest_path: Option<String>,

        #[structopt(long)]
        /// Build for the target triple
        target: Option<String>,
    },
    // `external_subcommand` tells structopt to put
    // all the extra arguments into this Vec
    // #[structopt(external_subcommand)]
    // Cargo(Vec<String>),
}

fn main() {
    // cargo passes us the "vcpkg" arg when it calls us. Drop it before
    // parsing the arg list so t doesn't end up the usage description
    let mut args = std::env::args().collect::<Vec<_>>();
    if args.len() > 2 && args[1] == "vcpkg" {
        args.remove(1);
    }
    let args = Opt::from_iter(args);

    match args.sub {
        Subcommands::Build { .. } => {
            build(args).unwrap_or_else(|e| {
                eprintln!("cargo-vcpkg: {}", e);
                std::process::exit(1);
            });
        }
    }
}
//use std::io::Write;
fn build(opt: Opt) -> Result<(), anyhow::Error> {
    let start_time = SystemTime::now();

    let target_triple = target_triple();

    let verbose = opt.verbose;

    let mut args = std::env::args().skip_while(|val| !val.starts_with("--manifest-path"));
    let mut cmd = cargo_metadata::MetadataCommand::new();
    // opt.manifest_path.map(|p| cmd.manifest_path(p));

    match args.next() {
        Some(p) if p == "--manifest-path" => {
            cmd.manifest_path(args.next().unwrap());
        }
        Some(p) => {
            cmd.manifest_path(p.trim_start_matches("--manifest-path="));
        }
        None => {}
    }
    let metadata = cmd.exec()?;

    let resolve = metadata.resolve.as_ref().unwrap();

    let root_crate = resolve
        .root
        .as_ref()
        .context("cannot run on a virtual manifest, this command requires running against an actual package in this workspace.")?;

    let mut git_url = None;
    let mut vcpkg_ports = Vec::new();
    let mut rev_tag_branch: Option<String> = None;
    let mut vcpkg_triplet = None;
    for p in &metadata.packages {
        if let Ok(v) = serde_json::from_value::<Metadata>(p.metadata.clone()) {
            let v = v.vcpkg;
            let is_root_crate = p.id == *root_crate;

            // only use git url and rev from the root crate
            if v.git.is_some() && is_root_crate {
                git_url = v.git;

                // TODO: check the target and use it's package set if required
                // TODO: get the correct target
                // TODO: make sure to pull if it's a branch
                rev_tag_branch = match (&v.branch, &v.tag, &v.rev) {
                    (Some(b), None, None) => Some(b.into()),
                    (None, Some(t), None) => Some(t.into()),
                    (None, None, Some(r)) => Some(r.into()),
                    _ => {
                        bail!("must specify one of branch,rev,tag for git source");
                    }
                };
            }

            // if there is specific configuration for the target and it has
            // an install key, use that rather than the general install key
            match v.target.get(&target_triple) {
                Some(target) => {
                    if target.install.is_some() {
                        vcpkg_ports.extend_from_slice(&target.install.as_ref().unwrap().as_slice());
                    }
                    if is_root_crate {
                        vcpkg_triplet = target.triplet.clone();
                    }
                }
                _ => {
                    // not found or install is empty
                    vcpkg_ports.extend_from_slice(&v.install.as_slice());
                }
            }
        }
    }

    // should we modify the existing?
    // let mut allow_updates = true;

    // find the vcpkg root
    let vcpkg_root = find_vcpkg_root(&Config::default()).unwrap_or_else(|_| {
        let target_directory = metadata.target_directory.clone();
        let mut vcpkg_root = target_directory.clone();
        vcpkg_root.push("vcpkg");
        vcpkg_root.to_path_buf();
        vcpkg_root
    });
    if verbose {
        println!("vcpkg root is {}", vcpkg_root.display());
    }
    // if it does not exist, clone vcpkg from git
    let mut vcpkg_root_file = vcpkg_root.clone();
    vcpkg_root_file.push(".vcpkg-root");
    if !vcpkg_root_file.exists() {
        let git_url = git_url.context(format!(
            "could not find a vcpkg installation and crate \
        {} does not specify a git repository to clone from.",
            root_crate
        ))?;
        print_tag("Cloning", &git_url);
        let mut cmd = Command::new("git");
        cmd.arg("clone");
        cmd.arg(git_url);
        cmd.arg(&vcpkg_root);
        let _output = run_command(cmd, verbose).context("failed to run git clone")?;

        // create a cargo-vcpkg.toml in the newly created vcpkg tree
        let mut cargo_vcpkg_config_file = vcpkg_root.clone();
        cargo_vcpkg_config_file.push("downloads");
        std::fs::create_dir_all(&cargo_vcpkg_config_file)
            .context("could not create downloads directory in vcpkg tree")?;
        cargo_vcpkg_config_file.push("cargo-vcpkg.toml");
        let mut file =
            File::create(cargo_vcpkg_config_file).context("could not create cargo-vcpkg.toml")?;
        file.write_all(b"# This file was created automatically by cargo-vcpkg\n")?;

    //eprintln!("git clone done = {:?}", output.status);
    } else {
        print_tag("Fetching", "vcpkg");
        let mut cmd = Command::new("git");
        cmd.arg("fetch");
        cmd.arg("--verbose");
        cmd.arg("--all");
        let output = run_command(cmd, verbose).context("failed to run git fatch")?;

        if !output.status.success() {
            bail!("fetch failed");
        }
    }
    // otherwise, check that the rev is where we want it to be
    // there needs to be some serious thought here because if we are on a branch
    // does this mean we should fetch?

    // check out the required rev
    let rev_tag_branch = rev_tag_branch.unwrap();
    print_tag("Checkout", &format!("rev/tag/branch {}", rev_tag_branch));
    let mut cmd = Command::new("git");
    cmd.arg("checkout");
    cmd.arg(rev_tag_branch);
    cmd.current_dir(&vcpkg_root);
    run_command(cmd, verbose).context("failed to execute process")?;

    // try and run 'vcpkg update' and if it fails or gives the version warning, rebuild it
    let require_bootstrap = match vcpkg_command(&vcpkg_root, &vcpkg_triplet)
        .arg("update")
        .output()
    {
        Ok(output) => {
            if verbose {
                println!("-- stdout --\n{}", String::from_utf8_lossy(&output.stdout));
                println!("-- stderr --\n{}", String::from_utf8_lossy(&output.stderr));
                println!("{:?}", output.status);
            }
            if output.status.success()
                && !str::from_utf8(&output.stdout)
                    .unwrap()
                    .contains("Warning: Different source is available for vcpkg")
            {
                false
            } else {
                true
            }
        }
        Err(_) => true,
    };

    // build vcpkg
    // if cfg!(windows) {

    // }

    if require_bootstrap {
        // let version = File::open()
        print_tag("Compiling", "vcpkg");
        let mut cmd = Command::new("sh");
        cmd.arg("-c");
        cmd.arg("./bootstrap-vcpkg.sh");
        cmd.arg("-disableMetrics");
        cmd.current_dir(&vcpkg_root);
        run_command(cmd, verbose).context("failed to run vcpkg bootstrap")?;
    }

    // TODO: upgrade anything that is installed
    print_tag("Compiling", &vcpkg_ports.join(", "));
    let mut v = vcpkg_command(&vcpkg_root, &vcpkg_triplet);
    v.arg("install");
    v.arg("--recurse");
    v.args(vcpkg_ports.as_slice());
    run_command(v, verbose).context("failed to execute vcpkg install")?;

    let duration = SystemTime::now().duration_since(start_time).unwrap();
    print_tag("Finished", &format!("in {:0.2}s", duration.as_secs_f32()));
    Ok(())
}

fn target_triple() -> String {
    let mut args = std::env::args().skip_while(|val| !val.starts_with("--target"));
    match args.next() {
        Some(p) if p == "--target" => args.next().unwrap(),
        Some(p) => p.trim_start_matches("--target=").into(),
        None => std::env!("TARGET").into(),
    }
}

fn vcpkg_command(vcpkg_root: &std::path::Path, vcpkg_triplet: &Option<String>) -> Command {
    let mut x = vcpkg_root.to_path_buf();
    if cfg!(windows) {
        x.push("vcpkg.exe");
    } else {
        x.push("vcpkg")
    }
    let mut command = Command::new(x);
    command.current_dir(&vcpkg_root);
    if let Some(triplet) = &vcpkg_triplet {
        command.arg("--triplet");
        command.arg(triplet);
    }
    command
}

fn run_command(mut cmd: Command, verbose: bool) -> Result<Output, anyhow::Error> {
    if verbose {
        cmd.stdout(Stdio::inherit());
        cmd.stderr(Stdio::inherit());
    }
    let output = cmd.output()?;

    if !output.status.success() && !verbose {
        println!("-- stdout --\n{}", String::from_utf8_lossy(&output.stdout));
        println!("-- stderr --\n{}", String::from_utf8_lossy(&output.stderr));
        bail!("failed");
    }

    Ok(output)
}

fn print_tag(tag: &str, detail: &str) {
    let mut stdout = StandardStream::stdout(ColorChoice::Auto);
    stdout
        .set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))
        .unwrap();

    print!("{:>12} ", tag);
    stdout.reset().unwrap();
    println!("{}", detail);
}
<commit_msg>bootstrap vcpkg on windows without using git bash<commit_after>use anyhow::{bail, Context};
use serde::Deserialize;
use std::{
    collections::BTreeMap,
    fs::File,
    io::Write,
    process::{Command, Output, Stdio},
    str,
    time::SystemTime,
};
use structopt::StructOpt;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
use vcpkg::{find_vcpkg_root, Config};

// settings for a specific Rust target
#[derive(Debug, Deserialize)]
struct Target {
    triplet: Option<String>,
    // this install key for a specific target overrides the main entry
    // so a the target can opt out of installing packages
    // #[serde(default = "Vec::new")]
    install: Option<Vec<String>>,
}

#[derive(Debug, Deserialize)]
struct Vcpkg {
    vcpkg_root: Option<String>,
    #[serde(default = "BTreeMap::new")]
    target: BTreeMap<String, Target>,
    branch: Option<String>,
    rev: Option<String>,
    git: Option<String>,
    tag: Option<String>,
    #[serde(default = "Vec::new")]
    install: Vec<String>,
}
#[derive(Debug, Deserialize)]
struct Metadata {
    vcpkg: Vcpkg,
}
#[derive(Debug, PartialEq, StructOpt)]
/// Install vcpkg and build packages
///
/// This program clones vcpkg from the specified source and
/// compiles it. It then builds packages required by crates
/// that are depended on by the top level crate being built.
#[structopt(rename_all = "kebab-case")]
struct Opt {
    ///
    #[structopt(short, long)]
    verbose: bool,

    // #[structopt(long)]
    // manifest_path: Option<String>,
    #[structopt(subcommand)]
    sub: Subcommands,
}

#[derive(Debug, PartialEq, StructOpt)]
enum Subcommands {
    /// Build packages
    ///
    /// This command will clone or update a vcpkg tree to the version specified
    /// in Cargo.toml and build the required packages.
    Build {
        #[structopt(long)]
        /// Path to Cargo.toml
        manifest_path: Option<String>,

        #[structopt(long)]
        /// Build for the target triple
        target: Option<String>,
    },
    // `external_subcommand` tells structopt to put
    // all the extra arguments into this Vec
    // #[structopt(external_subcommand)]
    // Cargo(Vec<String>),
}

fn main() {
    // cargo passes us the "vcpkg" arg when it calls us. Drop it before
    // parsing the arg list so t doesn't end up the usage description
    let mut args = std::env::args().collect::<Vec<_>>();
    if args.len() > 2 && args[1] == "vcpkg" {
        args.remove(1);
    }
    let args = Opt::from_iter(args);

    match args.sub {
        Subcommands::Build { .. } => {
            build(args).unwrap_or_else(|e| {
                eprintln!("cargo-vcpkg: {}", e);
                std::process::exit(1);
            });
        }
    }
}
//use std::io::Write;
fn build(opt: Opt) -> Result<(), anyhow::Error> {
    let start_time = SystemTime::now();

    let target_triple = target_triple();

    let verbose = opt.verbose;

    let mut args = std::env::args().skip_while(|val| !val.starts_with("--manifest-path"));
    let mut cmd = cargo_metadata::MetadataCommand::new();
    // opt.manifest_path.map(|p| cmd.manifest_path(p));

    match args.next() {
        Some(p) if p == "--manifest-path" => {
            cmd.manifest_path(args.next().unwrap());
        }
        Some(p) => {
            cmd.manifest_path(p.trim_start_matches("--manifest-path="));
        }
        None => {}
    }
    let metadata = cmd.exec()?;

    let resolve = metadata.resolve.as_ref().unwrap();

    let root_crate = resolve
        .root
        .as_ref()
        .context("cannot run on a virtual manifest, this command requires running against an actual package in this workspace.")?;

    let mut git_url = None;
    let mut vcpkg_ports = Vec::new();
    let mut rev_tag_branch: Option<String> = None;
    let mut vcpkg_triplet = None;
    for p in &metadata.packages {
        if let Ok(v) = serde_json::from_value::<Metadata>(p.metadata.clone()) {
            let v = v.vcpkg;
            let is_root_crate = p.id == *root_crate;

            // only use git url and rev from the root crate
            if v.git.is_some() && is_root_crate {
                git_url = v.git;

                // TODO: check the target and use it's package set if required
                // TODO: get the correct target
                // TODO: make sure to pull if it's a branch
                rev_tag_branch = match (&v.branch, &v.tag, &v.rev) {
                    (Some(b), None, None) => Some(b.into()),
                    (None, Some(t), None) => Some(t.into()),
                    (None, None, Some(r)) => Some(r.into()),
                    _ => {
                        bail!("must specify one of branch,rev,tag for git source");
                    }
                };
            }

            // if there is specific configuration for the target and it has
            // an install key, use that rather than the general install key
            match v.target.get(&target_triple) {
                Some(target) => {
                    if target.install.is_some() {
                        vcpkg_ports.extend_from_slice(&target.install.as_ref().unwrap().as_slice());
                    }
                    if is_root_crate {
                        vcpkg_triplet = target.triplet.clone();
                    }
                }
                _ => {
                    // not found or install is empty
                    vcpkg_ports.extend_from_slice(&v.install.as_slice());
                }
            }
        }
    }

    // should we modify the existing?
    // let mut allow_updates = true;

    // find the vcpkg root
    let vcpkg_root = find_vcpkg_root(&Config::default()).unwrap_or_else(|_| {
        let target_directory = metadata.target_directory.clone();
        let mut vcpkg_root = target_directory.clone();
        vcpkg_root.push("vcpkg");
        vcpkg_root.to_path_buf();
        vcpkg_root
    });
    if verbose {
        println!("vcpkg root is {}", vcpkg_root.display());
    }
    // if it does not exist, clone vcpkg from git
    let mut vcpkg_root_file = vcpkg_root.clone();
    vcpkg_root_file.push(".vcpkg-root");
    if !vcpkg_root_file.exists() {
        let git_url = git_url.context(format!(
            "could not find a vcpkg installation and crate \
        {} does not specify a git repository to clone from.",
            root_crate
        ))?;
        print_tag("Cloning", &git_url);
        let mut cmd = Command::new("git");
        cmd.arg("clone");
        cmd.arg(git_url);
        cmd.arg(&vcpkg_root);
        let _output = run_command(cmd, verbose).context("failed to run git clone")?;

        // create a cargo-vcpkg.toml in the newly created vcpkg tree
        let mut cargo_vcpkg_config_file = vcpkg_root.clone();
        cargo_vcpkg_config_file.push("downloads");
        std::fs::create_dir_all(&cargo_vcpkg_config_file)
            .context("could not create downloads directory in vcpkg tree")?;
        cargo_vcpkg_config_file.push("cargo-vcpkg.toml");
        let mut file =
            File::create(cargo_vcpkg_config_file).context("could not create cargo-vcpkg.toml")?;
        file.write_all(b"# This file was created automatically by cargo-vcpkg\n")?;

    //eprintln!("git clone done = {:?}", output.status);
    } else {
        print_tag("Fetching", "vcpkg");
        let mut cmd = Command::new("git");
        cmd.arg("fetch");
        cmd.arg("--verbose");
        cmd.arg("--all");
        let output = run_command(cmd, verbose).context("failed to run git fatch")?;

        if !output.status.success() {
            bail!("fetch failed");
        }
    }
    // otherwise, check that the rev is where we want it to be
    // there needs to be some serious thought here because if we are on a branch
    // does this mean we should fetch?

    // check out the required rev
    let rev_tag_branch = rev_tag_branch.unwrap();
    print_tag("Checkout", &format!("rev/tag/branch {}", rev_tag_branch));
    let mut cmd = Command::new("git");
    cmd.arg("checkout");
    cmd.arg(rev_tag_branch);
    cmd.current_dir(&vcpkg_root);
    run_command(cmd, verbose).context("failed to execute process")?;

    // try and run 'vcpkg update' and if it fails or gives the version warning, rebuild it
    let require_bootstrap = match vcpkg_command(&vcpkg_root, &vcpkg_triplet)
        .arg("update")
        .output()
    {
        Ok(output) => {
            if verbose {
                println!("-- stdout --\n{}", String::from_utf8_lossy(&output.stdout));
                println!("-- stderr --\n{}", String::from_utf8_lossy(&output.stderr));
                println!("{:?}", output.status);
            }
            if output.status.success()
                && !str::from_utf8(&output.stdout)
                    .unwrap()
                    .contains("Warning: Different source is available for vcpkg")
            {
                false
            } else {
                true
            }
        }
        Err(_) => true,
    };

    if require_bootstrap {
        print_tag("Compiling", "vcpkg");
        let mut cmd = if cfg!(windows) {
            let mut cmd = Command::new("cmd");
            cmd.arg("/C");
            cmd.arg("bootstrap-vcpkg.bat");
            cmd
        } else {
            let mut cmd = Command::new("sh");
            cmd.arg("-c");
            cmd.arg("./bootstrap-vcpkg.sh");
            cmd
        };
        cmd.arg("-disableMetrics");
        cmd.current_dir(&vcpkg_root);
        run_command(cmd, verbose).context("failed to run vcpkg bootstrap")?;
    }

    // TODO: upgrade anything that is installed
    print_tag("Compiling", &vcpkg_ports.join(", "));
    let mut v = vcpkg_command(&vcpkg_root, &vcpkg_triplet);
    v.arg("install");
    v.arg("--recurse");
    v.args(vcpkg_ports.as_slice());
    run_command(v, verbose).context("failed to execute vcpkg install")?;

    let duration = SystemTime::now().duration_since(start_time).unwrap();
    print_tag("Finished", &format!("in {:0.2}s", duration.as_secs_f32()));
    Ok(())
}

fn target_triple() -> String {
    let mut args = std::env::args().skip_while(|val| !val.starts_with("--target"));
    match args.next() {
        Some(p) if p == "--target" => args.next().unwrap(),
        Some(p) => p.trim_start_matches("--target=").into(),
        None => std::env!("TARGET").into(),
    }
}

fn vcpkg_command(vcpkg_root: &std::path::Path, vcpkg_triplet: &Option<String>) -> Command {
    let mut x = vcpkg_root.to_path_buf();
    if cfg!(windows) {
        x.push("vcpkg.exe");
    } else {
        x.push("vcpkg")
    }
    let mut command = Command::new(x);
    command.current_dir(&vcpkg_root);
    if let Some(triplet) = &vcpkg_triplet {
        command.arg("--triplet");
        command.arg(triplet);
    }
    command
}

fn run_command(mut cmd: Command, verbose: bool) -> Result<Output, anyhow::Error> {
    if verbose {
        cmd.stdout(Stdio::inherit());
        cmd.stderr(Stdio::inherit());
    }
    let output = cmd.output()?;

    if !output.status.success() && !verbose {
        println!("-- stdout --\n{}", String::from_utf8_lossy(&output.stdout));
        println!("-- stderr --\n{}", String::from_utf8_lossy(&output.stderr));
        bail!("failed");
    }

    Ok(output)
}

fn print_tag(tag: &str, detail: &str) {
    let mut stdout = StandardStream::stdout(ColorChoice::Auto);
    stdout
        .set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))
        .unwrap();

    print!("{:>12} ", tag);
    stdout.reset().unwrap();
    println!("{}", detail);
}
<|endoftext|>


<commit_before>/*!
 * Base16 Module
 *
 * See <http://tools.ietf.org/html/rfc4648#section-8> for details.
 *
 * # Example
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * use encoding;
 * import encoding::Codec;
 *
 * let src = "base16";
 * let res = src.encode(encoding::Base16);
 * let res = str::from_bytes(res);
 *
 * io::println(fmt!("%s", res));
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

export encode, decode;

// 0123456789ABCDEF
const TABLE: [u8]/16 = [
    48, 49, 50, 51, 52, 53, 54, 55,
    56, 57, 65, 66, 67, 68, 69, 70,
];

const DECODE_MAP: [u8]/256 = [
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      0,   1,   2,   3,   4,   5,   6,   7,   8,   9, 255, 255, 255, 255, 255, 255,
    255,  10,  11,  12,  13,  14,  15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255,  10,  11,  12,  13,  14,  15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
];

struct Base16 {
    table: [u8]/16;
    decode_map: [u8]/256;
}

fn Base16() -> Base16 {
    Base16 {table: TABLE, decode_map: DECODE_MAP}
}

#[inline(always)]
pure fn encoded_len(src_length: uint) -> uint { src_length * 2 }
#[inline(always)]
pure fn decoded_len(src_length: uint) -> uint { src_length / 2 }

impl Base16 : Encode {
    fn encode(dst: &[mut u8], src: &[u8]) {
        b16encode(self.table, dst, src);
    }
    fn encoded_len(src_length: uint) -> uint {
        encoded_len(src_length)
    }

    /**
     * Encode input bytes to hex-encoded bytes.
     *
     * # Arguments
     *
     * * src - bytes for encoding
     *
     * # Return
     *
     * hex-encoded bytes
     */
    fn encode_bytes(src: &[u8]) -> ~[u8] {
        let dst_len = self.encoded_len(src.len());
        let dst = vec::to_mut(vec::from_elem(dst_len, 0u8));
        self.encode(dst, src);
        vec::from_mut(dst)
    }
}

impl Base16 : Decode {
    fn decode(dst: &[mut u8], src: &[u8]) -> uint {
        b16decode(self.decode_map, dst, src)
    }
    fn decoded_len(src_length: uint) -> uint {
        decoded_len(src_length)
    }

    /**
     * Decode hex-encoded bytes to its original bytes.
     *
     * # Arguments
     *
     * * src - hex-encoded bytes
     *
     * # Return
     *
     * decoded bytes
     */
    fn decode_bytes(src: &[u8]) -> ~[u8] {
        let dst_len = self.decoded_len(src.len());
        let dst = vec::to_mut(vec::from_elem(dst_len, 0u8));
        let end = self.decode(dst, src);
        vec::slice(vec::from_mut(dst), 0u, end)
    }
}

/**
 * Shortcut for base16#encode_bytes
 *
 * # Arguments
 *
 * * src - bytes for encoding
 *
 * # Return
 *
 * hex-encoded bytes
 */
fn encode(src: &[u8]) -> ~[u8] {
    let base16 = Base16();
    base16.encode_bytes(src)
}

/**
 * Shortcut for base16#decode_bytes
 *
 * # Arguments
 *
 * * src - hex-encoded bytes
 *
 * # Return
 *
 * decoded bytes
 */
fn decode(src: &[u8]) -> ~[u8] {
    let base16 = Base16();
    base16.decode_bytes(src)
}

macro_rules! abort {
    { $s:expr } => { fail str::from_slice($s) }
}

fn b16encode(table: &[u8], dst: &[mut u8], src: &[u8]) {
    for uint::range(0, src.len()) |j| {
        dst[j+1*j]     = table[src[j]>>4];
        dst[j+1*j + 1] = table[src[j] & 0x0f];
    }
}

fn b16decode(decode_map: &[u8], dst: &[mut u8], src: &[u8]) -> uint {
    let mut src_length = src.len();
    let mut i = 0u;
    let mut j = 0u;

    while src_length > 0 {
        if char::is_whitespace(src[i] as char) {
            src_length -= 1;
            i += 1;
            again;
        }

        let chr1 = decode_map[src[i]];
        let chr2 = decode_map[src[i+1]];
        if chr1 == 0xff_u8 || chr2 == 0xff_u8 {
            abort!("malformed base16 string");
        }
        dst[j] = chr1<<4 | chr2;

        src_length -= 2;
        i += 2;
        j += 1;
    }

    j
}

#[cfg(test)]
module tests {
    #[test]
    fn test_encode() {
        let source = str::bytes("foo");
        let expect = str::bytes("666F6F");
        let actual = encode(source);
        assert expect == actual;
    }
    #[test]
    fn test_decode() {
        let source = str::bytes("\t66 6f\r\n 6f");
        let expect = str::bytes("foo");
        let actual = decode(source);
        assert expect == actual;
    }
}
<commit_msg>base16: first cut at stream abstraction<commit_after>/*!
 * Base16 Module
 *
 * See <http://tools.ietf.org/html/rfc4648#section-8> for details.
 *
 * # Example
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * use encoding;
 * import encoding::Codec;
 *
 * let src = "base16";
 * let res = src.encode(encoding::Base16);
 * let res = str::from_bytes(res);
 *
 * io::println(fmt!("%s", res));
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

export encode, decode;

// 0123456789ABCDEF
const TABLE: [u8]/16 = [
    48, 49, 50, 51, 52, 53, 54, 55,
    56, 57, 65, 66, 67, 68, 69, 70,
];

const DECODE_MAP: [u8]/256 = [
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
      0,   1,   2,   3,   4,   5,   6,   7,   8,   9, 255, 255, 255, 255, 255, 255,
    255,  10,  11,  12,  13,  14,  15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255,  10,  11,  12,  13,  14,  15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
];

struct Base16 {
    table: [u8]/16;
    decode_map: [u8]/256;
}

fn Base16() -> Base16 {
    Base16 {table: TABLE, decode_map: DECODE_MAP}
}

#[inline(always)]
pure fn encoded_len(src_length: uint) -> uint { src_length * 2 }
#[inline(always)]
pure fn decoded_len(src_length: uint) -> uint { src_length / 2 }

impl Base16 : Encode {
    fn encode(dst: &[mut u8], src: &[u8]) {
        b16encode(self.table, dst, src);
    }
    fn encoded_len(src_length: uint) -> uint {
        encoded_len(src_length)
    }

    /**
     * Encode input bytes to hex-encoded bytes.
     *
     * # Arguments
     *
     * * src - bytes for encoding
     *
     * # Return
     *
     * hex-encoded bytes
     */
    fn encode_bytes(src: &[u8]) -> ~[u8] {
        let dst_len = self.encoded_len(src.len());
        let dst = vec::to_mut(vec::from_elem(dst_len, 0u8));
        self.encode(dst, src);
        vec::from_mut(dst)
    }
}

impl Base16 : Decode {
    fn decode(dst: &[mut u8], src: &[u8]) -> uint {
        b16decode(self.decode_map, dst, src)
    }
    fn decoded_len(src_length: uint) -> uint {
        decoded_len(src_length)
    }

    /**
     * Decode hex-encoded bytes to its original bytes.
     *
     * # Arguments
     *
     * * src - hex-encoded bytes
     *
     * # Return
     *
     * decoded bytes
     */
    fn decode_bytes(src: &[u8]) -> ~[u8] {
        let dst_len = self.decoded_len(src.len());
        let dst = vec::to_mut(vec::from_elem(dst_len, 0u8));
        let end = self.decode(dst, src);
        vec::slice(vec::from_mut(dst), 0u, end)
    }
}

/**
 * Shortcut for base16#encode_bytes
 *
 * # Arguments
 *
 * * src - bytes for encoding
 *
 * # Return
 *
 * hex-encoded bytes
 */
fn encode(src: &[u8]) -> ~[u8] {
    let base16 = Base16();
    base16.encode_bytes(src)
}

/**
 * Shortcut for base16#decode_bytes
 *
 * # Arguments
 *
 * * src - hex-encoded bytes
 *
 * # Return
 *
 * decoded bytes
 */
fn decode(src: &[u8]) -> ~[u8] {
    let base16 = Base16();
    base16.decode_bytes(src)
}

struct Base16Writer {
    base16: &Base16;
    writer: &io::writer;
    outbuf: [mut u8]/1024;
}

fn Base16Writer(base16: &Base16, writer: &io::writer) -> Base16Writer {
    Base16Writer {
        base16: base16,
        writer: writer,
        outbuf: [mut 0, ..1024]
    }
}

impl Base16Writer {
    fn write(buf: &[u8]) {
        let mut buf = vec::view(buf, 0, buf.len());

        while buf.len() > 0 {
            let buflen = buf.len();
            let nn = self.outbuf.len() / 2;
            let nn = if nn > buflen { buflen } else { nn };

            if nn > 0 {
                self.base16.encode(self.outbuf, vec::view(buf, 0, nn));
                self.writer.write(vec::mut_view(self.outbuf, 0, nn * 2));
            }

            buf = vec::view(buf, nn, buflen);
        }
    }
}

macro_rules! abort {
    { $s:expr } => { fail str::from_slice($s) }
}

fn b16encode(table: &[u8], dst: &[mut u8], src: &[u8]) {
    for uint::range(0, src.len()) |j| {
        dst[j+1*j]     = table[src[j]>>4];
        dst[j+1*j + 1] = table[src[j] & 0x0f];
    }
}

fn b16decode(decode_map: &[u8], dst: &[mut u8], src: &[u8]) -> uint {
    let mut src_length = src.len();
    let mut i = 0u;
    let mut j = 0u;

    while src_length > 0 {
        if char::is_whitespace(src[i] as char) {
            src_length -= 1;
            i += 1;
            again;
        }

        let chr1 = decode_map[src[i]];
        let chr2 = decode_map[src[i+1]];
        if chr1 == 0xff_u8 || chr2 == 0xff_u8 {
            abort!("malformed base16 string");
        }
        dst[j] = chr1<<4 | chr2;

        src_length -= 2;
        i += 2;
        j += 1;
    }

    j
}

#[cfg(test)]
module tests {
    #[test]
    fn test_encode() {
        let source = str::bytes("foo");
        let expect = str::bytes("666F6F");
        let actual = encode(source);
        assert expect == actual;
    }
    #[test]
    fn test_decode() {
        let source = str::bytes("\t66 6f\r\n 6f");
        let expect = str::bytes("foo");
        let actual = decode(source);
        assert expect == actual;
    }
    #[test]
    fn test_base16_writer() {
        let base16 = Base16();

        let source1 = str::bytes("fo");
        let source2 = str::bytes("o");
        let expect  = str::bytes("666F6F");
        let actual  = io::with_buf_writer(|writer| {
            let writer = Base16Writer(&base16, &writer);
            writer.write(source1);
            writer.write(source2);
        });

        assert expect == actual;
    }
}
<|endoftext|>


<commit_before>extern crate collections;
extern crate sync;
extern crate rand;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use std::num::Zero;
use sync::{Arc, RWLock};
use sync::Future;
use rand::task_rng;
use rand::distributions::{IndependentSample, Range};
use rand::distributions::range::SampleRange;

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	path: Path,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

struct BufferFrame {
	page_id: u64,
	data: Vec<u8>,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint, path: Path) -> BufferManager {
		let h = HashMap::with_capacity(size);
		BufferManager {size: size, entries: h, path: path}
	}

	fn open_or_create(&self, page_id: u64) -> File {
		let file_path = self.path.join(page_id.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(_) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						match f.write([0_u8, ..4 * 1024]) {
							Ok(_) => (),
							Err(e) => fail!("writing page failed: {}", e),
						}
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}", e),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	fn load_page(&mut self, page_id: u64) {
		if self.entries.len() == self.size {
			self.evict_page();
		}

		let mut file_handle = self.open_or_create(page_id);
		//let content = match file_handle.read_exact(4*1024) {
		let content = match file_handle.read_exact(10) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, page_id: page_id};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(page_id, entry);
	}

	fn evict_page(&mut self) {
		let random_key = {
			let mut iter = self.entries.keys();
			sample(&mut iter).map(|v| v.clone())
		};

		match random_key {
			None => false,
			Some(key) => self.entries.remove(&key),
		};
	}

	pub fn fix_page(&mut self, page_id: u64) -> Option<Arc<RWLock<BufferFrame>>> {
		if !self.entries.contains_key(&page_id) {
			self.load_page(page_id);
		}
		let entry = self.entries.get(&page_id);
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfix_page(&mut self, frame: Arc<RWLock<BufferFrame>>, is_dirty: bool) {
		if !is_dirty {
			return;
		}
		let frame = frame.read();
		println!("writing back {}", frame.page_id);
		self.write_page(frame.page_id, frame.get_data());
	}

	fn write_page(&mut self, page_id: u64, data: &[u8]) {
		let file_path = self.path.join(page_id.to_str());
		let mut handle = match File::open_mode(&file_path, Open, Write) {
			Ok(handle) => handle,
			Err(e) => fail!("Opening file for writing failed: {}", e),
		};

		match handle.write(data) {
			Ok(_) => (),
			Err(e) => fail!("Writing to file failed: {}", e),
		};
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

fn sample<'a, T, I:Iterator<T>>(from: &'a mut I) -> Option<T> {
	let from: ~[T] = from.collect();
	let l = from.len();
	if l == 0 {
		return None;
	}
	let index = randrange(l);
	Some(from[index])
}

fn randrange<X: SampleRange + Ord + Zero>(high: X) -> X {
	let between: Range<X> = Range::new(Zero::zero(), high);
	let mut rng = rand::task_rng();
	between.ind_sample(&mut rng)
}

#[test]
fn test_create() {
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};

	let mut bm = BufferManager::new(16, dir.path().clone());
	let pageref = match bm.fix_page(42) {
		Some(p) => p,
		None => fail!("Getting page failed"),
	};
	{
		let mut page = pageref.write();
		let data = page.get_mut_data();
		data[0] = 42;
		//println!("data: {}", Vec::from_slice(data));
	}
	bm.unfix_page(pageref, true);
	fail!("always");
}

#[test]
fn test_threads() {
	use rand::random;
	use std::task::spawn;

	let pages_in_ram = 1;
	let pages_on_disk: u64 = 20;
	let thread_count = 3;
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let p = dir.path();
	let p = Path::new(".");

	let mut buffermanager = BufferManager::new(pages_in_ram, p.clone());

	for i in range(0, pages_on_disk) {
		let bf = match buffermanager.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page {}", i),
		};
		{
			let mut lock = bf.write();
			lock.get_mut_data()[0] = 0;
		}
		buffermanager.unfix_page(bf, true);
	}
	let bm = Arc::new(RWLock::new(buffermanager));

	// start read/write threads
	let mut rw_threads: Vec<Future<int>> = Vec::new();
	for _ in range(0, thread_count) {
		let bm = bm.clone();
		rw_threads.push(Future::spawn(proc() {
			let is_write = random::<bool>();
			println!("Creating new {} task",
				if is_write {"write"} else {"read"});
			let page_number = randrange(pages_on_disk);
			let mut bm = bm.write();
			if is_write {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Cound't fix page"),
				};
				{
					println!("Wrote to page");
					let mut lock = bf.write();
					let data = lock.get_mut_data();
					data[0] = data[0] + 1;
					println!("data: {}", Vec::from_slice(data));
				}
				bm.unfix_page(bf, is_write);
			} else {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Cound't fix page"),
				};
				bm.unfix_page(bf, is_write);
			}
			// return whether we wrote (1) or read (0) as future
			if is_write {1} else {0}
		}));
	}

	// Rust does not have join, but we can wait on Futures which does the same
	let total_count = rw_threads.mut_iter().fold(0, |acc, val| acc + val.get());
	println!("total_count: {}", total_count);

	// TODO: add scan thread

	let mut bm = BufferManager::new(pages_in_ram, p.clone());
	let mut total_count_on_disk = 0;
	for i in range(0, pages_on_disk) {
		let bf = match bm.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page")
		};
		let value = {
			let lock = bf.read();
			let data = lock.get_data();
			data[0]
		};
		bm.unfix_page(bf, false);
		// cast up from u8 to int
		total_count_on_disk += value as int;
	}
	println!("Total count on disk: {}", total_count_on_disk);
	assert_eq!(total_count, total_count_on_disk);

	fail!("always");
}
<commit_msg>Implemented scan thread<commit_after>extern crate collections;
extern crate sync;
extern crate rand;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use std::num::Zero;
use std::comm::{Data, Empty, Disconnected};
use sync::{Arc, RWLock};
use sync::Future;
use rand::task_rng;
use rand::distributions::{IndependentSample, Range};
use rand::distributions::range::SampleRange;

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	path: Path,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

struct BufferFrame {
	page_id: u64,
	data: Vec<u8>,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint, path: Path) -> BufferManager {
		let h = HashMap::with_capacity(size);
		BufferManager {size: size, entries: h, path: path}
	}

	fn open_or_create(&self, page_id: u64) -> File {
		let file_path = self.path.join(page_id.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(_) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						match f.write([0_u8, ..4 * 1024]) {
							Ok(_) => (),
							Err(e) => fail!("writing page failed: {}", e),
						}
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}", e),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	fn load_page(&mut self, page_id: u64) {
		if self.entries.len() == self.size {
			self.evict_page();
		}

		let mut file_handle = self.open_or_create(page_id);
		//let content = match file_handle.read_exact(4*1024) {
		let content = match file_handle.read_exact(10) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, page_id: page_id};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(page_id, entry);
	}

	fn evict_page(&mut self) {
		let random_key = {
			let mut iter = self.entries.keys();
			sample(&mut iter).map(|v| v.clone())
		};

		match random_key {
			None => false,
			Some(key) => self.entries.remove(&key),
		};
	}

	pub fn fix_page(&mut self, page_id: u64) -> Option<Arc<RWLock<BufferFrame>>> {
		if !self.entries.contains_key(&page_id) {
			self.load_page(page_id);
		}
		let entry = self.entries.get(&page_id);
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfix_page(&mut self, frame: Arc<RWLock<BufferFrame>>, is_dirty: bool) {
		if !is_dirty {
			return;
		}
		let frame = frame.read();
		println!("writing back {}", frame.page_id);
		self.write_page(frame.page_id, frame.get_data());
	}

	fn write_page(&mut self, page_id: u64, data: &[u8]) {
		let file_path = self.path.join(page_id.to_str());
		let mut handle = match File::open_mode(&file_path, Open, Write) {
			Ok(handle) => handle,
			Err(e) => fail!("Opening file for writing failed: {}", e),
		};

		match handle.write(data) {
			Ok(_) => (),
			Err(e) => fail!("Writing to file failed: {}", e),
		};
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

fn sample<'a, T, I:Iterator<T>>(from: &'a mut I) -> Option<T> {
	let from: ~[T] = from.collect();
	let l = from.len();
	if l == 0 {
		return None;
	}
	let index = randrange(l);
	Some(from[index])
}

fn randrange<X: SampleRange + Ord + Zero>(high: X) -> X {
	let between: Range<X> = Range::new(Zero::zero(), high);
	let mut rng = rand::task_rng();
	between.ind_sample(&mut rng)
}

#[test]
fn test_create() {
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};

	let mut bm = BufferManager::new(16, dir.path().clone());
	let pageref = match bm.fix_page(42) {
		Some(p) => p,
		None => fail!("Getting page failed"),
	};
	{
		let mut page = pageref.write();
		let data = page.get_mut_data();
		data[0] = 42;
		//println!("data: {}", Vec::from_slice(data));
	}
	bm.unfix_page(pageref, true);
	fail!("always");
}

#[test]
fn test_threads() {
	use rand::random;
	use std::task::spawn;

	let pages_in_ram = 1;
	let pages_on_disk: u64 = 20;
	let thread_count = 3;
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let p = dir.path();
	let p = Path::new(".");

	let mut buffermanager = BufferManager::new(pages_in_ram, p.clone());

	for i in range(0, pages_on_disk) {
		let bf = match buffermanager.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page {}", i),
		};
		{
			let mut lock = bf.write();
			lock.get_mut_data()[0] = 0;
		}
		buffermanager.unfix_page(bf, true);
	}
	let bm = Arc::new(RWLock::new(buffermanager));

	// start scan thread
	let (tx, rx) = channel();
	let bm_scan = bm.clone();
	let mut scan = Future::spawn(proc() {
		let mut counters = Vec::from_elem(pages_on_disk as uint, 0_u8);
		loop {
			println!("Running scan thread...");
			match rx.try_recv() {
				Empty => {
					let page_number = randrange(pages_on_disk);
					let mut bm = bm_scan.write();
					let bf = match bm.fix_page(page_number) {
						Some(frame) => frame,
						None => fail!("Couldn't scan/fix page"),
					};
					let current_val = {
						let lock = bf.read();
						lock.get_data()[0]
					};
					bm.unfix_page(bf, false);
					bm.downgrade();
					// check if the value is going up
					assert!(&current_val >= counters.get(page_number as uint));
					// set to the new value
					let v = counters.get_mut(page_number as uint);
					*v = current_val;

				},
				/*
				 * terminate on both disconnect and when any kind of
				 * data arrives
				 */
				Disconnected => break,
				Data(_) => break,
			};
		}
	});

	// start read/write threads
	let mut rw_threads: Vec<Future<int>> = Vec::new();
	for _ in range(0, thread_count) {
		let bm = bm.clone();
		rw_threads.push(Future::spawn(proc() {
			let is_write = random::<bool>();
			println!("Creating new {} task",
				if is_write {"write"} else {"read"});
			let page_number = randrange(pages_on_disk);
			let mut bm = bm.write();
			if is_write {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Couldn't fix page"),
				};
				{
					println!("Wrote to page");
					let mut lock = bf.write();
					let data = lock.get_mut_data();
					data[0] = data[0] + 1;
					println!("data: {}", Vec::from_slice(data));
				}
				bm.unfix_page(bf, is_write);
			} else {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Couldn't fix page"),
				};
				bm.unfix_page(bf, is_write);
			}
			// return whether we wrote (1) or read (0) as future
			if is_write {1} else {0}
		}));
	}

	// Rust does not have join, but we can wait on Futures which does the same
	let total_count = rw_threads.mut_iter().fold(0, |acc, val| acc + val.get());
	println!("total_count: {}", total_count);

	// terminate the scan thread and wait until it has completed
	tx.send("terminate");
	scan.get();

	// re-open the pages and check whether all numbers got saved
	let mut bm = BufferManager::new(pages_in_ram, p.clone());
	let mut total_count_on_disk = 0;
	for i in range(0, pages_on_disk) {
		let bf = match bm.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page")
		};
		let value = {
			let lock = bf.read();
			let data = lock.get_data();
			data[0]
		};
		bm.unfix_page(bf, false);
		// cast up from u8 to int
		total_count_on_disk += value as int;
	}
	println!("Total count on disk: {}", total_count_on_disk);
	assert_eq!(total_count, total_count_on_disk);

	fail!("always");
}
<|endoftext|>


<commit_before>// ShortURL (https://github.com/delight-im/ShortURL)
// Copyright (c) delight.im (https://www.delight.im/), andra.xyz (http://andra.xyz/)
// Licensed under the MIT License (https://opensource.org/licenses/MIT)

/// # ShortURL
/// Bijective conversion between natural numbers (IDs) (`usize`) and short strings (`String`)
///
/// short_url::encode(usize) takes an ID and turns it into a short string
/// short_url::decode(String) takes a short string and turns it into an ID
///
/// ## Features
/// * large alphabet (51 chars) and thus very short resulting strings
/// * proof against offensive words (removed 'a', 'e', 'i', 'o' and 'u')
/// * unambiguous (removed 'I', 'l', '1', 'O' and '0')
///
/// ## Example
/// * 123456789 <=> pgK8p

mod short_url {

	static ALPHABET: &str = "23456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ-_";
	static BASE: usize = 51;

	pub fn encode(mut id: usize) -> String {
		let mut string: String = format!("");
		while id > 0 {
			string.push_str(&ALPHABET[(id % BASE)..(id % BASE + 1)]);
			id = id / BASE;
		}
		string.chars().rev().collect()
	}

	pub fn decode(string: String) -> usize {
		let mut number: usize = 0;
		for c in string.chars() {
			number = number * BASE + ALPHABET.find(c).unwrap();
		}
		number
	}

}
<commit_msg>Use static lifetime in statics before Rust 1.16 for compatibility<commit_after>// ShortURL (https://github.com/delight-im/ShortURL)
// Copyright (c) delight.im (https://www.delight.im/), andra.xyz (http://andra.xyz/)
// Licensed under the MIT License (https://opensource.org/licenses/MIT)

/// # ShortURL
/// Bijective conversion between natural numbers (IDs) (`usize`) and short strings (`String`)
///
/// short_url::encode(usize) takes an ID and turns it into a short string
/// short_url::decode(String) takes a short string and turns it into an ID
///
/// ## Features
/// * large alphabet (51 chars) and thus very short resulting strings
/// * proof against offensive words (removed 'a', 'e', 'i', 'o' and 'u')
/// * unambiguous (removed 'I', 'l', '1', 'O' and '0')
///
/// ## Example
/// * 123456789 <=> pgK8p

mod short_url {

	static ALPHABET: &'static str = "23456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ-_";
	static BASE: usize = 51;

	pub fn encode(mut id: usize) -> String {
		let mut string: String = format!("");
		while id > 0 {
			string.push_str(&ALPHABET[(id % BASE)..(id % BASE + 1)]);
			id = id / BASE;
		}
		string.chars().rev().collect()
	}

	pub fn decode(string: String) -> usize {
		let mut number: usize = 0;
		for c in string.chars() {
			number = number * BASE + ALPHABET.find(c).unwrap();
		}
		number
	}

}
<|endoftext|>


<commit_before>#[link(name = "simplify", vers = "0.0.5")];
extern mod extra;
use extra::json::*;
use extra::treemap::TreeSet;
use std::vec;
pub struct Point {
	x: float,
	y: float
}
impl ToJson for Point {
    fn to_json(&self) -> Json { List(~[self.x.to_json(),self.y.to_json()]) }
}
impl Eq for Point {
    fn eq(&self, other: &Point) -> bool { other.x == self.x && other.y == self.y }
    fn ne(&self, other: &Point) -> bool { other.x != self.x || other.y != self.y }
}
impl Sub<Point,Point> for Point {
    #[inline]
    fn sub(&self, other: &Point) -> Point { Point {x:self.x-other.x,y:self.y-other.y} }
}
impl Add<Point,Point> for Point {
    #[inline]
    fn add(&self, other: &Point) -> Point { Point { x:self.x+other.x,y:self.y+other.y }}
}
impl Mul<Point,Point> for Point {
    #[inline]
    fn mul(&self, other: &Point) -> Point { Point { x:self.x*other.x,y:self.y*other.y }}
}

impl Point {
    fn sum(self) -> float { self.x+self.y }
    fn sqsum(self) -> float { self.x * self.x + self.y * self.y}
    fn sub(self, other: float) -> Point { Point { x:self.x - other , y:self.y - other }}
    fn mul(self, other: float) -> Point { Point { x:self.x * other, y:self.y * other }}
    fn add(self, other: float) -> Point {  Point {x:self.x + other, y:self.y + other }}
}
struct Pair(uint,uint);
enum Opt<T,U>{
    OK(T,T,U),
    NotOK
}
impl Pair {
fn first(self)-> uint {
        match self {
            Pair(l,_)=>l
        }
    }
    fn last(self)-> uint {
        match self {
            Pair(_,l)=>l
        }
    }
}
fn calcStuff(p:Point,p1:Point,d1:Point)->float {
	let top : float = ((p - p1) * d1).sum();
	let bottom : float =  d1.sqsum();
	match bottom{
		0.0=>0.0,
		_=>top/bottom
	}
}
fn getSquareSegmentDistance(p: Point, p1: Point, p2: Point) -> float {
	let d1 : Point = p2-p1;
	let d2 : Point = match d1{
		Point {x:0.0,_} | Point {y:0.0,_}=> {p1}
		_=>{
			let t : float = calcStuff(p,p1,d1);
			match t {
				tt if tt>1.0=>p2,
				tt if tt>0.0=> d1.mul(tt)+p1,
				_=>p1
			}
		}
	};
	let d4 : Point = p-d2;
	d4.sqsum()
}

fn simplifyRadialDistance(points:~[Point], sqTolerance:float) -> ~[Point]{
    let mut it = points.iter();
    it.next();
	let mut prevPoint : Point = points[0u];
	let mut newPoints : ~[Point] = ~[prevPoint];
	let &last = points.last();
	for &point in it{
	    if (point - prevPoint).sqsum() > sqTolerance {
			newPoints.push(point);
			prevPoint = point;
		}
	}
	if (prevPoint!= last) {
		newPoints.push(last);
	}
	newPoints
}

fn simplifyDouglasPeucker(points : ~[Point], tolerance : float) -> ~[Point]{
	let len : uint = points.len();
	let mut markers = TreeSet::new();
	let mut stack : ~[Pair] = ~[];
	markers.insert(0u);
	markers.insert(len-1u);
	let mut first = 0u;
    let mut last = len-1u;
	loop{
	   let mut index : uint = 0;
		let mut maxSqDist : float = 0.0f;
		let mut i : uint = first + 1u;
		while (i < last) {

			let sqDist :float  = getSquareSegmentDistance(
				points[i],
				points[first],
				points[last]
			);
			if (sqDist > maxSqDist) {
				index = i;
				maxSqDist = sqDist;
			}
			i += 1;
		}
		if maxSqDist > tolerance {
			  markers.insert(index);
			    stack.push(Pair(first,index));
			    stack.push(Pair(index,last));
		}
			match stack.pop_opt() {
		    Some(Pair(f,l))=> {
		        first = f;
		        last = l;
		    }
		    None=>break
		};
        };
    vec::from_fn(markers.len(),|k| points[k])
}

pub fn simplify(points : ~[Point], sqTolerance : float, hq:bool) -> ~[Point]{
	let tolerance : float = sqTolerance*sqTolerance;
	let pts:~[Point]=match hq {
		true=>points,
		_=>simplifyRadialDistance(points,tolerance)
	};
	simplifyDouglasPeucker(pts,tolerance)
}
<commit_msg>pairs<commit_after>#[link(name = "simplify", vers = "0.0.5")];
extern mod extra;
use extra::json::*;
use extra::treemap::TreeSet;
use std::vec;
pub struct Point {
	x: float,
	y: float
}
impl ToJson for Point {
	fn to_json(&self) -> Json { List(~[self.x.to_json(),self.y.to_json()]) }
}
impl Eq for Point {
	fn eq(&self, other: &Point) -> bool { other.x == self.x && other.y == self.y }
	fn ne(&self, other: &Point) -> bool { other.x != self.x || other.y != self.y }
}
impl Sub<Point,Point> for Point {
	#[inline]
	fn sub(&self, other: &Point) -> Point { Point {x:self.x-other.x,y:self.y-other.y} }
}
impl Add<Point,Point> for Point {
	#[inline]
	fn add(&self, other: &Point) -> Point { Point { x:self.x+other.x,y:self.y+other.y }}
}
impl Mul<Point,Point> for Point {
	#[inline]
	fn mul(&self, other: &Point) -> Point { Point { x:self.x*other.x,y:self.y*other.y }}
}

impl Point {
	fn sum(self) -> float { self.x+self.y }
	fn sqsum(self) -> float { self.x * self.x + self.y * self.y}
	fn sub(self, other: float) -> Point { Point { x:self.x - other , y:self.y - other }}
	fn mul(self, other: float) -> Point { Point { x:self.x * other, y:self.y * other }}
	fn add(self, other: float) -> Point {  Point {x:self.x + other, y:self.y + other }}
}
struct Pair(uint,uint);
enum Opt<T,U>{
	OK(T,T,U),
	NotOK
}
impl Pair {
fn first(self)-> uint {
		match self {
			Pair(l,_)=>l
		}
	}
	fn last(self)-> uint {
		match self {
			Pair(_,l)=>l
		}
	}
}
fn calcStuff(p:Point,p1:Point,d1:Point)->float {
	let top : float = ((p - p1) * d1).sum();
	let bottom : float =  d1.sqsum();
	match bottom{
		0.0=>0.0,
		_=>top/bottom
	}
}
fn getSquareSegmentDistance(p: Point, p1: Point, p2: Point) -> float {
	let d1 : Point = p2-p1;
	let d2 : Point = match d1{
		Point {x:0.0,_} | Point {y:0.0,_}=> {p1}
		_=>{
			let t : float = calcStuff(p,p1,d1);
			match t {
				tt if tt>1.0=>p2,
				tt if tt>0.0=> d1.mul(tt)+p1,
				_=>p1
			}
		}
	};
	let d4 : Point = p-d2;
	d4.sqsum()
}

fn simplifyRadialDistance(points:~[Point], sqTolerance:float) -> ~[Point]{
	let mut it = points.iter();
	it.next();
	let mut prevPoint : Point = points[0u];
	let mut newPoints : ~[Point] = ~[prevPoint];
	let &last = points.last();
	for &point in it{
		if (point - prevPoint).sqsum() > sqTolerance {
			newPoints.push(point);
			prevPoint = point;
		}
	}
	if (prevPoint!= last) {
		newPoints.push(last);
	}
	newPoints
}

fn simplifyDouglasPeucker(points : ~[Point], tolerance : float) -> ~[Point]{
	let len : uint = points.len();
	let mut markers = TreeSet::new();
	let mut stack : ~[Pair] = ~[];
	markers.insert(0u);
	markers.insert(len-1u);
	let mut pair = Pair(0u,len-1u);
	loop{
		let first = pair.first();
		let last = pair.last();
		let mut index : uint = 0;
		let mut maxSqDist : float = 0.0f;
		let mut i : uint = first + 1u;
		while (i < last) {
			let sqDist :float  = getSquareSegmentDistance(
				points[i],
				points[first],
				points[last]
			);
			if (sqDist > maxSqDist) {
				index = i;
				maxSqDist = sqDist;
			}
			i += 1;
		}
		if maxSqDist > tolerance {
				markers.insert(index);
				stack.push(Pair(first,index));
				stack.push(Pair(index,last));
		}
		match stack.pop_opt() {
			Some(p)=>pair=p,
			None=>break
		};
	};
	vec::from_fn(markers.len(),|k| points[k])
}

pub fn simplify(points : ~[Point], sqTolerance : float, hq:bool) -> ~[Point]{
	let tolerance : float = sqTolerance*sqTolerance;
	let pts:~[Point]=match hq {
		true=>points,
		_=>simplifyRadialDistance(points,tolerance)
	};
	simplifyDouglasPeucker(pts,tolerance)
}
<|endoftext|>


<commit_before>//! This crate contains client-only components of Playform.

#![deny(missing_docs)]
#![deny(warnings)]

#![feature(plugin)]
#![feature(test)]
#![feature(type_ascription)]
#![feature(unboxed_closures)]

#![plugin(clippy)]

#![allow(mutex_atomic)]
#![allow(match_ref_pats)]
#![allow(match_same_arms)]
#![allow(similar_names)]
#![allow(too_many_arguments)]
#![allow(let_and_return)]

extern crate bincode;
extern crate cgmath;
extern crate common;
extern crate fnv;
extern crate gl;
extern crate image;
extern crate isosurface_extraction;
#[macro_use]
extern crate log;
extern crate libc;
extern crate num;
extern crate rand;
extern crate sdl2;
extern crate sdl2_sys;
extern crate stopwatch;
extern crate rustc_serialize;
extern crate test;
extern crate thread_scoped;
extern crate time;
extern crate voxel_data;
extern crate yaglw;

mod block_position;
mod camera;
mod client;
mod hud;
mod light;
mod load_terrain;
mod lod;
mod mob_buffers;
mod player_buffers;
mod process_event;
mod record_book;
mod render;
mod run;
mod server;
mod server_update;
mod shaders;
mod grass_buffers;
mod terrain_buffers;
mod terrain_mesh;
mod update_thread;
mod vertex;
mod view;
mod view_thread;
mod view_update;

pub use run::run;
<commit_msg>clippy warnings<commit_after>//! This crate contains client-only components of Playform.

#![deny(missing_docs)]
#![deny(warnings)]

#![feature(plugin)]
#![feature(test)]
#![feature(type_ascription)]
#![feature(unboxed_closures)]

#![plugin(clippy)]

#![allow(mutex_atomic)]
#![allow(match_ref_pats)]
#![allow(match_same_arms)]
#![allow(similar_names)]
#![allow(too_many_arguments)]
#![allow(let_and_return)]
#![allow(many_single_char_names)]

extern crate bincode;
extern crate cgmath;
extern crate common;
extern crate fnv;
extern crate gl;
extern crate image;
extern crate isosurface_extraction;
#[macro_use]
extern crate log;
extern crate libc;
extern crate num;
extern crate rand;
extern crate sdl2;
extern crate sdl2_sys;
extern crate stopwatch;
extern crate rustc_serialize;
extern crate test;
extern crate thread_scoped;
extern crate time;
extern crate voxel_data;
extern crate yaglw;

mod block_position;
mod camera;
mod client;
mod hud;
mod light;
mod load_terrain;
mod lod;
mod mob_buffers;
mod player_buffers;
mod process_event;
mod record_book;
mod render;
mod run;
mod server;
mod server_update;
mod shaders;
mod grass_buffers;
mod terrain_buffers;
mod terrain_mesh;
mod update_thread;
mod vertex;
mod view;
mod view_thread;
mod view_update;

pub use run::run;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use common::*;
use arena::*;
use layout;

pub struct ReaderOptions {
    traversalLimitInWords : u64,
    nestingLimit : uint
}

pub static DEFAULT_READER_OPTIONS : ReaderOptions =
    ReaderOptions { traversalLimitInWords : 8 * 1024 * 1024, nestingLimit : 64 };

pub struct MessageReader<'a> {
    segments : &'a [ &'a [Word]],
    options : ReaderOptions,
    arena : ReaderArena<'a>
}

type SegmentId = u32;

impl <'a> MessageReader<'a> {

    #[inline]
    pub fn get_options<'b>(&'b self) -> &'b ReaderOptions {
        return &self.options;
    }
}

impl <'a> MessageReader<'a> {
    pub fn get_root<T : layout::FromStructReader<'a>>(&self) -> T {
        unsafe {
            let segment : *SegmentReader<'a> = std::ptr::to_unsafe_ptr(&self.arena.segment0);

            let pointer_reader = layout::PointerReader::get_root::<'a>(
                segment, (*segment).get_start_ptr(), self.options.nestingLimit as int);

            let result : T = layout::FromStructReader::from_struct_reader(
                pointer_reader.get_struct::<'a>(std::ptr::null()));

            result
        }
    }
}

pub enum AllocationStrategy {
    FIXED_SIZE,
    GROW_HEURISTICALLY
}

pub static SUGGESTED_FIRST_SEGMENT_WORDS : uint = 1024;
pub static SUGGESTED_ALLOCATION_STRATEGY : AllocationStrategy = GROW_HEURISTICALLY;

pub struct MessageBuilder<'a> {
    nextSize : uint,
    allocation_strategy : AllocationStrategy,
    arena : ~BuilderArena<'a>,
    segments : ~[~[Word]]
}

impl <'a>MessageBuilder<'a> {

    // TODO: maybe when Rust issue #5121 is fixed we can safely get away with not passing
    //  a closure here.
    pub fn new<T>(firstSegmentWords : uint,
                  allocationStrategy : AllocationStrategy,
                  cont : |&mut MessageBuilder| -> T) -> T {

        let mut segments = ~[];
        segments.push(allocate_zeroed_words(firstSegmentWords));
        let mut arena = ~BuilderArena {
            message : std::ptr::mut_null(),
            segment0 : SegmentBuilder {
                reader : SegmentReader {
                    ptr : unsafe { segments[0].unsafe_ref(0) },
                    size : segments[0].len(),
                    arena : Null },
                id : 0,
                pos : unsafe { segments[0].unsafe_mut_ref(0) }
            },
            more_segments : None };

        let arena_ptr = std::ptr::to_mut_unsafe_ptr(arena);
        arena.segment0.reader.arena = BuilderArenaPtr(arena_ptr);

        let mut result = ~MessageBuilder {
            nextSize : firstSegmentWords,
            allocation_strategy : allocationStrategy,
            segments : segments,
            arena : arena
        };

        cont(result)
    }

    pub fn new_default<T>(cont : |&mut MessageBuilder| -> T) -> T {
        MessageBuilder::new(SUGGESTED_FIRST_SEGMENT_WORDS, SUGGESTED_ALLOCATION_STRATEGY, cont)
    }

    pub fn allocate_segment(&mut self, minimumSize : WordCount) -> (*mut SegmentBuilder<'a>, *mut Word) {
        let size = std::cmp::max(minimumSize, self.nextSize);
        let mut id = self.segments.len() as u32;
        let mut new_words = allocate_zeroed_words(size);
        let ptr = unsafe { new_words.unsafe_mut_ref(0) };
        self.segments.push(new_words);
        let mut new_builder = ~SegmentBuilder::new(std::ptr::to_mut_unsafe_ptr(self.arena), id, ptr, size);
        let result_ptr = std::ptr::to_mut_unsafe_ptr(&mut new_builder);
        match self.arena.more_segments {
            None =>
                self.arena.more_segments = Some(~[new_builder]),
            Some(ref mut msegs) => {
                msegs.push(new_builder);
            }
        }

        match self.allocation_strategy {
            GROW_HEURISTICALLY => { self.nextSize += size; }
            _ => { }
        }
        fail!()
        //result_ptr
    }

    pub fn get_segments_for_output<T>(&self, cont : |&[&[Word]]| -> T) -> T {
        self.arena.get_segments_for_output(cont)
    }
}

impl <'a>MessageBuilder<'a> {
    // Note: This type signature ought to prevent a MessageBuilder
    // from being initted twice simultaneously. It currently does not
    // fulfill that goal, perhaps due to Rust issue #5121.
    pub fn init_root<T : layout::HasStructSize + layout::FromStructBuilder<'a>>(&'a mut self) -> T {
        // Rolled in this stuff form getRootSegment.
        let rootSegment = unsafe { std::ptr::to_mut_unsafe_ptr(&mut self.arena.segment0) };

        match self.arena.segment0.allocate(WORDS_PER_POINTER) {
            None => {fail!("could not allocate root pointer") }
            Some(location) => {
                //assert!(location == 0,
                //        "First allocated word of new segment was not at offset 0");

                let pb = layout::PointerBuilder::get_root(rootSegment, location);

                return layout::FromStructBuilder::from_struct_builder(
                    pb.init_struct(layout::HasStructSize::struct_size(None::<T>)));
            }
        }
    }

}
<commit_msg>not done yet, but libcapnp compiles<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use common::*;
use arena::*;
use layout;

pub struct ReaderOptions {
    traversalLimitInWords : u64,
    nestingLimit : uint
}

pub static DEFAULT_READER_OPTIONS : ReaderOptions =
    ReaderOptions { traversalLimitInWords : 8 * 1024 * 1024, nestingLimit : 64 };

pub struct MessageReader<'a> {
    segments : &'a [ &'a [Word]],
    options : ReaderOptions,
    arena : ReaderArena<'a>
}

type SegmentId = u32;

impl <'a> MessageReader<'a> {

    #[inline]
    pub fn get_options<'b>(&'b self) -> &'b ReaderOptions {
        return &self.options;
    }
}

impl <'a> MessageReader<'a> {
    pub fn get_root<T : layout::FromStructReader<'a>>(&self) -> T {
        unsafe {
            let segment : *SegmentReader<'a> = std::ptr::to_unsafe_ptr(&self.arena.segment0);

            let pointer_reader = layout::PointerReader::get_root::<'a>(
                segment, (*segment).get_start_ptr(), self.options.nestingLimit as int);

            let result : T = layout::FromStructReader::from_struct_reader(
                pointer_reader.get_struct::<'a>(std::ptr::null()));

            result
        }
    }
}

pub enum AllocationStrategy {
    FIXED_SIZE,
    GROW_HEURISTICALLY
}

pub static SUGGESTED_FIRST_SEGMENT_WORDS : uint = 1024;
pub static SUGGESTED_ALLOCATION_STRATEGY : AllocationStrategy = GROW_HEURISTICALLY;

pub struct MessageBuilder<'a> {
    nextSize : uint,
    allocation_strategy : AllocationStrategy,
    arena : ~BuilderArena<'a>,
    segments : ~[~[Word]]
}

impl <'a>MessageBuilder<'a> {

    // TODO: maybe when Rust issue #5121 is fixed we can safely get away with not passing
    //  a closure here.
    pub fn new<T>(firstSegmentWords : uint,
                  allocationStrategy : AllocationStrategy,
                  cont : |&mut MessageBuilder| -> T) -> T {

        let mut segments = ~[];
        segments.push(allocate_zeroed_words(firstSegmentWords));
        let mut arena = ~BuilderArena {
            message : std::ptr::mut_null(),
            segment0 : SegmentBuilder {
                reader : SegmentReader {
                    ptr : unsafe { segments[0].unsafe_ref(0) },
                    size : segments[0].len(),
                    arena : Null },
                id : 0,
                pos : unsafe { segments[0].unsafe_mut_ref(0) }
            },
            more_segments : None };

        let arena_ptr = std::ptr::to_mut_unsafe_ptr(arena);
        arena.segment0.reader.arena = BuilderArenaPtr(arena_ptr);

        let mut result = ~MessageBuilder {
            nextSize : firstSegmentWords,
            allocation_strategy : allocationStrategy,
            segments : segments,
            arena : arena
        };

        cont(result)
    }

    pub fn new_default<T>(cont : |&mut MessageBuilder| -> T) -> T {
        MessageBuilder::new(SUGGESTED_FIRST_SEGMENT_WORDS, SUGGESTED_ALLOCATION_STRATEGY, cont)
    }

    pub fn allocate_segment(&mut self, minimumSize : WordCount) -> (*mut SegmentBuilder<'a>, *mut Word) {
        let size = std::cmp::max(minimumSize, self.nextSize);
        let mut id = self.segments.len() as u32;
        let mut new_words = allocate_zeroed_words(size);
        let ptr = unsafe { new_words.unsafe_mut_ref(0) };
        self.segments.push(new_words);
        let mut new_builder = ~SegmentBuilder::new(std::ptr::to_mut_unsafe_ptr(self.arena), id, ptr, size);
        let result_ptr = std::ptr::to_mut_unsafe_ptr(&mut new_builder);
        match self.arena.more_segments {
            None =>
                self.arena.more_segments = Some(~[new_builder]),
            Some(ref mut msegs) => {
                msegs.push(new_builder);
            }
        }

        match self.allocation_strategy {
            GROW_HEURISTICALLY => { self.nextSize += size; }
            _ => { }
        }
        fail!()
        //result_ptr
    }

    pub fn get_segments_for_output<T>(&self, cont : |&[&[Word]]| -> T) -> T {
        self.arena.get_segments_for_output(cont)
    }
}

impl <'a>MessageBuilder<'a> {
    // Note: This type signature ought to prevent a MessageBuilder
    // from being initted twice simultaneously. It currently does not
    // fulfill that goal, perhaps due to Rust issue #5121.
    pub fn init_root<T : layout::HasStructSize + layout::FromStructBuilder<'a>>(&mut self) -> T {
        // Rolled in this stuff form getRootSegment.
        let rootSegment = unsafe { std::ptr::to_mut_unsafe_ptr(&mut self.arena.segment0) };

        match self.arena.segment0.allocate(WORDS_PER_POINTER) {
            None => {fail!("could not allocate root pointer") }
            Some(location) => {
                //assert!(location == 0,
                //        "First allocated word of new segment was not at offset 0");

                let pb = layout::PointerBuilder::get_root(rootSegment, location);

                return layout::FromStructBuilder::from_struct_builder(
                    pb.init_struct(layout::HasStructSize::struct_size(None::<T>)));
            }
        }
    }

}
<|endoftext|>