<commit_before>use std::string::String as StdString;

use Variants;
use primitives as prim;
use api::{generic, Generic, Getable, Array, MaybeError, primitive, WithVM};
use api::generic::A;
use gc::{Gc, Traverseable, DataDef, WriteOnly};
use vm::{Thread, DataStruct, VMInt, Status, Value, Result};

fn array_length(array: Array<generic::A>) -> VMInt {
    array.len() as VMInt
}

fn array_index<'vm>(array: Array<'vm, Generic<generic::A>>,
                    index: VMInt)
                    -> MaybeError<Generic<generic::A>, String> {
    match array.get(index) {
        Some(value) => MaybeError::Ok(value),
        None => MaybeError::Err(format!("{} is out of range", index)),
    }
}

fn array_append<'vm>(lhs: Array<'vm, Generic<generic::A>>,
                     rhs: Array<'vm, Generic<generic::A>>)
                     -> Array<'vm, Generic<generic::A>> {
    struct Append<'b> {
        lhs: &'b [Value],
        rhs: &'b [Value],
    }

    impl<'b> Traverseable for Append<'b> {
        fn traverse(&self, gc: &mut Gc) {
            self.lhs.traverse(gc);
            self.rhs.traverse(gc);
        }
    }

    unsafe impl<'b> DataDef for Append<'b> {
        type Value = DataStruct;
        fn size(&self) -> usize {
            use std::mem::size_of;
            let len = self.lhs.len() + self.rhs.len();
            size_of::<usize>() + ::array::Array::<Value>::size_of(len)
        }
        fn initialize<'w>(self, mut result: WriteOnly<'w, DataStruct>) -> &'w mut DataStruct {
            unsafe {
                let result = &mut *result.as_mut_ptr();
                result.tag = 0;
                result.fields.initialize(self.lhs.iter().chain(self.rhs.iter()).cloned());
                result
            }
        }
    }
    let vm = lhs.vm();
    let value = {
        let stack = vm.current_frame();
        vm.alloc(&stack.stack,
                 Append {
                     lhs: &lhs.fields,
                     rhs: &rhs.fields,
                 })
    };
    Getable::from_value(lhs.vm(), Variants(&Value::Data(value))).expect("Array")
}

fn string_append(lhs: WithVM<&str>, rhs: &str) -> String {
    use array::Str;
    struct StrAppend<'b> {
        lhs: &'b str,
        rhs: &'b str,
    }

    impl<'b> Traverseable for StrAppend<'b> {}

    unsafe impl<'b> DataDef for StrAppend<'b> {
        type Value = Str;
        fn size(&self) -> usize {
            ::array::Str::size_of(self.lhs.len() + self.rhs.len())
        }
        fn initialize<'w>(self, mut result: WriteOnly<'w, Str>) -> &'w mut Str {
            unsafe {
                let result = &mut *result.as_mut_ptr();
                {
                    let array = Str::as_mut_array(result);
                    ::array::Array::set_len(array, self.lhs.len() + self.rhs.len());
                    let (l, r) = array.split_at_mut(self.lhs.len());
                    l.clone_from_slice(self.lhs.as_bytes());
                    r.clone_from_slice(self.rhs.as_bytes());
                }
                result
            }
        }
    }

    let vm = lhs.vm;
    let lhs = lhs.value;
    let value = {
        let stack = vm.current_frame();
        vm.alloc(&stack.stack,
                 StrAppend {
                     lhs: lhs,
                     rhs: rhs,
                 })
    };
    Getable::from_value(vm, Variants(&Value::String(value))).expect("Array")
}

fn string_slice(s: &str, start: VMInt, end: VMInt) -> &str {
    &s[start as usize..end as usize]
}

fn trace(a: Generic<A>) {
    println!("{:?}", a.0);
}

fn show_int(i: VMInt) -> String {
    format!("{}", i)
}

fn show_float(f: f64) -> String {
    format!("{}", f)
}

fn show_char(c: char) -> String {
    format!("{}", c)
}

fn error(_: &Thread) -> Status {
    // We expect a string as an argument to this function but we only return Status::Error
    // and let the caller take care of printing the message
    Status::Error
}

fn f1<A, R>(f: fn(A) -> R) -> fn(A) -> R {
    f
}
fn f2<A, B, R>(f: fn(A, B) -> R) -> fn(A, B) -> R {
    f
}
fn f3<A, B, C, R>(f: fn(A, B, C) -> R) -> fn(A, B, C) -> R {
    f
}

pub fn load(vm: &Thread) -> Result<()> {
    use std::f64;
    try!(vm.define_global("float",
                          record!(
        digits => f64::DIGITS,
        epsilon => f64::EPSILON,
        infinity => f64::INFINITY,
        mantissa_digits => f64::MANTISSA_DIGITS,
        max_ => f64::MAX,
        max_10_exp => f64::MAX_10_EXP,
        max_exp => f64::MAX_EXP,
        min_ => f64::MIN,
        min_10_exp => f64::MIN_10_EXP,
        min_exp => f64::MIN_EXP,
        min_positive => f64::MIN_POSITIVE,
        nan => f64::NAN,
        neg_infinity => f64::NEG_INFINITY,
        e => f64::consts::E,
        pi => f64::consts::PI,
        radix => f64::RADIX,
        is_nan => f1(f64::is_nan),
        is_infinite => f1(f64::is_infinite),
        is_finite => f1(f64::is_finite),
        is_normal => f1(f64::is_normal),
        floor => f1(f64::floor),
        ceil => f1(f64::ceil),
        round => f1(f64::round),
        trunc => f1(f64::trunc),
        fract => f1(f64::fract),
        abs => f1(f64::abs),
        signum => f1(f64::signum),
        is_sign_positive => f1(f64::is_sign_positive),
        is_sign_negative => f1(f64::is_sign_negative),
        mul_add => f3(f64::mul_add),
        recip => f1(f64::recip),
        powi => f2(f64::powi),
        powf => f2(f64::powf),
        sqrt => f1(f64::sqrt),
        exp => f1(f64::exp),
        exp2 => f1(f64::exp2),
        ln => f1(f64::ln),
        log2 => f1(f64::log2),
        log10 => f1(f64::log10),
        to_degrees => f1(f64::to_degrees),
        to_radians => f1(f64::to_radians),
        max => f2(f64::max),
        min => f2(f64::min),
        abs_sub => f2(f64::abs_sub),
        cbrt => f1(f64::cbrt),
        hypot => f2(f64::hypot),
        sin => f1(f64::sin),
        cos => f1(f64::cos),
        tan => f1(f64::tan),
        acos => f1(f64::acos),
        atan => f1(f64::atan),
        atan2 => f2(f64::atan2),
        sin_cos => f1(f64::sin_cos),
        exp_m1 => f1(f64::exp_m1),
        ln_1p => f1(f64::ln_1p),
        sinh => f1(f64::sinh),
        cosh => f1(f64::cosh),
        tanh => f1(f64::tanh),
        acosh => f1(f64::acosh),
        atanh => f1(f64::atanh)
    )));
    try!(vm.define_global("int",
                          record!(
        min_value => VMInt::min_value(),
        max_value => VMInt::max_value(),
        count_ones => f1(VMInt::count_ones),
        rotate_left => f2(VMInt::rotate_left),
        rotate_right => f2(VMInt::rotate_right),
        swap_bytes => f1(VMInt::swap_bytes),
        from_be => f1(VMInt::from_be),
        from_le => f1(VMInt::from_le),
        to_be => f1(VMInt::to_be),
        to_le => f1(VMInt::to_le),
        pow => f2(VMInt::pow),
        abs => f1(VMInt::abs),
        signum => f1(VMInt::signum),
        is_positive => f1(VMInt::is_positive),
        is_negative => f1(VMInt::is_negative)
    )));
    try!(vm.define_global("array",
                          record!(
        length => f1(prim::array_length),
        index => f2(prim::array_index),
        append => f2(prim::array_append)
    )));

    try!(vm.define_global("string_prim",
                          record!(
        length => f1(str::len),
        is_empty => f1(str::is_empty),
        split_at => f2(str::split_at),
        find => f2(str::find::<&str>),
        rfind => f2(str::rfind::<&str>),
        trim => f1(str::trim),
        trim_left => f1(str::trim_left),
        trim_right => f1(str::trim_right),
        compare => f2(str::cmp),
        append => f2(prim::string_append),
        eq => f2(<str as PartialEq>::eq),
        slice => f3(prim::string_slice)
    )));
    try!(vm.define_global("prim",
                          record!(
        show_Int => f1(prim::show_int),
        show_Float => f1(prim::show_float),
        show_Char => f1(prim::show_char)
    )));

    try!(vm.define_global("#error",
                          primitive::<fn(StdString) -> A>("#error", prim::error)));
    try!(vm.define_global("error",
                          primitive::<fn(StdString) -> A>("error", prim::error)));
    try!(vm.define_global("trace", f1(prim::trace)));

    try!(::lazy::load(vm));
    try!(::reference::load(vm));
    Ok(())
}
<commit_msg>feat(vm): Add a char module<commit_after>use std::string::String as StdString;

use Variants;
use primitives as prim;
use api::{generic, Generic, Getable, Array, MaybeError, primitive, WithVM};
use api::generic::A;
use gc::{Gc, Traverseable, DataDef, WriteOnly};
use vm::{Thread, DataStruct, VMInt, Status, Value, Result};

fn array_length(array: Array<generic::A>) -> VMInt {
    array.len() as VMInt
}

fn array_index<'vm>(array: Array<'vm, Generic<generic::A>>,
                    index: VMInt)
                    -> MaybeError<Generic<generic::A>, String> {
    match array.get(index) {
        Some(value) => MaybeError::Ok(value),
        None => MaybeError::Err(format!("{} is out of range", index)),
    }
}

fn array_append<'vm>(lhs: Array<'vm, Generic<generic::A>>,
                     rhs: Array<'vm, Generic<generic::A>>)
                     -> Array<'vm, Generic<generic::A>> {
    struct Append<'b> {
        lhs: &'b [Value],
        rhs: &'b [Value],
    }

    impl<'b> Traverseable for Append<'b> {
        fn traverse(&self, gc: &mut Gc) {
            self.lhs.traverse(gc);
            self.rhs.traverse(gc);
        }
    }

    unsafe impl<'b> DataDef for Append<'b> {
        type Value = DataStruct;
        fn size(&self) -> usize {
            use std::mem::size_of;
            let len = self.lhs.len() + self.rhs.len();
            size_of::<usize>() + ::array::Array::<Value>::size_of(len)
        }
        fn initialize<'w>(self, mut result: WriteOnly<'w, DataStruct>) -> &'w mut DataStruct {
            unsafe {
                let result = &mut *result.as_mut_ptr();
                result.tag = 0;
                result.fields.initialize(self.lhs.iter().chain(self.rhs.iter()).cloned());
                result
            }
        }
    }
    let vm = lhs.vm();
    let value = {
        let stack = vm.current_frame();
        vm.alloc(&stack.stack,
                 Append {
                     lhs: &lhs.fields,
                     rhs: &rhs.fields,
                 })
    };
    Getable::from_value(lhs.vm(), Variants(&Value::Data(value))).expect("Array")
}

fn string_append(lhs: WithVM<&str>, rhs: &str) -> String {
    use array::Str;
    struct StrAppend<'b> {
        lhs: &'b str,
        rhs: &'b str,
    }

    impl<'b> Traverseable for StrAppend<'b> {}

    unsafe impl<'b> DataDef for StrAppend<'b> {
        type Value = Str;
        fn size(&self) -> usize {
            ::array::Str::size_of(self.lhs.len() + self.rhs.len())
        }
        fn initialize<'w>(self, mut result: WriteOnly<'w, Str>) -> &'w mut Str {
            unsafe {
                let result = &mut *result.as_mut_ptr();
                {
                    let array = Str::as_mut_array(result);
                    ::array::Array::set_len(array, self.lhs.len() + self.rhs.len());
                    let (l, r) = array.split_at_mut(self.lhs.len());
                    l.clone_from_slice(self.lhs.as_bytes());
                    r.clone_from_slice(self.rhs.as_bytes());
                }
                result
            }
        }
    }

    let vm = lhs.vm;
    let lhs = lhs.value;
    let value = {
        let stack = vm.current_frame();
        vm.alloc(&stack.stack,
                 StrAppend {
                     lhs: lhs,
                     rhs: rhs,
                 })
    };
    Getable::from_value(vm, Variants(&Value::String(value))).expect("Array")
}

fn string_slice(s: &str, start: VMInt, end: VMInt) -> &str {
    &s[start as usize..end as usize]
}

fn trace(a: Generic<A>) {
    println!("{:?}", a.0);
}

fn show_int(i: VMInt) -> String {
    format!("{}", i)
}

fn show_float(f: f64) -> String {
    format!("{}", f)
}

fn show_char(c: char) -> String {
    format!("{}", c)
}

fn error(_: &Thread) -> Status {
    // We expect a string as an argument to this function but we only return Status::Error
    // and let the caller take care of printing the message
    Status::Error
}

fn f1<A, R>(f: fn(A) -> R) -> fn(A) -> R {
    f
}
fn f2<A, B, R>(f: fn(A, B) -> R) -> fn(A, B) -> R {
    f
}
fn f3<A, B, C, R>(f: fn(A, B, C) -> R) -> fn(A, B, C) -> R {
    f
}

pub fn load(vm: &Thread) -> Result<()> {
    use std::f64;
    use std::char;
    try!(vm.define_global("float",
                          record!(
        digits => f64::DIGITS,
        epsilon => f64::EPSILON,
        infinity => f64::INFINITY,
        mantissa_digits => f64::MANTISSA_DIGITS,
        max_ => f64::MAX,
        max_10_exp => f64::MAX_10_EXP,
        max_exp => f64::MAX_EXP,
        min_ => f64::MIN,
        min_10_exp => f64::MIN_10_EXP,
        min_exp => f64::MIN_EXP,
        min_positive => f64::MIN_POSITIVE,
        nan => f64::NAN,
        neg_infinity => f64::NEG_INFINITY,
        e => f64::consts::E,
        pi => f64::consts::PI,
        radix => f64::RADIX,
        is_nan => f1(f64::is_nan),
        is_infinite => f1(f64::is_infinite),
        is_finite => f1(f64::is_finite),
        is_normal => f1(f64::is_normal),
        floor => f1(f64::floor),
        ceil => f1(f64::ceil),
        round => f1(f64::round),
        trunc => f1(f64::trunc),
        fract => f1(f64::fract),
        abs => f1(f64::abs),
        signum => f1(f64::signum),
        is_sign_positive => f1(f64::is_sign_positive),
        is_sign_negative => f1(f64::is_sign_negative),
        mul_add => f3(f64::mul_add),
        recip => f1(f64::recip),
        powi => f2(f64::powi),
        powf => f2(f64::powf),
        sqrt => f1(f64::sqrt),
        exp => f1(f64::exp),
        exp2 => f1(f64::exp2),
        ln => f1(f64::ln),
        log2 => f1(f64::log2),
        log10 => f1(f64::log10),
        to_degrees => f1(f64::to_degrees),
        to_radians => f1(f64::to_radians),
        max => f2(f64::max),
        min => f2(f64::min),
        abs_sub => f2(f64::abs_sub),
        cbrt => f1(f64::cbrt),
        hypot => f2(f64::hypot),
        sin => f1(f64::sin),
        cos => f1(f64::cos),
        tan => f1(f64::tan),
        acos => f1(f64::acos),
        atan => f1(f64::atan),
        atan2 => f2(f64::atan2),
        sin_cos => f1(f64::sin_cos),
        exp_m1 => f1(f64::exp_m1),
        ln_1p => f1(f64::ln_1p),
        sinh => f1(f64::sinh),
        cosh => f1(f64::cosh),
        tanh => f1(f64::tanh),
        acosh => f1(f64::acosh),
        atanh => f1(f64::atanh)
    )));
    try!(vm.define_global("int",
                          record!(
        min_value => VMInt::min_value(),
        max_value => VMInt::max_value(),
        count_ones => f1(VMInt::count_ones),
        rotate_left => f2(VMInt::rotate_left),
        rotate_right => f2(VMInt::rotate_right),
        swap_bytes => f1(VMInt::swap_bytes),
        from_be => f1(VMInt::from_be),
        from_le => f1(VMInt::from_le),
        to_be => f1(VMInt::to_be),
        to_le => f1(VMInt::to_le),
        pow => f2(VMInt::pow),
        abs => f1(VMInt::abs),
        signum => f1(VMInt::signum),
        is_positive => f1(VMInt::is_positive),
        is_negative => f1(VMInt::is_negative)
    )));
    try!(vm.define_global("array",
                          record!(
        length => f1(prim::array_length),
        index => f2(prim::array_index),
        append => f2(prim::array_append)
    )));

    try!(vm.define_global("string_prim",
                          record!(
        length => f1(str::len),
        is_empty => f1(str::is_empty),
        split_at => f2(str::split_at),
        find => f2(str::find::<&str>),
        rfind => f2(str::rfind::<&str>),
        trim => f1(str::trim),
        trim_left => f1(str::trim_left),
        trim_right => f1(str::trim_right),
        compare => f2(str::cmp),
        append => f2(prim::string_append),
        eq => f2(<str as PartialEq>::eq),
        slice => f3(prim::string_slice)
    )));
    try!(vm.define_global("char",
                          record!(
        is_digit => f2(char::is_digit),
        to_digit => f2(char::to_digit),
        len_utf8 => f1(char::len_utf8),
        len_utf16 => f1(char::len_utf16),
        is_alphabetic => f1(char::is_alphabetic),
        is_lowercase => f1(char::is_lowercase),
        is_uppercase => f1(char::is_uppercase),
        is_whitespace => f1(char::is_whitespace),
        is_alphanumeric => f1(char::is_alphanumeric),
        is_control => f1(char::is_control),
        is_numeric => f1(char::is_numeric)
    )));
    try!(vm.define_global("prim",
                          record!(
        show_Int => f1(prim::show_int),
        show_Float => f1(prim::show_float),
        show_Char => f1(prim::show_char)
    )));

    try!(vm.define_global("#error",
                          primitive::<fn(StdString) -> A>("#error", prim::error)));
    try!(vm.define_global("error",
                          primitive::<fn(StdString) -> A>("error", prim::error)));
    try!(vm.define_global("trace", f1(prim::trace)));

    try!(::lazy::load(vm));
    try!(::reference::load(vm));
    Ok(())
}
<|endoftext|>


<commit_before>use chrono::offset::{TimeZone, Utc};
use data_encoding::HEXLOWER;
use futures_executor::block_on;
use serde_derive::Deserialize;
use std::collections::HashMap;
use std::fs::File;
use std::path::Path;
use std::process::Command;
use tuf::crypto::{Ed25519PrivateKey, HashAlgorithm, KeyType, PrivateKey, SignatureScheme};
use tuf::interchange::JsonPretty;
use tuf::metadata::{
    MetadataPath, MetadataVersion, Role, RootMetadataBuilder, SnapshotMetadataBuilder, TargetPath,
    TargetsMetadataBuilder, TimestampMetadataBuilder, VirtualTargetPath,
};
use tuf::repository::{FileSystemRepository, FileSystemRepositoryBuilder, RepositoryStorage};

const KEYS_PATH: &str = "./keys.json";
// These structs and functions are necessary to parse keys.json, which contains the keys
// used by go-tuf to generate the equivalent metadata. We use the same keys to facilitate
// compatibility testing.

#[derive(Clone, Deserialize)]
struct KeyValue {
    public: String,
    private: String,
}

#[derive(Clone, Deserialize)]
struct TestKeyPair {
    keytype: KeyType,
    scheme: SignatureScheme,
    keyid_hash_algorithms: Option<Vec<String>>,
    keyval: KeyValue,
}

impl TestKeyPair {
    fn to_private_key(&self) -> Ed25519PrivateKey {
        let priv_bytes = HEXLOWER.decode(self.keyval.private.as_bytes()).unwrap();
        Ed25519PrivateKey::from_ed25519(&priv_bytes[..]).unwrap()
    }
}

#[derive(Deserialize)]
struct TestKeys {
    root: Vec<Vec<TestKeyPair>>,
    targets: Vec<Vec<TestKeyPair>>,
    snapshot: Vec<Vec<TestKeyPair>>,
    timestamp: Vec<Vec<TestKeyPair>>,
}

fn init_json_keys(path: &str) -> TestKeys {
    let f = File::open(path).expect("failed to open keys file");
    serde_json::from_reader(f).expect("serde failed")
}

// Map each role to its current key.
type RoleKeys = HashMap<&'static str, Ed25519PrivateKey>;

fn init_role_keys(json_keys: &TestKeys) -> RoleKeys {
    let mut keys = HashMap::new();
    keys.insert("root", json_keys.root[0][0].to_private_key());
    keys.insert("snapshot", json_keys.snapshot[0][0].to_private_key());
    keys.insert("targets", json_keys.targets[0][0].to_private_key());
    keys.insert("timestamp", json_keys.timestamp[0][0].to_private_key());
    keys
}

// TODO: replace this with a pure Rust library so it's portable across OSes.
fn copy_repo(dir: &str, step: u8) {
    let src = Path::new(dir)
        .join((step - 1).to_string())
        .join("repository");
    let dst = Path::new(dir).join(step.to_string());
    Command::new("/bin/cp")
        .arg("-r")
        .arg(src.to_str().unwrap())
        .arg(dst.to_str().unwrap())
        .output()
        .expect("cp failed");
}

// updates the root metadata. If root_signer is Some, use that to sign the
// metadata, otherwise use keys["root"].
async fn update_root(
    repo: &FileSystemRepository<JsonPretty>,
    keys: &RoleKeys,
    root_signer: Option<&dyn PrivateKey>,
    version: u32,
    consistent_snapshot: bool,
) {
    let signer = match root_signer {
        Some(k) => k,
        None => keys.get("root").unwrap(),
    };

    // Same expiration as go-tuf metadata generator.
    let expiration = Utc.ymd(2100, 1, 1).and_hms(0, 0, 0);

    let mut root = RootMetadataBuilder::new()
        .root_key(keys.get("root").unwrap().public().clone())
        .expires(expiration)
        .version(version)
        .snapshot_key(keys.get("snapshot").unwrap().public().clone())
        .targets_key(keys.get("targets").unwrap().public().clone())
        .timestamp_key(keys.get("timestamp").unwrap().public().clone())
        .consistent_snapshot(consistent_snapshot)
        .signed::<JsonPretty>(signer)
        .unwrap();

    // If we rotated the root, sign it again with the new key.
    if root_signer.is_some() {
        root.add_signature(keys.get("root").unwrap()).unwrap()
    };

    let root_path = MetadataPath::from_role(&Role::Root);
    repo.store_metadata(
        &root_path,
        &MetadataVersion::Number(version),
        &mut root.to_raw().unwrap().as_bytes(),
    )
    .await
    .unwrap();
    repo.store_metadata(
        &root_path,
        &MetadataVersion::None,
        &mut root.to_raw().unwrap().as_bytes(),
    )
    .await
    .unwrap();
}

// adds a target and updates the non-root metadata files.
async fn add_target(
    repo: &FileSystemRepository<JsonPretty>,
    keys: &RoleKeys,
    step: u8,
    consistent_snapshot: bool,
) {
    // Same expiration as go-tuf metadata generator.
    let expiration = Utc.ymd(2100, 1, 1).and_hms(0, 0, 0);
    let version: u32 = (step + 1).into();

    let mut targets_builder = TargetsMetadataBuilder::new()
        .expires(expiration)
        .version(version);

    let targets_path = MetadataPath::from_role(&Role::Targets);
    for i in 0..step + 1 {
        let step_str = format!("{}", i);
        let target_data = step_str.as_bytes();
        targets_builder = targets_builder
            .insert_target_from_reader(
                VirtualTargetPath::new(i.to_string()).unwrap(),
                target_data,
                &[HashAlgorithm::Sha256],
            )
            .unwrap();
    }
    let step_str = format!("{}", step);
    let target_data = step_str.as_bytes();

    let signed_targets = targets_builder
        .signed::<JsonPretty>(keys.get("targets").unwrap())
        .unwrap();
    let targets = signed_targets.assume_valid().unwrap();

    let hash = targets
        .targets()
        .get(&VirtualTargetPath::new(step.to_string()).unwrap())
        .unwrap()
        .hashes()
        .get(&HashAlgorithm::Sha256)
        .unwrap();

    let target_str = if consistent_snapshot {
        format!("{}.{}", hash, step.to_string())
    } else {
        step.to_string()
    };
    let target_path = TargetPath::new(target_str).unwrap();
    repo.store_target(&mut &*target_data, &target_path)
        .await
        .unwrap();

    let version_prefix = if consistent_snapshot {
        MetadataVersion::Number(version)
    } else {
        MetadataVersion::None
    };

    repo.store_metadata(
        &targets_path,
        &version_prefix,
        &mut signed_targets.to_raw().unwrap().as_bytes(),
    )
    .await
    .unwrap();

    let snapshot_path = MetadataPath::from_role(&Role::Snapshot);
    let snapshot = SnapshotMetadataBuilder::new()
        .expires(expiration)
        .version(version)
        .insert_metadata(&signed_targets, &[HashAlgorithm::Sha256])
        .unwrap()
        .signed::<JsonPretty>(keys.get("snapshot").unwrap())
        .unwrap();

    repo.store_metadata(
        &snapshot_path,
        &version_prefix,
        &mut snapshot.to_raw().unwrap().as_bytes(),
    )
    .await
    .unwrap();

    let timestamp_path = MetadataPath::from_role(&Role::Timestamp);
    let timestamp = TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
        .unwrap()
        .expires(expiration)
        .version(version)
        .signed::<JsonPretty>(keys.get("timestamp").unwrap())
        .unwrap();

    // Timestamp doesn't require a version prefix even in consistent_snapshot.
    repo.store_metadata(
        &timestamp_path,
        &MetadataVersion::None,
        &mut timestamp.to_raw().unwrap().as_bytes(),
    )
    .await
    .unwrap();
}

async fn generate_repos(dir: &str, consistent_snapshot: bool) -> tuf::Result<()> {
    // Create initial repo.
    let json_keys = init_json_keys(KEYS_PATH);
    let mut keys = init_role_keys(&json_keys);
    let dir0 = Path::new(dir).join("0");
    let repo = FileSystemRepositoryBuilder::new(dir0)
        .metadata_prefix(Path::new("repository"))
        .targets_prefix(Path::new("repository").join("targets"))
        .build()?;

    update_root(&repo, &keys, None, 1, consistent_snapshot).await;
    add_target(&repo, &keys, 0, consistent_snapshot).await;

    let mut i: u8 = 1;
    let rotations = vec![
        Some(Role::Root),
        Some(Role::Targets),
        Some(Role::Snapshot),
        Some(Role::Timestamp),
        None,
    ];
    for r in rotations.iter() {
        // Initialize new repo and copy the files from the previous step.
        let dir_i = Path::new(dir).join(i.to_string());
        let repo = FileSystemRepositoryBuilder::new(dir_i)
            .metadata_prefix(Path::new("repository"))
            .targets_prefix(Path::new("repository").join("targets"))
            .build()
            .unwrap();
        copy_repo(dir, i);

        let root_signer = match r {
            Some(Role::Root) => keys.insert("root", json_keys.root[1][0].to_private_key()),
            Some(Role::Targets) => {
                keys.insert("targets", json_keys.targets[1][0].to_private_key());
                None
            }
            Some(Role::Snapshot) => {
                keys.insert("snapshot", json_keys.snapshot[1][0].to_private_key());
                None
            }
            Some(Role::Timestamp) => {
                keys.insert("timestamp", json_keys.timestamp[1][0].to_private_key());
                None
            }
            None => None,
        };
        update_root(
            &repo,
            &keys,
            root_signer.as_ref().map(|x| x as &dyn PrivateKey),
            (i + 1).into(),
            consistent_snapshot,
        )
        .await;
        add_target(&repo, &keys, i, consistent_snapshot).await;
        i += 1;
    }
    Ok(())
}

fn main() {
    block_on(async {
        generate_repos("consistent-snapshot-true", true)
            .await
            .unwrap();
        generate_repos("consistent-snapshot-false", false)
            .await
            .unwrap();
    })
}
<commit_msg>Fix warnings<commit_after>use chrono::offset::{TimeZone, Utc};
use data_encoding::HEXLOWER;
use futures_executor::block_on;
use serde_derive::Deserialize;
use std::collections::HashMap;
use std::fs::File;
use std::path::Path;
use std::process::Command;
use tuf::crypto::{Ed25519PrivateKey, HashAlgorithm, KeyType, PrivateKey, SignatureScheme};
use tuf::interchange::JsonPretty;
use tuf::metadata::{
    MetadataPath, MetadataVersion, Role, RootMetadataBuilder, SnapshotMetadataBuilder, TargetPath,
    TargetsMetadataBuilder, TimestampMetadataBuilder, VirtualTargetPath,
};
use tuf::repository::{FileSystemRepository, FileSystemRepositoryBuilder, RepositoryStorage};

const KEYS_PATH: &str = "./keys.json";
// These structs and functions are necessary to parse keys.json, which contains the keys
// used by go-tuf to generate the equivalent metadata. We use the same keys to facilitate
// compatibility testing.

#[derive(Clone, Deserialize)]
struct KeyValue {
    #[serde(rename = "public")]
    _public: String,
    private: String,
}

#[derive(Clone, Deserialize)]
struct TestKeyPair {
    #[serde(rename = "keytype")]
    _keytype: KeyType,
    #[serde(rename = "scheme")]
    _scheme: SignatureScheme,
    #[serde(rename = "keyid_hash_algorithms")]
    _keyid_hash_algorithms: Option<Vec<String>>,
    keyval: KeyValue,
}

impl TestKeyPair {
    fn to_private_key(&self) -> Ed25519PrivateKey {
        let priv_bytes = HEXLOWER.decode(self.keyval.private.as_bytes()).unwrap();
        Ed25519PrivateKey::from_ed25519(&priv_bytes[..]).unwrap()
    }
}

#[derive(Deserialize)]
struct TestKeys {
    root: Vec<Vec<TestKeyPair>>,
    targets: Vec<Vec<TestKeyPair>>,
    snapshot: Vec<Vec<TestKeyPair>>,
    timestamp: Vec<Vec<TestKeyPair>>,
}

fn init_json_keys(path: &str) -> TestKeys {
    let f = File::open(path).expect("failed to open keys file");
    serde_json::from_reader(f).expect("serde failed")
}

// Map each role to its current key.
type RoleKeys = HashMap<&'static str, Ed25519PrivateKey>;

fn init_role_keys(json_keys: &TestKeys) -> RoleKeys {
    let mut keys = HashMap::new();
    keys.insert("root", json_keys.root[0][0].to_private_key());
    keys.insert("snapshot", json_keys.snapshot[0][0].to_private_key());
    keys.insert("targets", json_keys.targets[0][0].to_private_key());
    keys.insert("timestamp", json_keys.timestamp[0][0].to_private_key());
    keys
}

// TODO: replace this with a pure Rust library so it's portable across OSes.
fn copy_repo(dir: &str, step: u8) {
    let src = Path::new(dir)
        .join((step - 1).to_string())
        .join("repository");
    let dst = Path::new(dir).join(step.to_string());
    Command::new("/bin/cp")
        .arg("-r")
        .arg(src.to_str().unwrap())
        .arg(dst.to_str().unwrap())
        .output()
        .expect("cp failed");
}

// updates the root metadata. If root_signer is Some, use that to sign the
// metadata, otherwise use keys["root"].
async fn update_root(
    repo: &FileSystemRepository<JsonPretty>,
    keys: &RoleKeys,
    root_signer: Option<&dyn PrivateKey>,
    version: u32,
    consistent_snapshot: bool,
) {
    let signer = match root_signer {
        Some(k) => k,
        None => keys.get("root").unwrap(),
    };

    // Same expiration as go-tuf metadata generator.
    let expiration = Utc.ymd(2100, 1, 1).and_hms(0, 0, 0);

    let mut root = RootMetadataBuilder::new()
        .root_key(keys.get("root").unwrap().public().clone())
        .expires(expiration)
        .version(version)
        .snapshot_key(keys.get("snapshot").unwrap().public().clone())
        .targets_key(keys.get("targets").unwrap().public().clone())
        .timestamp_key(keys.get("timestamp").unwrap().public().clone())
        .consistent_snapshot(consistent_snapshot)
        .signed::<JsonPretty>(signer)
        .unwrap();

    // If we rotated the root, sign it again with the new key.
    if root_signer.is_some() {
        root.add_signature(keys.get("root").unwrap()).unwrap()
    };

    let root_path = MetadataPath::from_role(&Role::Root);
    repo.store_metadata(
        &root_path,
        &MetadataVersion::Number(version),
        &mut root.to_raw().unwrap().as_bytes(),
    )
    .await
    .unwrap();
    repo.store_metadata(
        &root_path,
        &MetadataVersion::None,
        &mut root.to_raw().unwrap().as_bytes(),
    )
    .await
    .unwrap();
}

// adds a target and updates the non-root metadata files.
async fn add_target(
    repo: &FileSystemRepository<JsonPretty>,
    keys: &RoleKeys,
    step: u8,
    consistent_snapshot: bool,
) {
    // Same expiration as go-tuf metadata generator.
    let expiration = Utc.ymd(2100, 1, 1).and_hms(0, 0, 0);
    let version: u32 = (step + 1).into();

    let mut targets_builder = TargetsMetadataBuilder::new()
        .expires(expiration)
        .version(version);

    let targets_path = MetadataPath::from_role(&Role::Targets);
    for i in 0..step + 1 {
        let step_str = format!("{}", i);
        let target_data = step_str.as_bytes();
        targets_builder = targets_builder
            .insert_target_from_reader(
                VirtualTargetPath::new(i.to_string()).unwrap(),
                target_data,
                &[HashAlgorithm::Sha256],
            )
            .unwrap();
    }
    let step_str = format!("{}", step);
    let target_data = step_str.as_bytes();

    let signed_targets = targets_builder
        .signed::<JsonPretty>(keys.get("targets").unwrap())
        .unwrap();
    let targets = signed_targets.assume_valid().unwrap();

    let hash = targets
        .targets()
        .get(&VirtualTargetPath::new(step.to_string()).unwrap())
        .unwrap()
        .hashes()
        .get(&HashAlgorithm::Sha256)
        .unwrap();

    let target_str = if consistent_snapshot {
        format!("{}.{}", hash, step.to_string())
    } else {
        step.to_string()
    };
    let target_path = TargetPath::new(target_str).unwrap();
    repo.store_target(&mut &*target_data, &target_path)
        .await
        .unwrap();

    let version_prefix = if consistent_snapshot {
        MetadataVersion::Number(version)
    } else {
        MetadataVersion::None
    };

    repo.store_metadata(
        &targets_path,
        &version_prefix,
        &mut signed_targets.to_raw().unwrap().as_bytes(),
    )
    .await
    .unwrap();

    let snapshot_path = MetadataPath::from_role(&Role::Snapshot);
    let snapshot = SnapshotMetadataBuilder::new()
        .expires(expiration)
        .version(version)
        .insert_metadata(&signed_targets, &[HashAlgorithm::Sha256])
        .unwrap()
        .signed::<JsonPretty>(keys.get("snapshot").unwrap())
        .unwrap();

    repo.store_metadata(
        &snapshot_path,
        &version_prefix,
        &mut snapshot.to_raw().unwrap().as_bytes(),
    )
    .await
    .unwrap();

    let timestamp_path = MetadataPath::from_role(&Role::Timestamp);
    let timestamp = TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
        .unwrap()
        .expires(expiration)
        .version(version)
        .signed::<JsonPretty>(keys.get("timestamp").unwrap())
        .unwrap();

    // Timestamp doesn't require a version prefix even in consistent_snapshot.
    repo.store_metadata(
        &timestamp_path,
        &MetadataVersion::None,
        &mut timestamp.to_raw().unwrap().as_bytes(),
    )
    .await
    .unwrap();
}

async fn generate_repos(dir: &str, consistent_snapshot: bool) -> tuf::Result<()> {
    // Create initial repo.
    let json_keys = init_json_keys(KEYS_PATH);
    let mut keys = init_role_keys(&json_keys);
    let dir0 = Path::new(dir).join("0");
    let repo = FileSystemRepositoryBuilder::new(dir0)
        .metadata_prefix(Path::new("repository"))
        .targets_prefix(Path::new("repository").join("targets"))
        .build()?;

    update_root(&repo, &keys, None, 1, consistent_snapshot).await;
    add_target(&repo, &keys, 0, consistent_snapshot).await;

    let mut i: u8 = 1;
    let rotations = vec![
        Some(Role::Root),
        Some(Role::Targets),
        Some(Role::Snapshot),
        Some(Role::Timestamp),
        None,
    ];
    for r in rotations.iter() {
        // Initialize new repo and copy the files from the previous step.
        let dir_i = Path::new(dir).join(i.to_string());
        let repo = FileSystemRepositoryBuilder::new(dir_i)
            .metadata_prefix(Path::new("repository"))
            .targets_prefix(Path::new("repository").join("targets"))
            .build()
            .unwrap();
        copy_repo(dir, i);

        let root_signer = match r {
            Some(Role::Root) => keys.insert("root", json_keys.root[1][0].to_private_key()),
            Some(Role::Targets) => {
                keys.insert("targets", json_keys.targets[1][0].to_private_key());
                None
            }
            Some(Role::Snapshot) => {
                keys.insert("snapshot", json_keys.snapshot[1][0].to_private_key());
                None
            }
            Some(Role::Timestamp) => {
                keys.insert("timestamp", json_keys.timestamp[1][0].to_private_key());
                None
            }
            None => None,
        };
        update_root(
            &repo,
            &keys,
            root_signer.as_ref().map(|x| x as &dyn PrivateKey),
            (i + 1).into(),
            consistent_snapshot,
        )
        .await;
        add_target(&repo, &keys, i, consistent_snapshot).await;
        i += 1;
    }
    Ok(())
}

fn main() {
    block_on(async {
        generate_repos("consistent-snapshot-true", true)
            .await
            .unwrap();
        generate_repos("consistent-snapshot-false", false)
            .await
            .unwrap();
    })
}
<|endoftext|>


<commit_before>use std::{any::Any, collections::HashMap};

use dces::prelude::Component;

/// The struct `Registry` represents a global registry. It is used to register and call
/// global elements like services.
#[derive(Default)]
pub struct Registry {
    registry: HashMap<String, Box<dyn Any>>,
}

impl Registry {
    /// Creates a service registry with an empty Registry map.
    pub fn new() -> Self {
        Registry::default()
    }

    /// Register a new Registry with the given key.
    pub fn register<C: Component>(&mut self, key: impl Into<String>, service: C) {
        self.registry.insert(key.into(), Box::new(service));
    }

    /// Gets an element from the registry.
    ///
    /// # Panics
    ///
    /// Panics if the there is no element for the given key or the given service type is wrong.
    pub fn get<C: Component>(&self, key: &str) -> &C {
        self.registry
            .get(&key.to_string())
            .unwrap_or_else(|| panic!("Registry.get(): key: {} could not be found.", key))
            .downcast_ref()
            .unwrap_or_else(|| panic!("Registry.get(): wrong type for key: {}", key))
    }

    /// Gets a mutable reference of the requested element.
    ///
    /// # Panics
    ///
    /// Panics if the there is no service for the given key or the given service type is wrong.
    pub fn get_mut<C: Component>(&mut self, key: &str) -> &mut C {
        self.registry
            .get_mut(&key.to_string())
            .unwrap_or_else(|| panic!("Registry.get(): key: {} could not be found.", key))
            .downcast_mut()
            .unwrap_or_else(|| panic!("Registry.get(): wrong type for key: {}", key))
    }

    /// Try to get an element from the registry.
    ///
    /// # Panics
    ///
    /// Panics if the there is no service for the given key or the given service type is wrong.
    pub fn try_get<C: Component>(&self, key: &str) -> Option<&C> {
        if let Some(e) = self.registry.get(&key.to_string()) {
            if let Some(r) = e.downcast_ref() {
                return Some(r);
            }
        }

        None
    }

    /// Try to get an element from the registry.
    ///
    /// # Panics
    ///
    /// Panics if the there is no service for the given key or the given service type is wrong.
    pub fn try_get_mut<C: Component>(&mut self, key: &str) -> Option<&mut C> {
        if let Some(e) = self.registry.get_mut(&key.to_string()) {
            if let Some(r) = e.downcast_mut() {
                return Some(r);
            }
        }

        None
    }

    /// Returns the number of elements in the registry.
    pub fn len(&self) -> usize {
        self.registry.len()
    }

    /// Returns true if the registry contains no elements.
    pub fn is_empty(&self) -> bool {
        self.registry.is_empty()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    struct ServiceOne;
    struct ServiceTwo;

    #[test]
    fn register() {
        let mut registry = Registry::new();
        registry.register("one", ServiceOne);
        registry.register("two", ServiceTwo);

        assert!(registry.try_get::<ServiceOne>("one").is_some());
        assert!(registry.try_get::<ServiceTwo>("two").is_some());
    }

    #[test]
    fn try_get_mut() {
        let mut registry = Registry::new();
        registry.register("one", ServiceOne);
        registry.register("two", ServiceTwo);

        assert!(registry.try_get_mut::<ServiceOne>("one").is_some());
        assert!(registry.try_get_mut::<ServiceTwo>("two").is_some());
    }

    #[test]
    fn len() {
        let mut registry = Registry::new();
        assert_eq!(registry.len(), 0);

        registry.register("one", ServiceOne);
        assert_eq!(registry.len(), 1);

        registry.register("two", ServiceTwo);
        assert_eq!(registry.len(), 2);
    }

    #[test]
    fn is_empty() {
        let mut registry = Registry::new();
        assert!(registry.is_empty());

        registry.register("one", ServiceOne);
        assert!(!registry.is_empty());
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    struct ServiceOne;
    struct ServiceTwo;

    #[test]
    fn register() {
        let mut registry = Registry::new();
        registry.register("one", ServiceOne);
        registry.register("two", ServiceTwo);

        assert!(registry.try_get::<ServiceOne>("one").is_some());
        assert!(registry.try_get::<ServiceTwo>("two").is_some());
    }

    #[test]
    fn try_get_mut() {
        let mut registry = Registry::new();
        registry.register("one", ServiceOne);
        registry.register("two", ServiceTwo);

        assert!(registry.try_get_mut::<ServiceOne>("one").is_some());
        assert!(registry.try_get_mut::<ServiceTwo>("two").is_some());
    }

    #[test]
    fn len() {
        let mut registry = Registry::new();
        assert_eq!(registry.len(), 0);

        registry.register("one", ServiceOne);
        assert_eq!(registry.len(), 1);

        registry.register("two", ServiceTwo);
        assert_eq!(registry.len(), 2);
    }

    #[test]
    fn is_empty() {
        let mut registry = Registry::new();
        assert!(registry.is_empty());

        registry.register("one", ServiceOne);
        assert!(!registry.is_empty());
    }
}<commit_msg>Save settings finished. Load settings wip.<commit_after>use std::{any::Any, collections::HashMap};

use dces::prelude::Component;

/// The struct `Registry` represents a global registry. It is used to register and call
/// global elements like services.
#[derive(Default)]
pub struct Registry {
    registry: HashMap<String, Box<dyn Any>>,
}

impl Registry {
    /// Creates a service registry with an empty Registry map.
    pub fn new() -> Self {
        Registry::default()
    }

    /// Register a new Registry with the given key.
    pub fn register<C: Component>(&mut self, key: impl Into<String>, service: C) {
        self.registry.insert(key.into(), Box::new(service));
    }

    /// Gets an element from the registry.
    ///
    /// # Panics
    ///
    /// Panics if the there is no element for the given key or the given service type is wrong.
    pub fn get<C: Component>(&self, key: &str) -> &C {
        self.registry
            .get(&key.to_string())
            .unwrap_or_else(|| panic!("Registry.get(): key: {} could not be found.", key))
            .downcast_ref()
            .unwrap_or_else(|| panic!("Registry.get(): wrong type for key: {}", key))
    }

    /// Gets a mutable reference of the requested element.
    ///
    /// # Panics
    ///
    /// Panics if the there is no service for the given key or the given service type is wrong.
    pub fn get_mut<C: Component>(&mut self, key: &str) -> &mut C {
        self.registry
            .get_mut(&key.to_string())
            .unwrap_or_else(|| panic!("Registry.get(): key: {} could not be found.", key))
            .downcast_mut()
            .unwrap_or_else(|| panic!("Registry.get(): wrong type for key: {}", key))
    }

    /// Try to get an element from the registry.
    ///
    /// # Panics
    ///
    /// Panics if the there is no service for the given key or the given service type is wrong.
    pub fn try_get<C: Component>(&self, key: &str) -> Option<&C> {
        if let Some(e) = self.registry.get(&key.to_string()) {
            if let Some(r) = e.downcast_ref() {
                return Some(r);
            }
        }

        None
    }

    /// Try to get an element from the registry.
    ///
    /// # Panics
    ///
    /// Panics if the there is no service for the given key or the given service type is wrong.
    pub fn try_get_mut<C: Component>(&mut self, key: &str) -> Option<&mut C> {
        if let Some(e) = self.registry.get_mut(&key.to_string()) {
            if let Some(r) = e.downcast_mut() {
                return Some(r);
            }
        }

        None
    }

    /// Returns the number of elements in the registry.
    pub fn len(&self) -> usize {
        self.registry.len()
    }

    /// Returns true if the registry contains no elements.
    pub fn is_empty(&self) -> bool {
        self.registry.is_empty()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    struct ServiceOne;
    struct ServiceTwo;

    #[test]
    fn register() {
        let mut registry = Registry::new();
        registry.register("one", ServiceOne);
        registry.register("two", ServiceTwo);

        assert!(registry.try_get::<ServiceOne>("one").is_some());
        assert!(registry.try_get::<ServiceTwo>("two").is_some());
    }

    #[test]
    fn try_get_mut() {
        let mut registry = Registry::new();
        registry.register("one", ServiceOne);
        registry.register("two", ServiceTwo);

        assert!(registry.try_get_mut::<ServiceOne>("one").is_some());
        assert!(registry.try_get_mut::<ServiceTwo>("two").is_some());
    }

    #[test]
    fn len() {
        let mut registry = Registry::new();
        assert_eq!(registry.len(), 0);

        registry.register("one", ServiceOne);
        assert_eq!(registry.len(), 1);

        registry.register("two", ServiceTwo);
        assert_eq!(registry.len(), 2);
    }

    #[test]
    fn is_empty() {
        let mut registry = Registry::new();
        assert!(registry.is_empty());

        registry.register("one", ServiceOne);
        assert!(!registry.is_empty());
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    struct ServiceOne;
    struct ServiceTwo;

    #[test]
    fn register() {
        let mut registry = Registry::new();
        registry.register("one", ServiceOne);
        registry.register("two", ServiceTwo);

        assert!(registry.try_get::<ServiceOne>("one").is_some());
        assert!(registry.try_get::<ServiceTwo>("two").is_some());
    }

    #[test]
    fn try_get_mut() {
        let mut registry = Registry::new();
        registry.register("one", ServiceOne);
        registry.register("two", ServiceTwo);

        assert!(registry.try_get_mut::<ServiceOne>("one").is_some());
        assert!(registry.try_get_mut::<ServiceTwo>("two").is_some());
    }

    #[test]
    fn len() {
        let mut registry = Registry::new();
        assert_eq!(registry.len(), 0);

        registry.register("one", ServiceOne);
        assert_eq!(registry.len(), 1);

        registry.register("two", ServiceTwo);
        assert_eq!(registry.len(), 2);
    }

    #[test]
    fn is_empty() {
        let mut registry = Registry::new();
        assert!(registry.is_empty());

        registry.register("one", ServiceOne);
        assert!(!registry.is_empty());
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate capnp;
pub mod addressbook_capnp {
  include!(concat!(env!("OUT_DIR"), "/addressbook_capnp.rs"));
}

use capnp::message::{Builder, HeapAllocator, TypedReader};
use std::sync::mpsc;
use std::thread;

pub mod addressbook {
    use addressbook_capnp::{address_book, person};
    use capnp::message::{Builder, HeapAllocator, TypedReader};

    pub fn build_address_book() -> TypedReader<Builder<HeapAllocator>, address_book::Owned> {
        let mut message = Builder::new_default();
        {
            let address_book = message.init_root::<address_book::Builder>();

            let mut people = address_book.init_people(2);

            {
                let mut alice = people.borrow().get(0);
                alice.set_id(123);
                alice.set_name("Alice");
                alice.set_email("alice@example.com");
                {
                    let mut alice_phones = alice.borrow().init_phones(1);
                    alice_phones.borrow().get(0).set_number("555-1212");
                    alice_phones.borrow().get(0).set_type(person::phone_number::Type::Mobile);
                }
                alice.get_employment().set_school("MIT");
            }

            {
                let mut bob = people.get(1);
                bob.set_id(456);
                bob.set_name("Bob");
                bob.set_email("bob@example.com");
                {
                    let mut bob_phones = bob.borrow().init_phones(2);
                    bob_phones.borrow().get(0).set_number("555-4567");
                    bob_phones.borrow().get(0).set_type(person::phone_number::Type::Home);
                    bob_phones.borrow().get(1).set_number("555-7654");
                    bob_phones.borrow().get(1).set_type(person::phone_number::Type::Work);
                }
                bob.get_employment().set_unemployed(());
            }
        }

        message.into_typed()
    }
}

pub fn main() {

    let book = addressbook::build_address_book();

    let (tx_book, rx_book) = mpsc::channel::<TypedReader<Builder<HeapAllocator>, addressbook_capnp::address_book::Owned>>();
    let (tx_id, rx_id) = mpsc::channel::<u32>();

    thread::spawn(move || {
        let addressbook_reader = rx_book.recv().unwrap();
        let addressbook = addressbook_reader.get().unwrap();
        let first_person = addressbook.get_people().unwrap().get(0);
        let first_id = first_person.get_id();
        tx_id.send(first_id)
    });

    tx_book.send(book).unwrap();
    let first_id = rx_id.recv().unwrap();
    assert_eq!(first_id, 123);
}
<commit_msg>Update addressbook_send.rs<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate capnp;
pub mod addressbook_capnp {
  include!(concat!(env!("OUT_DIR"), "/addressbook_capnp.rs"));
}

use capnp::message::{Builder, HeapAllocator, TypedReader};
use std::sync::mpsc;
use std::thread;

pub mod addressbook {
    use addressbook_capnp::{address_book, person};
    use capnp::message::{Builder, HeapAllocator, TypedReader};

    pub fn build_address_book() -> TypedReader<Builder<HeapAllocator>, address_book::Owned> {
        let mut message = Builder::new_default();
        {
            let address_book = message.init_root::<address_book::Builder>();

            let mut people = address_book.init_people(2);

            {
                let mut alice = people.borrow().get(0);
                alice.set_id(123);
                alice.set_name("Alice");
                alice.set_email("alice@example.com");
                {
                    let mut alice_phones = alice.borrow().init_phones(1);
                    alice_phones.borrow().get(0).set_number("555-1212");
                    alice_phones.borrow().get(0).set_type(person::phone_number::Type::Mobile);
                }
                alice.get_employment().set_school("MIT");
            }

            {
                let mut bob = people.get(1);
                bob.set_id(456);
                bob.set_name("Bob");
                bob.set_email("bob@example.com");
                {
                    let mut bob_phones = bob.borrow().init_phones(2);
                    bob_phones.borrow().get(0).set_number("555-4567");
                    bob_phones.borrow().get(0).set_type(person::phone_number::Type::Home);
                    bob_phones.borrow().get(1).set_number("555-7654");
                    bob_phones.borrow().get(1).set_type(person::phone_number::Type::Work);
                }
                bob.get_employment().set_unemployed(());
            }
        }

        // There are two ways to get a TypedReader from our `message`:
        //
        // Option 1: Go through the full process manually
        //  message.into_reader::<address_book::Owned>().into_typed()
        //
        //  Option 2: Use the "Into" trait defined on the builder
        //   message.into()
        //
        // Option 3: Use the "From" trait defined on the builder
        TypedReader::from(message)
    }
}

pub fn main() {

    let book = addressbook::build_address_book();

    let (tx_book, rx_book) = mpsc::channel::<TypedReader<Builder<HeapAllocator>, addressbook_capnp::address_book::Owned>>();
    let (tx_id, rx_id) = mpsc::channel::<u32>();

    thread::spawn(move || {
        let addressbook_reader = rx_book.recv().unwrap();
        let addressbook = addressbook_reader.get().unwrap();
        let first_person = addressbook.get_people().unwrap().get(0);
        let first_id = first_person.get_id();
        tx_id.send(first_id)
    });

    tx_book.send(book).unwrap();
    let first_id = rx_id.recv().unwrap();
    assert_eq!(first_id, 123);
}
<|endoftext|>


<commit_before>extern crate corrosion;

use corrosion::{PlayerAction, GameStatus};

use corrosion::utility::*;

/// Tests conceding.
#[test]
fn test_concede() {
    let mut game = new_two_player_game();

    let player1_id = game.player_turn_order[0];

    game.do_player_action(player1_id, &PlayerAction::Concede).unwrap();

    assert_eq!(game.current_status, GameStatus::Ended);
}
<commit_msg>Remove useless test comment<commit_after>extern crate corrosion;

use corrosion::{PlayerAction, GameStatus};

use corrosion::utility::*;

#[test]
fn test_concede() {
    let mut game = new_two_player_game();

    let player1_id = game.player_turn_order[0];

    game.do_player_action(player1_id, &PlayerAction::Concede).unwrap();

    assert_eq!(game.current_status, GameStatus::Ended);
}
<|endoftext|>


<commit_before>extern crate mpd;
extern crate time;

use std::net::TcpStream;
use time::Duration;

fn connect() -> mpd::Client<TcpStream> {
    mpd::Client::new(TcpStream::connect(option_env!("MPD_SOCK").unwrap_or("127.0.0.1:6600")).unwrap()).unwrap()
}

#[test]
fn status() {
    let mut mpd = connect();
    let status = mpd.status().unwrap();
    println!("{:?}", status);
}

macro_rules! test_options_impl {
    ($name:ident, $val1:expr, $tval1:expr, $val2:expr, $tval2:expr) => {
        #[test]
        fn $name() {
            let mut mpd = connect();
            mpd.$name($val1).unwrap();
            assert_eq!(mpd.status().unwrap().$name, $tval1);
            mpd.$name($val2).unwrap();
            assert_eq!(mpd.status().unwrap().$name, $tval2);
        }
    }
}

macro_rules! test_option {
    ($name:ident, $val1:expr, $val2:expr) => {
        test_options_impl!($name, $val1, $val1, $val2, $val2);
    };
    ($name:ident, $val1:expr => $tval1:expr, $val2:expr => $tval2:expr) => {
        test_options_impl!($name, $val1, $tval1, $val2, $tval2);
    };
}

test_option!(volume, 100, 0);
test_option!(consume, true, false);
test_option!(single, true, false);
test_option!(random, true, false);
test_option!(repeat, true, false);
test_option!(crossfade, 1000 => Some(1000), 0 => None);
//test_option!(mixrampdb, 1.0f32, 0.0f32);
//test_option!(mixrampdelay, 1 => Some(Duration::seconds(1)), 0 => None);

#[test]
fn replaygain() {
    let mut mpd = connect();
    if mpd.version >= mpd::Version(0, 16, 0) {
        mpd.replaygain(mpd::ReplayGain::Track).unwrap();
        assert_eq!(mpd.get_replaygain().unwrap(), mpd::ReplayGain::Track);
        mpd.replaygain(mpd::ReplayGain::Off).unwrap();
        assert_eq!(mpd.get_replaygain().unwrap(), mpd::ReplayGain::Off);
    }
}
<commit_msg>volume test update<commit_after>extern crate mpd;
extern crate time;

use std::net::TcpStream;
use time::Duration;

fn connect() -> mpd::Client<TcpStream> {
    mpd::Client::new(TcpStream::connect(option_env!("MPD_SOCK").unwrap_or("127.0.0.1:6600")).unwrap()).unwrap()
}

#[test]
fn status() {
    let mut mpd = connect();
    let status = mpd.status().unwrap();
    println!("{:?}", status);
}

macro_rules! test_options_impl {
    ($name:ident, $val1:expr, $tval1:expr, $val2:expr, $tval2:expr) => {
        #[test]
        fn $name() {
            let mut mpd = connect();
            mpd.$name($val1).unwrap();
            assert_eq!(mpd.status().unwrap().$name, $tval1);
            mpd.$name($val2).unwrap();
            assert_eq!(mpd.status().unwrap().$name, $tval2);
        }
    }
}

macro_rules! test_option {
    ($name:ident, $val1:expr, $val2:expr) => {
        test_options_impl!($name, $val1, $val1, $val2, $val2);
    };
    ($name:ident, $val1:expr => $tval1:expr, $val2:expr => $tval2:expr) => {
        test_options_impl!($name, $val1, $tval1, $val2, $tval2);
    };
}

test_option!(consume, true, false);
test_option!(single, true, false);
test_option!(random, true, false);
test_option!(repeat, true, false);
test_option!(crossfade, 1000 => Some(1000), 0 => None);
//test_option!(mixrampdb, 1.0f32, 0.0f32);
//test_option!(mixrampdelay, 1 => Some(Duration::seconds(1)), 0 => None);

#[test]
fn replaygain() {
    let mut mpd = connect();
    if mpd.version >= mpd::Version(0, 16, 0) {
        mpd.replaygain(mpd::ReplayGain::Track).unwrap();
        assert_eq!(mpd.get_replaygain().unwrap(), mpd::ReplayGain::Track);
        mpd.replaygain(mpd::ReplayGain::Off).unwrap();
        assert_eq!(mpd.get_replaygain().unwrap(), mpd::ReplayGain::Off);
    }
}

#[test]
fn volume() {
    let mut mpd = connect();
    if mpd.status().unwrap().volume >= 0 {
        mpd.volume(100).unwrap();
        assert_eq!(mpd.status().unwrap().volume, 100);
        mpd.volume(0).unwrap();
        assert_eq!(mpd.status().unwrap().volume, 0);
    }
}
<|endoftext|>


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

use std::num::FromPrimitive;
use std::isize;

#[derive(FromPrimitive)]
struct A { x: isize }
//~^^ ERROR `FromPrimitive` cannot be derived for structs
//~^^^ ERROR `FromPrimitive` cannot be derived for structs

#[derive(FromPrimitive)]
struct B(isize);
//~^^ ERROR `FromPrimitive` cannot be derived for structs
//~^^^ ERROR `FromPrimitive` cannot be derived for structs

#[derive(FromPrimitive)]
enum C { Foo(isize), Bar(usize) }
//~^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants
//~^^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants

#[derive(FromPrimitive)]
enum D { Baz { x: isize } }
//~^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants
//~^^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants

pub fn main() {}
<commit_msg>test #[derive(FromPrimitive)] triggers custom-derive error<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[derive(FromPrimitive)] //~ERROR `#[derive]` for custom traits is not stable
enum Foo {}

fn main() {}

<|endoftext|>


<commit_before>use card_strategy::CardStrategy;

use card::Card;
use game_status::GameStatus;
use player::PlayerName;

use std::collections::BTreeMap;

#[derive(Debug)]
pub struct MyCardStrategy;

impl MyCardStrategy {
    fn score_card<'a>(card: &'a Card, game_status: &'a GameStatus, player_name: &PlayerName) -> (i32, i32, i32, i32) {
        let card_penalty_to_me = MyCardStrategy::card_penalty_to_me(card, game_status, player_name);
        let card_penalty = 0 - MyCardStrategy::card_penalty(card, game_status);
        let trouble = card_penalty_to_me * (u32::from(card.rank) as i32);
        let card_rank = 0 - (u32::from(card.rank) as i32);
        (card_penalty_to_me, card_penalty, trouble, card_rank)
    }

    fn card_penalty(card: &Card, game_status: &GameStatus) -> i32 {
        game_status.round_parameters.card_points.get(card).map(|penalty| penalty.clone()).unwrap_or_default()
    }

    fn card_penalty_to_me(card: &Card, game_status: &GameStatus, player_name: &PlayerName) -> i32 {
        if MyCardStrategy::will_win_deal(card, game_status) {
            MyCardStrategy::card_penalty(card, game_status)
        } else {
            0
        }
    }

    fn will_win_deal(card: &Card, game_status: &GameStatus) -> bool {
        match game_status.my_in_progress_deal {
            Some(ref deal) => {
                match deal.suit {
                    Some(current_suit) => {
                        let mut option_winning_card: Option<Card> = None;

                        for deal_card in deal.deal_cards.iter() {
                            if deal_card.card.suit == current_suit {
                                match option_winning_card {
                                    None => option_winning_card = Some(deal_card.card.clone()),
                                    Some(winning_card) => {
                                        if deal_card.card.rank > winning_card.rank {
                                            option_winning_card = Some(deal_card.card.clone())
                                        }
                                    }
                                }
                            }
                        }

                        let will_win_rank = match option_winning_card {
                            Some(winning_card) => card.rank > winning_card.rank,
                            None => true
                        };

                        card.suit == current_suit && will_win_rank
                    }
                    None => true
                }
            }
            None => true
        }
    }
}

impl CardStrategy for MyCardStrategy {

    fn pass_cards<'a>(&mut self, game_status: &'a GameStatus) -> Vec<&'a Card> {
        // Need to order cards by potential to win lowest penalty hands
        let mut initial_hand = game_status.my_initial_hand.clone();
        initial_hand.reverse();
        initial_hand.iter().take(3).collect()
    }

    fn play_card<'a>(&mut self, game_status: &'a GameStatus, player_name: &PlayerName) -> &'a Card {
        let current_suit = game_status.my_in_progress_deal.as_ref().and_then(|deal| deal.suit);
        let mut valid_cards: Vec<&'a Card> = game_status.my_current_hand.iter().filter(|card| Some(card.suit) == current_suit).collect();

        if valid_cards.is_empty() {
            valid_cards.extend(&game_status.my_current_hand);
        }

        let scored_cards: BTreeMap<((i32, i32, i32, i32), &Card), &Card> = valid_cards.into_iter().map(|card| {
            ((MyCardStrategy::score_card(card, game_status, player_name), card), card)
        }).collect();

        scored_cards.values().next().expect("No valid cards to play!")
    }

}<commit_msg>slightly better passing<commit_after>use card_strategy::CardStrategy;

use card::Card;
use game_status::GameStatus;
use player::PlayerName;

use std::collections::BTreeMap;

#[derive(Debug)]
pub struct MyCardStrategy;

impl MyCardStrategy {
    fn score_card<'a>(card: &'a Card, game_status: &'a GameStatus, player_name: &PlayerName) -> (i32, i32, i32, i32) {
        let card_penalty_to_me = MyCardStrategy::card_penalty_to_me(card, game_status, player_name);
        let card_penalty = 0 - MyCardStrategy::card_penalty(card, game_status);
        let trouble = card_penalty_to_me * (u32::from(card.rank) as i32);
        let card_rank = 0 - (u32::from(card.rank) as i32);
        (card_penalty_to_me, card_penalty, trouble, card_rank)
    }

    fn card_penalty(card: &Card, game_status: &GameStatus) -> i32 {
        game_status.round_parameters.card_points.get(card).map(|penalty| penalty.clone()).unwrap_or_default()
    }

    fn card_penalty_to_me(card: &Card, game_status: &GameStatus, player_name: &PlayerName) -> i32 {
        if MyCardStrategy::will_win_deal(card, game_status) {
            MyCardStrategy::card_penalty(card, game_status)
        } else {
            0
        }
    }

    fn will_win_deal(card: &Card, game_status: &GameStatus) -> bool {
        match game_status.my_in_progress_deal {
            Some(ref deal) => {
                match deal.suit {
                    Some(current_suit) => {
                        let mut option_winning_card: Option<Card> = None;

                        for deal_card in deal.deal_cards.iter() {
                            if deal_card.card.suit == current_suit {
                                match option_winning_card {
                                    None => option_winning_card = Some(deal_card.card.clone()),
                                    Some(winning_card) => {
                                        if deal_card.card.rank > winning_card.rank {
                                            option_winning_card = Some(deal_card.card.clone())
                                        }
                                    }
                                }
                            }
                        }

                        let will_win_rank = match option_winning_card {
                            Some(winning_card) => card.rank > winning_card.rank,
                            None => true
                        };

                        card.suit == current_suit && will_win_rank
                    }
                    None => true
                }
            }
            None => true
        }
    }
}

impl CardStrategy for MyCardStrategy {

    fn pass_cards<'a>(&mut self, game_status: &'a GameStatus) -> Vec<&'a Card> {
        // Need to order cards by potential to win lowest penalty hands
        let mut initial_hand: Vec<&'a Card> = game_status.my_initial_hand.iter().collect();
        initial_hand.reverse();
        initial_hand.into_iter().take(3).collect()
    }

    fn play_card<'a>(&mut self, game_status: &'a GameStatus, player_name: &PlayerName) -> &'a Card {
        let current_suit = game_status.my_in_progress_deal.as_ref().and_then(|deal| deal.suit);
        let mut valid_cards: Vec<&'a Card> = game_status.my_current_hand.iter().filter(|card| Some(card.suit) == current_suit).collect();

        if valid_cards.is_empty() {
            valid_cards.extend(&game_status.my_current_hand);
        }

        let scored_cards: BTreeMap<((i32, i32, i32, i32), &Card), &Card> = valid_cards.into_iter().map(|card| {
            ((MyCardStrategy::score_card(card, game_status, player_name), card), card)
        }).collect();

        scored_cards.values().next().expect("No valid cards to play!")
    }

}<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use anyhow::{bail, Result};
use async_trait::async_trait;
use bytes::{Bytes, BytesMut};
use std::convert::TryInto;
use tokio::io::{AsyncRead, AsyncReadExt};

#[async_trait]
pub trait ReadRecordBytes {
    async fn read_full_buf_or_none(&mut self, buf: &mut BytesMut) -> Result<()>;
    async fn read_record_bytes(&mut self) -> Result<Option<Bytes>>;
}

#[async_trait]
impl<R: AsyncRead + Send + Unpin> ReadRecordBytes for R {
    async fn read_full_buf_or_none(&mut self, buf: &mut BytesMut) -> Result<()> {
        assert_eq!(buf.len(), 0);
        let n_expected = buf.capacity();

        loop {
            let n_read = self.read_buf(buf).await?;
            let n_read_total = buf.len();
            if n_read_total == n_expected {
                return Ok(());
            }
            if n_read == 0 {
                if n_read_total == 0 {
                    return Ok(());
                } else {
                    bail!(
                        "Hit EOF before filling the whole buffer, read {}, expected {}",
                        n_read_total,
                        n_expected
                    );
                }
            }
        }
    }

    async fn read_record_bytes(&mut self) -> Result<Option<Bytes>> {
        // read record size
        let mut size_buf = BytesMut::with_capacity(4);
        self.read_full_buf_or_none(&mut size_buf).await?;
        if size_buf.is_empty() {
            return Ok(None);
        }

        // read record
        let record_size = u32::from_be_bytes(size_buf.as_ref().try_into()?) as usize;
        let mut record_buf = BytesMut::with_capacity(record_size);
        self.read_full_buf_or_none(&mut record_buf).await?;
        if record_buf.is_empty() {
            bail!("Hit EOF when reading record.")
        }

        Ok(Some(record_buf.freeze()))
    }
}
<commit_msg>[backup] fix test_read_record_bytes()<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use anyhow::{bail, Result};
use async_trait::async_trait;
use bytes::{Bytes, BytesMut};
use std::convert::TryInto;
use tokio::io::{AsyncRead, AsyncReadExt};

#[async_trait]
pub trait ReadRecordBytes {
    async fn read_full_buf_or_none(&mut self, buf: &mut BytesMut) -> Result<()>;
    async fn read_record_bytes(&mut self) -> Result<Option<Bytes>>;
}

#[async_trait]
impl<R: AsyncRead + Send + Unpin> ReadRecordBytes for R {
    async fn read_full_buf_or_none(&mut self, buf: &mut BytesMut) -> Result<()> {
        assert_eq!(buf.len(), 0);
        let n_expected = buf.capacity();

        loop {
            let n_read = self.read_buf(buf).await?;
            let n_read_total = buf.len();
            if n_read_total == n_expected {
                return Ok(());
            }
            if n_read == 0 {
                if n_read_total == 0 {
                    return Ok(());
                } else {
                    bail!(
                        "Hit EOF before filling the whole buffer, read {}, expected {}",
                        n_read_total,
                        n_expected
                    );
                }
            }
        }
    }

    async fn read_record_bytes(&mut self) -> Result<Option<Bytes>> {
        // read record size
        let mut size_buf = BytesMut::with_capacity(4);
        self.read_full_buf_or_none(&mut size_buf).await?;
        if size_buf.is_empty() {
            return Ok(None);
        }

        // empty record
        let record_size = u32::from_be_bytes(size_buf.as_ref().try_into()?) as usize;
        if record_size == 0 {
            return Ok(Some(Bytes::new()));
        }

        // read record
        let mut record_buf = BytesMut::with_capacity(record_size);
        self.read_full_buf_or_none(&mut record_buf).await?;
        if record_buf.is_empty() {
            bail!("Hit EOF when reading record.")
        }

        Ok(Some(record_buf.freeze()))
    }
}

#[cfg(test)]
mod tests {
    use crate::utils::read_record_bytes::ReadRecordBytes;
    use tokio::runtime::Runtime;

    #[test]
    fn test_read_record_bytes() {
        Runtime::new().unwrap().block_on(async {
            let data = b"abc";
            let size = (data.len() as u32).to_be_bytes();

            let mut good_record = size.to_vec();
            good_record.extend_from_slice(data);

            assert_eq!(
                good_record
                    .as_slice()
                    .read_record_bytes()
                    .await
                    .unwrap()
                    .unwrap(),
                &data[..],
            );

            let mut eof: &[u8] = &[];
            assert!(eof.read_record_bytes().await.unwrap().is_none());

            let mut empty = &0u32.to_be_bytes()[..];
            assert_eq!(empty.read_record_bytes().await.unwrap().unwrap(), &[][..]);

            let mut data_missing = &1u32.to_be_bytes()[..];
            assert!(data_missing.read_record_bytes().await.is_err());

            let mut bad_len = 10u32.to_be_bytes().to_vec();
            bad_len.pop();
            assert!(bad_len.as_slice().read_record_bytes().await.is_err());

            let mut bad_data = 10u32.to_be_bytes().to_vec();
            bad_data.push(0u8);
            assert!(bad_data.as_slice().read_record_bytes().await.is_err());
        })
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use super::functions::sql_function;
use super::{is_aggregate, AsExpression};
use super::{Expression, ValidGrouping};
use crate::query_builder::*;
use crate::result::QueryResult;
use crate::sql_types::{BigInt, DieselNumericOps, SingleValue, SqlType};
use crate::backend::Backend;
use crate::{AppearsOnTable, SelectableExpression};

sql_function! {
    /// Creates a SQL `COUNT` expression
    ///
    /// As with most bare functions, this is not exported by default. You can import
    /// it specifically as `diesel::dsl::count`, or glob import
    /// `diesel::dsl::*`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use diesel::dsl::*;
    /// #
    /// # fn main() {
    /// #     use schema::animals::dsl::*;
    /// #     let connection = establish_connection();
    /// assert_eq!(Ok(1), animals.select(count(name)).first(&connection));
    /// # }
    /// ```
    #[aggregate]
    fn count<T: SqlType + SingleValue>(expr: T) -> BigInt;
}

/// Creates a SQL `COUNT(*)` expression
///
/// For selecting the count of a query, and nothing else, you can just call
/// [`count`](crate::query_dsl::QueryDsl::count())
/// on the query instead.
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::dsl::count_star`, or glob import
/// `diesel::dsl::*`
///
/// # Examples
///
/// ```rust
/// # include!("../doctest_setup.rs");
/// # use diesel::dsl::*;
/// #
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// assert_eq!(Ok(2), users.select(count_star()).first(&connection));
/// # }
/// ```
pub fn count_star() -> CountStar {
    CountStar
}

#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps, ValidGrouping)]
#[diesel(aggregate)]
#[doc(hidden)]
pub struct CountStar;

impl Expression for CountStar {
    type SqlType = BigInt;
}

impl<DB: Backend> QueryFragment<DB> for CountStar {
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("COUNT(*)");
        Ok(())
    }
}

impl_selectable_expression!(CountStar);

/// Creates a SQL `COUNT(DISTINCT ...)` expression
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::dsl::count_distinct`, or glob import
/// `diesel::dsl::*`
///
/// # Examples
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// # use diesel::dsl::*;
/// #
/// # fn main() {
/// #     use schema::posts::dsl::*;
/// #     let connection = establish_connection();
/// let unique_user_count = posts.select(count_distinct(user_id)).first(&connection);
/// assert_eq!(Ok(2), unique_user_count);
/// # }
/// ```
pub fn count_distinct<T, E>(expr: E) -> CountDistinct<T, E::Expression>
where
    T: SqlType + SingleValue,
    E: AsExpression<T>,
{
    CountDistinct {
        expr: expr.as_expression(),
        _marker: PhantomData,
    }
}

#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps)]
#[doc(hidden)]
pub struct CountDistinct<T, E> {
    expr: E,
    _marker: PhantomData<T>,
}

impl<T, E> Expression for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
    E: Expression,
{
    type SqlType = BigInt;
}

impl<T, E, GB> ValidGrouping<GB> for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
{
    type IsAggregate = is_aggregate::Yes;
}

impl<T, E, QS> SelectableExpression<QS> for CountDistinct<T, E>
where
    Self: AppearsOnTable<QS>,
    E: SelectableExpression<QS>,
{
}

impl<T, E, QS> AppearsOnTable<QS> for CountDistinct<T, E>
where
    Self: Expression,
    E: AppearsOnTable<QS>,
{
}

impl<T, E, DB> QueryFragment<DB> for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
    DB: Backend,
    for<'a> &'a E: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("COUNT(DISTINCT ");
        (&self.expr).walk_ast(out.reborrow())?;
        out.push_sql(")");
        Ok(())
    }
}
<commit_msg>fmt changes<commit_after>use std::marker::PhantomData;

use super::functions::sql_function;
use super::{is_aggregate, AsExpression};
use super::{Expression, ValidGrouping};
use crate::backend::Backend;
use crate::query_builder::*;
use crate::result::QueryResult;
use crate::sql_types::{BigInt, DieselNumericOps, SingleValue, SqlType};
use crate::{AppearsOnTable, SelectableExpression};

sql_function! {
    /// Creates a SQL `COUNT` expression
    ///
    /// As with most bare functions, this is not exported by default. You can import
    /// it specifically as `diesel::dsl::count`, or glob import
    /// `diesel::dsl::*`
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use diesel::dsl::*;
    /// #
    /// # fn main() {
    /// #     use schema::animals::dsl::*;
    /// #     let connection = establish_connection();
    /// assert_eq!(Ok(1), animals.select(count(name)).first(&connection));
    /// # }
    /// ```
    #[aggregate]
    fn count<T: SqlType + SingleValue>(expr: T) -> BigInt;
}

/// Creates a SQL `COUNT(*)` expression
///
/// For selecting the count of a query, and nothing else, you can just call
/// [`count`](crate::query_dsl::QueryDsl::count())
/// on the query instead.
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::dsl::count_star`, or glob import
/// `diesel::dsl::*`
///
/// # Examples
///
/// ```rust
/// # include!("../doctest_setup.rs");
/// # use diesel::dsl::*;
/// #
/// # fn main() {
/// #     use schema::users::dsl::*;
/// #     let connection = establish_connection();
/// assert_eq!(Ok(2), users.select(count_star()).first(&connection));
/// # }
/// ```
pub fn count_star() -> CountStar {
    CountStar
}

#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps, ValidGrouping)]
#[diesel(aggregate)]
#[doc(hidden)]
pub struct CountStar;

impl Expression for CountStar {
    type SqlType = BigInt;
}

impl<DB: Backend> QueryFragment<DB> for CountStar {
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("COUNT(*)");
        Ok(())
    }
}

impl_selectable_expression!(CountStar);

/// Creates a SQL `COUNT(DISTINCT ...)` expression
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::dsl::count_distinct`, or glob import
/// `diesel::dsl::*`
///
/// # Examples
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../doctest_setup.rs");
/// # use diesel::dsl::*;
/// #
/// # fn main() {
/// #     use schema::posts::dsl::*;
/// #     let connection = establish_connection();
/// let unique_user_count = posts.select(count_distinct(user_id)).first(&connection);
/// assert_eq!(Ok(2), unique_user_count);
/// # }
/// ```
pub fn count_distinct<T, E>(expr: E) -> CountDistinct<T, E::Expression>
where
    T: SqlType + SingleValue,
    E: AsExpression<T>,
{
    CountDistinct {
        expr: expr.as_expression(),
        _marker: PhantomData,
    }
}

#[derive(Debug, Clone, Copy, QueryId, DieselNumericOps)]
#[doc(hidden)]
pub struct CountDistinct<T, E> {
    expr: E,
    _marker: PhantomData<T>,
}

impl<T, E> Expression for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
    E: Expression,
{
    type SqlType = BigInt;
}

impl<T, E, GB> ValidGrouping<GB> for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
{
    type IsAggregate = is_aggregate::Yes;
}

impl<T, E, QS> SelectableExpression<QS> for CountDistinct<T, E>
where
    Self: AppearsOnTable<QS>,
    E: SelectableExpression<QS>,
{
}

impl<T, E, QS> AppearsOnTable<QS> for CountDistinct<T, E>
where
    Self: Expression,
    E: AppearsOnTable<QS>,
{
}

impl<T, E, DB> QueryFragment<DB> for CountDistinct<T, E>
where
    T: SqlType + SingleValue,
    DB: Backend,
    for<'a> &'a E: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("COUNT(DISTINCT ");
        (&self.expr).walk_ast(out.reborrow())?;
        out.push_sql(")");
        Ok(())
    }
}
<|endoftext|>


<commit_before>use flowgger::decoder::Decoder;
use flowgger::encoder::Encoder;
use std::io::{stderr, ErrorKind, Read, Write, BufRead, BufReader};
use std::str;
use std::sync::mpsc::SyncSender;
use super::Splitter;

pub struct NulSplitter;

impl<T: Read> Splitter<T> for NulSplitter {
    fn run(&self, buf_reader: BufReader<T>, tx: SyncSender<Vec<u8>>, decoder: Box<Decoder>, encoder: Box<Encoder>) {
        for line in buf_reader.split(0) {
            let line = match line {
                Ok(line) => line,
                Err(e) => match e.kind() {
                    ErrorKind::Interrupted => continue,
                    ErrorKind::WouldBlock => {
                        let _ = writeln!(stderr(), "Client hasn't sent any data for a while - Closing idle connection");
                        return
                    },
                    _ => return
                }
            };
            let line = match str::from_utf8(&line) {
                Err(_) => {
                    let _ = writeln!(stderr(), "Invalid UTF-8 input");
                    continue;
                }
                Ok(line) => line
            };
            if let Err(e) = handle_line(line, &tx, &decoder, &encoder) {
                let _ = writeln!(stderr(), "{}: [{}]", e, line.trim());
            }
        }
    }
}

fn handle_line(line: &str, tx: &SyncSender<Vec<u8>>, decoder: &Box<Decoder>, encoder: &Box<Encoder>) -> Result<(), &'static str> {
    let decoded = try!(decoder.decode(line));
    let reencoded = try!(encoder.encode(decoded));
    tx.send(reencoded).unwrap();
    Ok(())
}
<commit_msg>NUL splitter: tolerate extra tabs, spaces, \r\n and \n after the last \0<commit_after>use flowgger::decoder::Decoder;
use flowgger::encoder::Encoder;
use std::io::{stderr, ErrorKind, Read, Write, BufRead, BufReader};
use std::str;
use std::sync::mpsc::SyncSender;
use super::Splitter;

pub struct NulSplitter;

impl<T: Read> Splitter<T> for NulSplitter {
    fn run(&self, buf_reader: BufReader<T>, tx: SyncSender<Vec<u8>>, decoder: Box<Decoder>, encoder: Box<Encoder>) {
        for line in buf_reader.split(0) {
            let line = match line {
                Ok(line) => line,
                Err(e) => match e.kind() {
                    ErrorKind::Interrupted => continue,
                    ErrorKind::WouldBlock => {
                        let _ = writeln!(stderr(), "Client hasn't sent any data for a while - Closing idle connection");
                        return
                    },
                    _ => return
                }
            };
            let line = match str::from_utf8(&line) {
                Err(_) => {
                    let _ = writeln!(stderr(), "Invalid UTF-8 input");
                    continue;
                }
                Ok(line) => line
            };
            if let Err(e) = handle_line(line, &tx, &decoder, &encoder) {
                let line = line.trim();
                if line.len() > 0 {
                    let _ = writeln!(stderr(), "{}: [{}]", e, line.trim());
                }
            }
        }
    }
}

fn handle_line(line: &str, tx: &SyncSender<Vec<u8>>, decoder: &Box<Decoder>, encoder: &Box<Encoder>) -> Result<(), &'static str> {
    let decoded = try!(decoder.decode(line));
    let reencoded = try!(encoder.encode(decoded));
    tx.send(reencoded).unwrap();
    Ok(())
}
<|endoftext|>


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

use syn::{ItemEnum, ItemStruct};

use super::{
    api::{AnalysisPhase, Api, ApiName, FuncToConvert, TypedefKind},
    convert_error::{ConvertErrorWithContext, ErrorContext},
    ConvertError,
};
use crate::types::{Namespace, QualifiedName};

/// Run some code which may generate a ConvertError.
/// If it does, try to note the problem in our output APIs
/// such that users will see documentation of the error.
pub(crate) fn report_any_error<F, T>(
    ns: &Namespace,
    apis: &mut Vec<Api<impl AnalysisPhase>>,
    fun: F,
) -> Option<T>
where
    F: FnOnce() -> Result<T, ConvertErrorWithContext>,
{
    match fun() {
        Ok(result) => Some(result),
        Err(ConvertErrorWithContext(err, None)) => {
            eprintln!("Ignored item: {}", err);
            None
        }
        Err(ConvertErrorWithContext(err, Some(ctx))) => {
            eprintln!("Ignored item {}: {}", ctx.to_string(), err);
            apis.push(ignored_item(ns, ctx, err));
            None
        }
    }
}

/// Run some code which generates an API. Add that API, or if
/// anything goes wrong, instead add a note of the problem in our
/// output API such that users will see documentation for the problem.
pub(crate) fn convert_apis<FF, SF, EF, TF, A, B>(
    in_apis: Vec<Api<A>>,
    out_apis: &mut Vec<Api<B>>,
    mut func_conversion: FF,
    mut struct_conversion: SF,
    mut enum_conversion: EF,
    mut typedef_conversion: TF,
) where
    A: AnalysisPhase,
    B: AnalysisPhase,
    FF: FnMut(
        ApiName,
        Box<FuncToConvert>,
        A::FunAnalysis,
    ) -> Result<Option<Api<B>>, ConvertErrorWithContext>,
    SF: FnMut(
        ApiName,
        ItemStruct,
        A::StructAnalysis,
    ) -> Result<Option<Api<B>>, ConvertErrorWithContext>,
    EF: FnMut(ApiName, ItemEnum) -> Result<Option<Api<B>>, ConvertErrorWithContext>,
    TF: FnMut(
        ApiName,
        TypedefKind,
        Option<QualifiedName>,
        A::TypedefAnalysis,
    ) -> Result<Option<Api<B>>, ConvertErrorWithContext>,
{
    out_apis.extend(in_apis.into_iter().filter_map(|api| {
        let tn = api.name().clone();
        let result = match api {
            // No changes to any of these...
            Api::ConcreteType {
                name,
                rs_definition,
                cpp_definition,
            } => Ok(Some(Api::ConcreteType {
                name,
                rs_definition,
                cpp_definition,
            })),
            Api::ForwardDeclaration { name } => Ok(Some(Api::ForwardDeclaration { name })),
            Api::StringConstructor { name } => Ok(Some(Api::StringConstructor { name })),
            Api::Const { name, const_item } => Ok(Some(Api::Const { name, const_item })),
            Api::CType { name, typename } => Ok(Some(Api::CType { name, typename })),
            Api::IgnoredItem { name, err, ctx } => Ok(Some(Api::IgnoredItem { name, err, ctx })),
            // Apply a mapping to the following
            Api::Enum { name, item } => enum_conversion(name, item),
            Api::Typedef {
                name,
                item,
                old_tyname,
                analysis,
            } => typedef_conversion(name, item, old_tyname, analysis),
            Api::Function {
                name,
                fun,
                analysis,
            } => func_conversion(name, fun, analysis),
            Api::Struct {
                name,
                item,
                analysis,
            } => struct_conversion(name, item, analysis),
        };
        api_or_error(tn, result)
    }))
}

fn api_or_error<T: AnalysisPhase>(
    name: QualifiedName,
    api_or_error: Result<Option<Api<T>>, ConvertErrorWithContext>,
) -> Option<Api<T>> {
    match api_or_error {
        Ok(opt) => opt,
        Err(ConvertErrorWithContext(err, None)) => {
            eprintln!("Ignored {}: {}", name.to_string(), err);
            None
        }
        Err(ConvertErrorWithContext(err, Some(ctx))) => {
            eprintln!("Ignored {}: {}", name.to_string(), err);
            Some(ignored_item(name.get_namespace(), ctx, err))
        }
    }
}

/// Run some code which generates an API. Add that API, or if
/// anything goes wrong, instead add a note of the problem in our
/// output API such that users will see documentation for the problem.
pub(crate) fn transform_apis<F, A, B>(in_apis: Vec<Api<A>>, out_apis: &mut Vec<Api<B>>, mut fun: F)
where
    F: FnMut(Api<A>) -> Result<Option<Api<B>>, ConvertErrorWithContext>,
    A: AnalysisPhase,
    B: AnalysisPhase,
{
    out_apis.extend(in_apis.into_iter().filter_map(|api| {
        let tn = api.name().clone();
        api_or_error(tn, fun(api))
    }))
}

/// Run some code which generates an API for an item (as opposed to
/// a method). Add that API, or if
/// anything goes wrong, instead add a note of the problem in our
/// output API such that users will see documentation for the problem.
pub(crate) fn convert_item_apis<F, A, B>(
    in_apis: Vec<Api<A>>,
    out_apis: &mut Vec<Api<B>>,
    mut fun: F,
) where
    F: FnMut(Api<A>) -> Result<Option<Api<B>>, ConvertError>,
    A: AnalysisPhase,
    B: AnalysisPhase,
{
    transform_apis(in_apis, out_apis, |api| {
        let id = api.name().get_final_ident();
        fun(api).map_err(|e| ConvertErrorWithContext(e, Some(ErrorContext::Item(id))))
    })
}

fn ignored_item<A: AnalysisPhase>(ns: &Namespace, ctx: ErrorContext, err: ConvertError) -> Api<A> {
    Api::IgnoredItem {
        name: ApiName::new(ns, ctx.get_id().clone()),
        err,
        ctx,
    }
}<commit_msg>Inline another function.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use syn::{ItemEnum, ItemStruct};

use super::{
    api::{AnalysisPhase, Api, ApiName, FuncToConvert, TypedefKind},
    convert_error::{ConvertErrorWithContext, ErrorContext},
    ConvertError,
};
use crate::types::{Namespace, QualifiedName};

/// Run some code which may generate a ConvertError.
/// If it does, try to note the problem in our output APIs
/// such that users will see documentation of the error.
pub(crate) fn report_any_error<F, T>(
    ns: &Namespace,
    apis: &mut Vec<Api<impl AnalysisPhase>>,
    fun: F,
) -> Option<T>
where
    F: FnOnce() -> Result<T, ConvertErrorWithContext>,
{
    match fun() {
        Ok(result) => Some(result),
        Err(ConvertErrorWithContext(err, None)) => {
            eprintln!("Ignored item: {}", err);
            None
        }
        Err(ConvertErrorWithContext(err, Some(ctx))) => {
            eprintln!("Ignored item {}: {}", ctx.to_string(), err);
            apis.push(ignored_item(ns, ctx, err));
            None
        }
    }
}

/// Run some code which generates an API. Add that API, or if
/// anything goes wrong, instead add a note of the problem in our
/// output API such that users will see documentation for the problem.
pub(crate) fn convert_apis<FF, SF, EF, TF, A, B>(
    in_apis: Vec<Api<A>>,
    out_apis: &mut Vec<Api<B>>,
    mut func_conversion: FF,
    mut struct_conversion: SF,
    mut enum_conversion: EF,
    mut typedef_conversion: TF,
) where
    A: AnalysisPhase,
    B: AnalysisPhase,
    FF: FnMut(
        ApiName,
        Box<FuncToConvert>,
        A::FunAnalysis,
    ) -> Result<Option<Api<B>>, ConvertErrorWithContext>,
    SF: FnMut(
        ApiName,
        ItemStruct,
        A::StructAnalysis,
    ) -> Result<Option<Api<B>>, ConvertErrorWithContext>,
    EF: FnMut(ApiName, ItemEnum) -> Result<Option<Api<B>>, ConvertErrorWithContext>,
    TF: FnMut(
        ApiName,
        TypedefKind,
        Option<QualifiedName>,
        A::TypedefAnalysis,
    ) -> Result<Option<Api<B>>, ConvertErrorWithContext>,
{
    out_apis.extend(in_apis.into_iter().filter_map(|api| {
        let tn = api.name().clone();
        let result = match api {
            // No changes to any of these...
            Api::ConcreteType {
                name,
                rs_definition,
                cpp_definition,
            } => Ok(Some(Api::ConcreteType {
                name,
                rs_definition,
                cpp_definition,
            })),
            Api::ForwardDeclaration { name } => Ok(Some(Api::ForwardDeclaration { name })),
            Api::StringConstructor { name } => Ok(Some(Api::StringConstructor { name })),
            Api::Const { name, const_item } => Ok(Some(Api::Const { name, const_item })),
            Api::CType { name, typename } => Ok(Some(Api::CType { name, typename })),
            Api::IgnoredItem { name, err, ctx } => Ok(Some(Api::IgnoredItem { name, err, ctx })),
            // Apply a mapping to the following
            Api::Enum { name, item } => enum_conversion(name, item),
            Api::Typedef {
                name,
                item,
                old_tyname,
                analysis,
            } => typedef_conversion(name, item, old_tyname, analysis),
            Api::Function {
                name,
                fun,
                analysis,
            } => func_conversion(name, fun, analysis),
            Api::Struct {
                name,
                item,
                analysis,
            } => struct_conversion(name, item, analysis),
        };
        api_or_error(tn, result)
    }))
}

fn api_or_error<T: AnalysisPhase>(
    name: QualifiedName,
    api_or_error: Result<Option<Api<T>>, ConvertErrorWithContext>,
) -> Option<Api<T>> {
    match api_or_error {
        Ok(opt) => opt,
        Err(ConvertErrorWithContext(err, None)) => {
            eprintln!("Ignored {}: {}", name.to_string(), err);
            None
        }
        Err(ConvertErrorWithContext(err, Some(ctx))) => {
            eprintln!("Ignored {}: {}", name.to_string(), err);
            Some(ignored_item(name.get_namespace(), ctx, err))
        }
    }
}

/// Run some code which generates an API for an item (as opposed to
/// a method). Add that API, or if
/// anything goes wrong, instead add a note of the problem in our
/// output API such that users will see documentation for the problem.
pub(crate) fn convert_item_apis<F, A, B>(
    in_apis: Vec<Api<A>>,
    out_apis: &mut Vec<Api<B>>,
    mut fun: F,
) where
    F: FnMut(Api<A>) -> Result<Option<Api<B>>, ConvertError>,
    A: AnalysisPhase,
    B: AnalysisPhase,
{
    out_apis.extend(in_apis.into_iter().filter_map(|api| {
        let tn = api.name().clone();
        let result = fun(api).map_err(|e| {
            ConvertErrorWithContext(e, Some(ErrorContext::Item(tn.get_final_ident())))
        });
        api_or_error(tn, result)
    }))
}

fn ignored_item<A: AnalysisPhase>(ns: &Namespace, ctx: ErrorContext, err: ConvertError) -> Api<A> {
    Api::IgnoredItem {
        name: ApiName::new(ns, ctx.get_id().clone()),
        err,
        ctx,
    }
}
<|endoftext|>