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

use criterion::{measurement::Measurement, BatchSize, Bencher};
use diem_framework_releases::current_modules;
use diem_types::transaction::{SignedTransaction, Transaction};
use diem_vm::{parallel_executor::ParallelDiemVM, read_write_set_analysis::add_on_functions_list};
use language_e2e_tests::{
    account_universe::{log_balance_strategy, AUTransactionGen, AccountUniverseGen},
    executor::FakeExecutor,
    gas_costs::TXN_RESERVED,
};
use proptest::{
    collection::vec,
    strategy::{Strategy, ValueTree},
    test_runner::TestRunner,
};
use read_write_set::analyze;
use read_write_set_dynamic::NormalizedReadWriteSetAnalysis;

/// Benchmarking support for transactions.
#[derive(Clone, Debug)]
pub struct TransactionBencher<S> {
    num_accounts: usize,
    num_transactions: usize,
    strategy: S,
}

impl<S> TransactionBencher<S>
where
    S: Strategy,
    S::Value: AUTransactionGen,
{
    /// The number of accounts created by default.
    pub const DEFAULT_NUM_ACCOUNTS: usize = 100;

    /// The number of transactions created by default.
    pub const DEFAULT_NUM_TRANSACTIONS: usize = 1000;

    /// Creates a new transaction bencher with default settings.
    pub fn new(strategy: S) -> Self {
        Self {
            num_accounts: Self::DEFAULT_NUM_ACCOUNTS,
            num_transactions: Self::DEFAULT_NUM_TRANSACTIONS,
            strategy,
        }
    }

    /// Sets a custom number of accounts.
    pub fn num_accounts(&mut self, num_accounts: usize) -> &mut Self {
        self.num_accounts = num_accounts;
        self
    }

    /// Sets a custom number of transactions.
    pub fn num_transactions(&mut self, num_transactions: usize) -> &mut Self {
        self.num_transactions = num_transactions;
        self
    }

    /// Runs the bencher.
    pub fn bench<M: Measurement>(&self, b: &mut Bencher<M>) {
        b.iter_batched(
            || {
                TransactionBenchState::with_size(
                    &self.strategy,
                    self.num_accounts,
                    self.num_transactions,
                )
            },
            |state| state.execute(),
            // The input here is the entire list of signed transactions, so it's pretty large.
            BatchSize::LargeInput,
        )
    }

    /// Runs the bencher.
    pub fn bench_parallel<M: Measurement>(&self, b: &mut Bencher<M>) {
        b.iter_batched(
            || {
                ParallelBenchState::with_size(
                    &self.strategy,
                    self.num_accounts,
                    self.num_transactions,
                )
            },
            |state| state.execute(),
            // The input here is the entire list of signed transactions, so it's pretty large.
            BatchSize::LargeInput,
        )
    }
}

struct TransactionBenchState {
    // Use the fake executor for now.
    // TODO: Hook up the real executor in the future. Here's what needs to be done:
    // 1. Provide a way to construct a write set from the genesis write set + initial balances.
    // 2. Provide a trait for an executor with the functionality required for account_universe.
    // 3. Implement the trait for the fake executor.
    // 4. Implement the trait for the real executor, using the genesis write set implemented in 1
    //    and the helpers in the execution_tests crate.
    // 5. Add a type parameter that implements the trait here and switch "executor" to use it.
    // 6. Add an enum to TransactionBencher that lets callers choose between the fake and real
    //    executors.
    executor: FakeExecutor,
    transactions: Vec<SignedTransaction>,
}

impl TransactionBenchState {
    /// Creates a new benchmark state with the given number of accounts and transactions.
    fn with_size<S>(strategy: S, num_accounts: usize, num_transactions: usize) -> Self
    where
        S: Strategy,
        S::Value: AUTransactionGen,
    {
        Self::with_universe(
            strategy,
            universe_strategy(num_accounts, num_transactions),
            num_transactions,
        )
    }

    /// Creates a new benchmark state with the given account universe strategy and number of
    /// transactions.
    fn with_universe<S>(
        strategy: S,
        universe_strategy: impl Strategy<Value = AccountUniverseGen>,
        num_transactions: usize,
    ) -> Self
    where
        S: Strategy,
        S::Value: AUTransactionGen,
    {
        let mut runner = TestRunner::default();
        let universe = universe_strategy
            .new_tree(&mut runner)
            .expect("creating a new value should succeed")
            .current();

        let mut executor = FakeExecutor::from_genesis_file();
        // Run in gas-cost-stability mode for now -- this ensures that new accounts are ignored.
        // XXX We may want to include new accounts in case they have interesting performance
        // characteristics.
        let mut universe = universe.setup_gas_cost_stability(&mut executor);

        let transaction_gens = vec(strategy, num_transactions)
            .new_tree(&mut runner)
            .expect("creating a new value should succeed")
            .current();
        let transactions = transaction_gens
            .into_iter()
            .map(|txn_gen| txn_gen.apply(&mut universe).0)
            .collect();

        Self {
            executor,
            transactions,
        }
    }

    /// Executes this state in a single block.
    fn execute(self) {
        // The output is ignored here since we're just testing transaction performance, not trying
        // to assert correctness.
        self.executor
            .execute_block(self.transactions)
            .expect("VM should not fail to start");
    }
}

/// Returns a strategy for the account universe customized for benchmarks.
fn universe_strategy(
    num_accounts: usize,
    num_transactions: usize,
) -> impl Strategy<Value = AccountUniverseGen> {
    // Multiply by 5 past the number of  to provide
    let max_balance = TXN_RESERVED * num_transactions as u64 * 5;
    let balance_strategy = log_balance_strategy(max_balance);
    AccountUniverseGen::strategy(num_accounts, balance_strategy)
}

struct ParallelBenchState {
    bench_state: TransactionBenchState,
    infer_results: NormalizedReadWriteSetAnalysis,
}

impl ParallelBenchState {
    /// Creates a new benchmark state with the given number of accounts and transactions.
    fn with_size<S>(strategy: S, num_accounts: usize, num_transactions: usize) -> Self
    where
        S: Strategy,
        S::Value: AUTransactionGen,
    {
        Self {
            bench_state: TransactionBenchState::with_universe(
                strategy,
                universe_strategy(num_accounts, num_transactions),
                num_transactions,
            ),
            infer_results: analyze(current_modules().iter())
                .unwrap()
                .normalize_all_scripts(add_on_functions_list()),
        }
    }

    fn execute(self) {
        ParallelDiemVM::execute_block(
            &self.infer_results,
            self.bench_state
                .transactions
                .into_iter()
                .map(Transaction::UserTransaction)
                .collect(),
            self.bench_state.executor.get_state_view(),
        )
        .expect("VM should not fail to start");
    }
}
<commit_msg>[transaction-benchmark] Change benchmark logic to use DiemVM api<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use criterion::{measurement::Measurement, BatchSize, Bencher};
use diem_types::transaction::Transaction;
use diem_vm::{DiemVM, VMExecutor};
use language_e2e_tests::{
    account_universe::{log_balance_strategy, AUTransactionGen, AccountUniverseGen},
    executor::FakeExecutor,
    gas_costs::TXN_RESERVED,
};
use proptest::{
    collection::vec,
    strategy::{Strategy, ValueTree},
    test_runner::TestRunner,
};

/// Benchmarking support for transactions.
#[derive(Clone, Debug)]
pub struct TransactionBencher<S> {
    num_accounts: usize,
    num_transactions: usize,
    strategy: S,
}

impl<S> TransactionBencher<S>
where
    S: Strategy,
    S::Value: AUTransactionGen,
{
    /// The number of accounts created by default.
    pub const DEFAULT_NUM_ACCOUNTS: usize = 100;

    /// The number of transactions created by default.
    pub const DEFAULT_NUM_TRANSACTIONS: usize = 1000;

    /// Creates a new transaction bencher with default settings.
    pub fn new(strategy: S) -> Self {
        Self {
            num_accounts: Self::DEFAULT_NUM_ACCOUNTS,
            num_transactions: Self::DEFAULT_NUM_TRANSACTIONS,
            strategy,
        }
    }

    /// Sets a custom number of accounts.
    pub fn num_accounts(&mut self, num_accounts: usize) -> &mut Self {
        self.num_accounts = num_accounts;
        self
    }

    /// Sets a custom number of transactions.
    pub fn num_transactions(&mut self, num_transactions: usize) -> &mut Self {
        self.num_transactions = num_transactions;
        self
    }

    /// Runs the bencher.
    pub fn bench<M: Measurement>(&self, b: &mut Bencher<M>) {
        b.iter_batched(
            || {
                TransactionBenchState::with_size(
                    &self.strategy,
                    self.num_accounts,
                    self.num_transactions,
                )
            },
            |state| state.execute(),
            // The input here is the entire list of signed transactions, so it's pretty large.
            BatchSize::LargeInput,
        )
    }

    /// Runs the bencher.
    pub fn bench_parallel<M: Measurement>(&self, b: &mut Bencher<M>) {
        b.iter_batched(
            || {
                TransactionBenchState::with_size_parallel(
                    &self.strategy,
                    self.num_accounts,
                    self.num_transactions,
                )
            },
            |state| state.execute(),
            // The input here is the entire list of signed transactions, so it's pretty large.
            BatchSize::LargeInput,
        )
    }
}

struct TransactionBenchState {
    // Use the fake executor for now.
    // TODO: Hook up the real executor in the future. Here's what needs to be done:
    // 1. Provide a way to construct a write set from the genesis write set + initial balances.
    // 2. Provide a trait for an executor with the functionality required for account_universe.
    // 3. Implement the trait for the fake executor.
    // 4. Implement the trait for the real executor, using the genesis write set implemented in 1
    //    and the helpers in the execution_tests crate.
    // 5. Add a type parameter that implements the trait here and switch "executor" to use it.
    // 6. Add an enum to TransactionBencher that lets callers choose between the fake and real
    //    executors.
    executor: FakeExecutor,
    transactions: Vec<Transaction>,
}

impl TransactionBenchState {
    /// Creates a new benchmark state with the given number of accounts and transactions.
    fn with_size<S>(strategy: S, num_accounts: usize, num_transactions: usize) -> Self
    where
        S: Strategy,
        S::Value: AUTransactionGen,
    {
        Self::with_universe(
            strategy,
            universe_strategy(num_accounts, num_transactions),
            num_transactions,
        )
    }

    /// Creates a new benchmark state with the given account universe strategy and number of
    /// transactions.
    fn with_universe<S>(
        strategy: S,
        universe_strategy: impl Strategy<Value = AccountUniverseGen>,
        num_transactions: usize,
    ) -> Self
    where
        S: Strategy,
        S::Value: AUTransactionGen,
    {
        let mut runner = TestRunner::default();
        let universe = universe_strategy
            .new_tree(&mut runner)
            .expect("creating a new value should succeed")
            .current();

        let mut executor = FakeExecutor::from_genesis_file();
        // Run in gas-cost-stability mode for now -- this ensures that new accounts are ignored.
        // XXX We may want to include new accounts in case they have interesting performance
        // characteristics.
        let mut universe = universe.setup_gas_cost_stability(&mut executor);

        let transaction_gens = vec(strategy, num_transactions)
            .new_tree(&mut runner)
            .expect("creating a new value should succeed")
            .current();
        let transactions = transaction_gens
            .into_iter()
            .map(|txn_gen| Transaction::UserTransaction(txn_gen.apply(&mut universe).0))
            .collect();

        Self {
            executor,
            transactions,
        }
    }

    /// Executes this state in a single block.
    fn execute(self) {
        // The output is ignored here since we're just testing transaction performance, not trying
        // to assert correctness.
        DiemVM::execute_block(self.transactions, self.executor.get_state_view())
            .expect("VM should not fail to start");
    }

    fn with_size_parallel<S>(strategy: S, num_accounts: usize, num_transactions: usize) -> Self
    where
        S: Strategy,
        S::Value: AUTransactionGen,
    {
        let mut state = Self::with_universe(
            strategy,
            universe_strategy(num_accounts, num_transactions),
            num_transactions,
        );
        state.executor.enable_parallel_execution();

        state
    }
}

/// Returns a strategy for the account universe customized for benchmarks.
fn universe_strategy(
    num_accounts: usize,
    num_transactions: usize,
) -> impl Strategy<Value = AccountUniverseGen> {
    // Multiply by 5 past the number of  to provide
    let max_balance = TXN_RESERVED * num_transactions as u64 * 5;
    let balance_strategy = log_balance_strategy(max_balance);
    AccountUniverseGen::strategy(num_accounts, balance_strategy)
}
<|endoftext|>


<commit_before>//use crate::database::Database;
use crate::processor::ProcessingStep;
use crate::processor::ProcessorData;
//use cpp_to_rust_common::log;
use crate::common::errors::{bail, Result};
use crate::cpp_type::CppClassType;
use crate::cpp_type::CppType;
use crate::database::CppItemData;
use crate::database::DatabaseItem;
use cpp_to_rust_common::log;

fn check_type(all_items: &[&DatabaseItem], cpp_type: &CppType) -> Result<()> {
    match cpp_type {
        CppType::Class(CppClassType {
            ref name,
            ref template_arguments,
        }) => {
            if !all_items
                .iter()
                .filter_map(|item| item.cpp_data.as_type_ref())
                .any(|t| &t.name == name && t.kind.is_class())
            {
                bail!("class not found: {}", name);
            }

            if let Some(ref args) = *template_arguments {
                for arg in args {
                    check_type(all_items, arg)?;
                }
            }
        }
        CppType::Enum { name } => {
            if !all_items
                .iter()
                .filter_map(|item| item.cpp_data.as_type_ref())
                .any(|t| &t.name == name && t.kind.is_enum())
            {
                bail!("enum not found: {}", name);
            }
        }
        CppType::PointerLike { ref target, .. } => {
            check_type(all_items, target)?;
        }
        CppType::FunctionPointer(t) => {
            check_type(all_items, &t.return_type)?;

            for arg in &t.arguments {
                check_type(all_items, arg)?;
            }
        }
        _ => {}
    }
    Ok(())
}

fn is_cpp_item_resolvable(all_items: &[&DatabaseItem], item: &CppItemData) -> Result<()> {
    for cpp_type in &item.all_involved_types() {
        check_type(&all_items, cpp_type)?;
    }
    Ok(())
}

/// Runs the parser on specified data.
fn run(data: &mut ProcessorData) -> Result<()> {
    let all_items = data.all_items();
    for item in &data.current_database.items {
        if item.rust_item.is_some() {
            continue;
        }
        match is_cpp_item_resolvable(&all_items, &item.cpp_data) {
            Ok(_) => unimplemented!(),
            Err(err) => {
                log::error(format!("skipping item: {}: {}", &item.cpp_data, err));
            }
        }
    }
    // TODO: everything
    Ok(())
}

pub fn rust_name_resolver_step() -> ProcessingStep {
    // TODO: set dependencies
    ProcessingStep::new("rust_name_resolver", Vec::new(), run)
}

#[test]
fn it_should_check_functions() {
    use crate::cpp_data::CppName;
    use crate::cpp_data::CppTypeData;
    use crate::cpp_data::CppTypeDataKind;
    use crate::cpp_function::CppFunction;
    use crate::cpp_function::CppFunctionArgument;
    use crate::database::DatabaseItemSource;

    let func = CppFunction {
        name: CppName::from_one_part("foo"),
        member: None,
        operator: None,
        return_type: CppType::Void,
        arguments: vec![],
        allows_variadic_arguments: false,
        template_arguments: None,
        declaration_code: None,
        doc: None,
    };
    let func_item = DatabaseItem {
        cpp_data: CppItemData::Function(func.clone()),
        source: DatabaseItemSource::ImplicitDestructor,
        ffi_items: None,
        rust_item: None,
    };

    let func2_item = DatabaseItem {
        cpp_data: CppItemData::Function(CppFunction {
            arguments: vec![CppFunctionArgument {
                name: "a".to_string(),
                argument_type: CppType::Class(CppClassType {
                    name: CppName::from_one_part("C1"),
                    template_arguments: None,
                }),
                has_default_value: false,
            }],
            ..func
        }),
        source: DatabaseItemSource::ImplicitDestructor,
        ffi_items: None,
        rust_item: None,
    };
    let all_items = &[&func_item, &func2_item];
    assert!(is_cpp_item_resolvable(all_items, &func_item.cpp_data).is_ok());
    assert!(is_cpp_item_resolvable(all_items, &func2_item.cpp_data).is_err());

    let class_item = DatabaseItem {
        cpp_data: CppItemData::Type(CppTypeData {
            name: CppName::from_one_part("C1"),
            kind: CppTypeDataKind::Class {
                type_base: CppClassType {
                    name: CppName::from_one_part("C1"),
                    template_arguments: None,
                },
            },
            doc: None,
            is_movable: false,
        }),
        source: DatabaseItemSource::ImplicitDestructor,
        ffi_items: None,
        rust_item: None,
    };
    let all_items = &[&func_item, &func2_item, &class_item];
    assert!(is_cpp_item_resolvable(all_items, &func_item.cpp_data).is_ok());
    assert!(is_cpp_item_resolvable(all_items, &func2_item.cpp_data).is_ok());
}
<commit_msg>check for template parameters in name resolver<commit_after>//use crate::database::Database;
use crate::processor::ProcessingStep;
use crate::processor::ProcessorData;
//use cpp_to_rust_common::log;
use crate::common::errors::{bail, Result};
use crate::cpp_data::CppTypeDataKind;
use crate::cpp_type::CppType;
use crate::database::CppItemData;
use crate::database::DatabaseItem;
use cpp_to_rust_common::log;

fn check_type(all_items: &[&DatabaseItem], cpp_type: &CppType) -> Result<()> {
    match cpp_type {
        CppType::Class(class_type) => {
            let kind = CppTypeDataKind::Class {
                class_type: class_type.clone(),
            };
            if !all_items
                .iter()
                .filter_map(|item| item.cpp_data.as_type_ref())
                .any(|t| t.name == class_type.name && t.kind == kind)
            {
                bail!("class not found: {}", class_type.to_cpp_pseudo_code());
            }

            if let Some(ref template_arguments) = class_type.template_arguments {
                if template_arguments
                    .iter()
                    .any(|arg| arg.is_or_contains_template_parameter())
                {
                    bail!("template parameters are not supported");
                }
            }
        }
        CppType::Enum { name } => {
            if !all_items
                .iter()
                .filter_map(|item| item.cpp_data.as_type_ref())
                .any(|t| &t.name == name && t.kind.is_enum())
            {
                bail!("enum not found: {}", name);
            }
        }
        CppType::PointerLike { ref target, .. } => {
            check_type(all_items, target)?;
        }
        CppType::FunctionPointer(t) => {
            check_type(all_items, &t.return_type)?;

            for arg in &t.arguments {
                check_type(all_items, arg)?;
            }
        }
        CppType::TemplateParameter { .. } => {
            bail!("template parameters are not supported");
        }
        _ => {}
    }
    Ok(())
}

fn is_cpp_item_resolvable(all_items: &[&DatabaseItem], item: &CppItemData) -> Result<()> {
    for cpp_type in &item.all_involved_types() {
        check_type(&all_items, cpp_type)?;
    }
    Ok(())
}

/// Runs the parser on specified data.
fn run(data: &mut ProcessorData) -> Result<()> {
    let all_items = data.all_items();
    for item in &data.current_database.items {
        if item.rust_item.is_some() {
            continue;
        }
        match is_cpp_item_resolvable(&all_items, &item.cpp_data) {
            Ok(_) => unimplemented!(),
            Err(err) => {
                log::error(format!("skipping item: {}: {}", &item.cpp_data, err));
            }
        }
    }
    // TODO: everything
    Ok(())
}

pub fn rust_name_resolver_step() -> ProcessingStep {
    // TODO: set dependencies
    ProcessingStep::new("rust_name_resolver", Vec::new(), run)
}

#[test]
fn it_should_check_functions() {
    use crate::cpp_data::CppName;
    use crate::cpp_data::CppTypeData;
    use crate::cpp_data::CppTypeDataKind;
    use crate::cpp_function::CppFunction;
    use crate::cpp_function::CppFunctionArgument;
    use crate::database::DatabaseItemSource;

    let func = CppFunction {
        name: CppName::from_one_part("foo"),
        member: None,
        operator: None,
        return_type: CppType::Void,
        arguments: vec![],
        allows_variadic_arguments: false,
        template_arguments: None,
        declaration_code: None,
        doc: None,
    };
    let func_item = DatabaseItem {
        cpp_data: CppItemData::Function(func.clone()),
        source: DatabaseItemSource::ImplicitDestructor,
        ffi_items: None,
        rust_item: None,
    };

    let func2_item = DatabaseItem {
        cpp_data: CppItemData::Function(CppFunction {
            arguments: vec![CppFunctionArgument {
                name: "a".to_string(),
                argument_type: CppType::Class(CppClassType {
                    name: CppName::from_one_part("C1"),
                    template_arguments: None,
                }),
                has_default_value: false,
            }],
            ..func
        }),
        source: DatabaseItemSource::ImplicitDestructor,
        ffi_items: None,
        rust_item: None,
    };
    let all_items = &[&func_item, &func2_item];
    assert!(is_cpp_item_resolvable(all_items, &func_item.cpp_data).is_ok());
    assert!(is_cpp_item_resolvable(all_items, &func2_item.cpp_data).is_err());

    let class_item = DatabaseItem {
        cpp_data: CppItemData::Type(CppTypeData {
            name: CppName::from_one_part("C1"),
            kind: CppTypeDataKind::Class {
                class_type: CppClassType {
                    name: CppName::from_one_part("C1"),
                    template_arguments: None,
                },
            },
            doc: None,
            is_movable: false,
        }),
        source: DatabaseItemSource::ImplicitDestructor,
        ffi_items: None,
        rust_item: None,
    };
    let all_items = &[&func_item, &func2_item, &class_item];
    assert!(is_cpp_item_resolvable(all_items, &func_item.cpp_data).is_ok());
    assert!(is_cpp_item_resolvable(all_items, &func2_item.cpp_data).is_ok());
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::rc::Rc;

use crate::borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
use crate::borrow_check::nll::ToRegionVid;
use crate::util::liveness::{self, DefUse};
use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
use rustc::mir::{Local, Location, Mir};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;

crate fn find<'tcx>(
    mir: &Mir<'tcx>,
    regioncx: &Rc<RegionInferenceContext<'tcx>>,
    tcx: TyCtxt<'_, '_, 'tcx>,
    region_vid: RegionVid,
    start_point: Location,
) -> Option<Cause> {
    let mut uf = UseFinder {
        mir,
        regioncx,
        tcx,
        region_vid,
        start_point,
    };

    uf.find()
}

struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    mir: &'cx Mir<'tcx>,
    regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
    region_vid: RegionVid,
    start_point: Location,
}

impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
    fn find(&mut self) -> Option<Cause> {
        let mut queue = VecDeque::new();
        let mut visited = FxHashSet::default();

        queue.push_back(self.start_point);
        while let Some(p) = queue.pop_front() {
            if !self.regioncx.region_contains(self.region_vid, p) {
                continue;
            }

            if !visited.insert(p) {
                continue;
            }

            let block_data = &self.mir[p.block];

            match self.def_use(p, block_data.visitable(p.statement_index)) {
                Some(DefUseResult::Def) => {}

                Some(DefUseResult::UseLive { local }) => {
                    return Some(Cause::LiveVar(local, p));
                }

                Some(DefUseResult::UseDrop { local }) => {
                    return Some(Cause::DropVar(local, p));
                }

                None => {
                    if p.statement_index < block_data.statements.len() {
                        queue.push_back(Location {
                            statement_index: p.statement_index + 1,
                            ..p
                        });
                    } else {
                        queue.extend(
                            block_data
                                .terminator()
                                .successors()
                                .filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind())
                                .map(|&bb| Location {
                                    statement_index: 0,
                                    block: bb,
                                }),
                        );
                    }
                }
            }
        }

        None
    }

    fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
        let mut visitor = DefUseVisitor {
            mir: self.mir,
            tcx: self.tcx,
            region_vid: self.region_vid,
            def_use_result: None,
        };

        thing.apply(location, &mut visitor);

        visitor.def_use_result
    }
}

struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    mir: &'cx Mir<'tcx>,
    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
    region_vid: RegionVid,
    def_use_result: Option<DefUseResult>,
}

enum DefUseResult {
    Def,
    UseLive { local: Local },
    UseDrop { local: Local },
}

impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> {
    fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
        let local_ty = self.mir.local_decls[local].ty;

        let mut found_it = false;
        self.tcx.for_each_free_region(&local_ty, |r| {
            if r.to_region_vid() == self.region_vid {
                found_it = true;
            }
        });

        if found_it {
            self.def_use_result = match liveness::categorize(context) {
                Some(DefUse::Def) => Some(DefUseResult::Def),
                Some(DefUse::Use) => Some(DefUseResult::UseLive { local }),
                Some(DefUse::Drop) => Some(DefUseResult::UseDrop { local }),
                None => None,
            };
        }
    }
}
<commit_msg>Use successor_within_block helper<commit_after>use std::collections::VecDeque;
use std::rc::Rc;

use crate::borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
use crate::borrow_check::nll::ToRegionVid;
use crate::util::liveness::{self, DefUse};
use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor};
use rustc::mir::{Local, Location, Mir};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;

crate fn find<'tcx>(
    mir: &Mir<'tcx>,
    regioncx: &Rc<RegionInferenceContext<'tcx>>,
    tcx: TyCtxt<'_, '_, 'tcx>,
    region_vid: RegionVid,
    start_point: Location,
) -> Option<Cause> {
    let mut uf = UseFinder {
        mir,
        regioncx,
        tcx,
        region_vid,
        start_point,
    };

    uf.find()
}

struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    mir: &'cx Mir<'tcx>,
    regioncx: &'cx Rc<RegionInferenceContext<'tcx>>,
    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
    region_vid: RegionVid,
    start_point: Location,
}

impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> {
    fn find(&mut self) -> Option<Cause> {
        let mut queue = VecDeque::new();
        let mut visited = FxHashSet::default();

        queue.push_back(self.start_point);
        while let Some(p) = queue.pop_front() {
            if !self.regioncx.region_contains(self.region_vid, p) {
                continue;
            }

            if !visited.insert(p) {
                continue;
            }

            let block_data = &self.mir[p.block];

            match self.def_use(p, block_data.visitable(p.statement_index)) {
                Some(DefUseResult::Def) => {}

                Some(DefUseResult::UseLive { local }) => {
                    return Some(Cause::LiveVar(local, p));
                }

                Some(DefUseResult::UseDrop { local }) => {
                    return Some(Cause::DropVar(local, p));
                }

                None => {
                    if p.statement_index < block_data.statements.len() {
                        queue.push_back(p.successor_within_block());
                    } else {
                        queue.extend(
                            block_data
                                .terminator()
                                .successors()
                                .filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind())
                                .map(|&bb| Location {
                                    statement_index: 0,
                                    block: bb,
                                }),
                        );
                    }
                }
            }
        }

        None
    }

    fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
        let mut visitor = DefUseVisitor {
            mir: self.mir,
            tcx: self.tcx,
            region_vid: self.region_vid,
            def_use_result: None,
        };

        thing.apply(location, &mut visitor);

        visitor.def_use_result
    }
}

struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    mir: &'cx Mir<'tcx>,
    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
    region_vid: RegionVid,
    def_use_result: Option<DefUseResult>,
}

enum DefUseResult {
    Def,
    UseLive { local: Local },
    UseDrop { local: Local },
}

impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> {
    fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
        let local_ty = self.mir.local_decls[local].ty;

        let mut found_it = false;
        self.tcx.for_each_free_region(&local_ty, |r| {
            if r.to_region_vid() == self.region_vid {
                found_it = true;
            }
        });

        if found_it {
            self.def_use_result = match liveness::categorize(context) {
                Some(DefUse::Def) => Some(DefUseResult::Def),
                Some(DefUse::Use) => Some(DefUseResult::UseLive { local }),
                Some(DefUse::Drop) => Some(DefUseResult::UseDrop { local }),
                None => None,
            };
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

fn main() {
    // Pass our linker script to the top crate
    let mut ld = String::new();

    let interrupts = env::var_os("CARGO_FEATURE_INTERRUPTS").is_some();
    let static_ram = env::var_os("CARGO_FEATURE_STATIC_RAM").is_some();

    ld.push_str("
MEMORY
{
  CCRAM : ORIGIN = 0x10000000, LENGTH = 8K
  FLASH : ORIGIN = 0x08000000, LENGTH = 256K
  RAM : ORIGIN = 0x20000000, LENGTH = 40K
}

ENTRY(_reset)

SECTIONS
{
  .text ORIGIN(FLASH) :
  {
    /* Vector table */
    LONG(ORIGIN(RAM) + LENGTH(RAM));
    LONG(_reset + 1);
    KEEP(*(.text.exceptions));
    _eexceptions = .;");

    if interrupts {
        ld.push_str("
    KEEP(*(.text.interrupts));
    _einterrupts = .;");
    }

    ld.push_str("
    /* Entry point: reset handler */
    _reset = .;
    KEEP(*(.text._reset));

    *(.text.*);
    *(.rodata.*);
  } > FLASH");

    if static_ram {
        ld.push_str("
  .bss : ALIGN(4)
  {
    _sbss = .;
    *(.bss.*);
    _ebss = ALIGN(4);
  } > RAM

  .data : ALIGN(4)
  {
    _sdata = .;
    *(.data.*);
    _edata = ALIGN(4);
  } > RAM AT > FLASH

  _sidata = LOADADDR(.data);");
    }

    ld.push_str("
  /DISCARD/ :
  {
    *(.ARM.exidx.*)");

    if !static_ram {
        ld.push_str("
    *(.bss.*)
    *(.data.*)");
    }

    ld.push_str("
  }
}

/* HACK to make these symbols overrideable by _dependencies_ (they were
   already overridable by the top crate), we declare them as undefined
   (EXTERN) here. */
EXTERN(__aeabi_memclr4);
EXTERN(_default_exception_handler);
EXTERN(_init);

/* Exceptions */
PROVIDE(_nmi = _default_exception_handler);
PROVIDE(_hard_fault = _default_exception_handler);
PROVIDE(_memmanage_fault = _default_exception_handler);
PROVIDE(_bus_fault = _default_exception_handler);
PROVIDE(_usage_fault = _default_exception_handler);
PROVIDE(_svcall = _default_exception_handler);
PROVIDE(_pendsv = _default_exception_handler);
PROVIDE(_systick = _default_exception_handler);");

    if interrupts {

        ld.push_str("
/* Interrupts */
PROVIDE(_wwdg = _default_exception_handler);
PROVIDE(_pvd = _default_exception_handler);
PROVIDE(_tamper_stamp = _default_exception_handler);
PROVIDE(_rtc_wkup = _default_exception_handler);
PROVIDE(_flash = _default_exception_handler);
PROVIDE(_rcc = _default_exception_handler);
PROVIDE(_exti0 = _default_exception_handler);
PROVIDE(_exti1 = _default_exception_handler);
PROVIDE(_exti2_ts = _default_exception_handler);
PROVIDE(_exti3 = _default_exception_handler);
PROVIDE(_exti4 = _default_exception_handler);
PROVIDE(_dma1_channel1 = _default_exception_handler);
PROVIDE(_dma1_channel2 = _default_exception_handler);
PROVIDE(_dma1_channel3 = _default_exception_handler);
PROVIDE(_dma1_channel4 = _default_exception_handler);
PROVIDE(_dma1_channel5 = _default_exception_handler);
PROVIDE(_dma1_channel6 = _default_exception_handler);
PROVIDE(_dma1_channel7 = _default_exception_handler);
PROVIDE(_adc1_2 = _default_exception_handler);
PROVIDE(_usb_hp_can_tx = _default_exception_handler);
PROVIDE(_usb_lp_can_rx0 = _default_exception_handler);
PROVIDE(_can_rx1 = _default_exception_handler);
PROVIDE(_can_sce = _default_exception_handler);
PROVIDE(_exti9_5 = _default_exception_handler);
PROVIDE(_tim1_brk_tim15 = _default_exception_handler);
PROVIDE(_tim1_up_tim16 = _default_exception_handler);
PROVIDE(_tim1_trg_com_tim17 = _default_exception_handler);
PROVIDE(_tim1_cc = _default_exception_handler);
PROVIDE(_tim2 = _default_exception_handler);
PROVIDE(_tim3 = _default_exception_handler);
PROVIDE(_tim4 = _default_exception_handler);
PROVIDE(_i2c1_ev = _default_exception_handler);
PROVIDE(_i2c1_er = _default_exception_handler);
PROVIDE(_i2c2_ev = _default_exception_handler);
PROVIDE(_i2c2_er = _default_exception_handler);
PROVIDE(_spi1 = _default_exception_handler);
PROVIDE(_spi2 = _default_exception_handler);
PROVIDE(_usart1 = _default_exception_handler);
PROVIDE(_usart2 = _default_exception_handler);
PROVIDE(_usart3 = _default_exception_handler);
PROVIDE(_exti15_10 = _default_exception_handler);
PROVIDE(_rtc_alarm = _default_exception_handler);
PROVIDE(_usb_wake_up = _default_exception_handler);
PROVIDE(_tim8_brk = _default_exception_handler);
PROVIDE(_tim8_up = _default_exception_handler);
PROVIDE(_tim8_trg_com = _default_exception_handler);
PROVIDE(_tim8_cc = _default_exception_handler);
PROVIDE(_adc3 = _default_exception_handler);
PROVIDE(_fmc = _default_exception_handler);
PROVIDE(_spi3 = _default_exception_handler);
PROVIDE(_uart4 = _default_exception_handler);
PROVIDE(_uart5 = _default_exception_handler);
PROVIDE(_tim6_dac = _default_exception_handler);
PROVIDE(_tim7 = _default_exception_handler);
PROVIDE(_dma2_channel1 = _default_exception_handler);
PROVIDE(_dma2_channel2 = _default_exception_handler);
PROVIDE(_dma2_channel3 = _default_exception_handler);
PROVIDE(_dma2_channel4 = _default_exception_handler);
PROVIDE(_dma2_channel5 = _default_exception_handler);
PROVIDE(_adc4 = _default_exception_handler);
PROVIDE(_comp1_2_3 = _default_exception_handler);
PROVIDE(_comp4_5_6 = _default_exception_handler);
PROVIDE(_comp7 = _default_exception_handler);
PROVIDE(_i2c3_ev = _default_exception_handler);
PROVIDE(_i2c3_er = _default_exception_handler);
PROVIDE(_usb_hp = _default_exception_handler);
PROVIDE(_usb_lp = _default_exception_handler);
PROVIDE(_usb_wake_up_rmp = _default_exception_handler);
PROVIDE(_tim20_brk = _default_exception_handler);
PROVIDE(_tim20_up = _default_exception_handler);
PROVIDE(_tim20_trg_com = _default_exception_handler);
PROVIDE(_tim20_cc = _default_exception_handler);
PROVIDE(_fpu = _default_exception_handler);
PROVIDE(_spi4 = _default_exception_handler);");
    }

    ld.push_str("
ASSERT(_eexceptions - ORIGIN(FLASH) == 0x40, \"exceptions \
                 not linked where expected\");");

    if interrupts {
        ld.push_str("
ASSERT(_einterrupts - ORIGIN(FLASH) == 0x194, \
                     \"interrupts not linked where expected\");");
    }

    let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    File::create(out.join("stm32f3discovery.ld"))
        .unwrap()
        .write_all(ld.as_bytes())
        .unwrap();

    println!("cargo:rustc-link-search={}", out.display());
}
<commit_msg>ld: we don't to "KEEP" the _reset symbol because it's the entry point<commit_after>use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

fn main() {
    // Pass our linker script to the top crate
    let mut ld = String::new();

    let interrupts = env::var_os("CARGO_FEATURE_INTERRUPTS").is_some();
    let static_ram = env::var_os("CARGO_FEATURE_STATIC_RAM").is_some();

    ld.push_str("
MEMORY
{
  CCRAM : ORIGIN = 0x10000000, LENGTH = 8K
  FLASH : ORIGIN = 0x08000000, LENGTH = 256K
  RAM : ORIGIN = 0x20000000, LENGTH = 40K
}

ENTRY(_reset)

SECTIONS
{
  .text ORIGIN(FLASH) :
  {
    /* Vector table */
    LONG(ORIGIN(RAM) + LENGTH(RAM));
    LONG(_reset + 1);
    KEEP(*(.text.exceptions));
    _eexceptions = .;");

    if interrupts {
        ld.push_str("
    KEEP(*(.text.interrupts));
    _einterrupts = .;");
    }

    ld.push_str("
    /* Entry point: reset handler */
    _reset = .;
    *(.text._reset);

    *(.text.*);
    *(.rodata.*);
  } > FLASH");

    if static_ram {
        ld.push_str("
  .bss : ALIGN(4)
  {
    _sbss = .;
    *(.bss.*);
    _ebss = ALIGN(4);
  } > RAM

  .data : ALIGN(4)
  {
    _sdata = .;
    *(.data.*);
    _edata = ALIGN(4);
  } > RAM AT > FLASH

  _sidata = LOADADDR(.data);");
    }

    ld.push_str("
  /DISCARD/ :
  {
    *(.ARM.exidx.*)");

    if !static_ram {
        ld.push_str("
    *(.bss.*)
    *(.data.*)");
    }

    ld.push_str("
  }
}

/* HACK to make these symbols overrideable by _dependencies_ (they were
   already overridable by the top crate), we declare them as undefined
   (EXTERN) here. */
EXTERN(__aeabi_memclr4);
EXTERN(_default_exception_handler);
EXTERN(_init);

/* Exceptions */
PROVIDE(_nmi = _default_exception_handler);
PROVIDE(_hard_fault = _default_exception_handler);
PROVIDE(_memmanage_fault = _default_exception_handler);
PROVIDE(_bus_fault = _default_exception_handler);
PROVIDE(_usage_fault = _default_exception_handler);
PROVIDE(_svcall = _default_exception_handler);
PROVIDE(_pendsv = _default_exception_handler);
PROVIDE(_systick = _default_exception_handler);");

    if interrupts {

        ld.push_str("
/* Interrupts */
PROVIDE(_wwdg = _default_exception_handler);
PROVIDE(_pvd = _default_exception_handler);
PROVIDE(_tamper_stamp = _default_exception_handler);
PROVIDE(_rtc_wkup = _default_exception_handler);
PROVIDE(_flash = _default_exception_handler);
PROVIDE(_rcc = _default_exception_handler);
PROVIDE(_exti0 = _default_exception_handler);
PROVIDE(_exti1 = _default_exception_handler);
PROVIDE(_exti2_ts = _default_exception_handler);
PROVIDE(_exti3 = _default_exception_handler);
PROVIDE(_exti4 = _default_exception_handler);
PROVIDE(_dma1_channel1 = _default_exception_handler);
PROVIDE(_dma1_channel2 = _default_exception_handler);
PROVIDE(_dma1_channel3 = _default_exception_handler);
PROVIDE(_dma1_channel4 = _default_exception_handler);
PROVIDE(_dma1_channel5 = _default_exception_handler);
PROVIDE(_dma1_channel6 = _default_exception_handler);
PROVIDE(_dma1_channel7 = _default_exception_handler);
PROVIDE(_adc1_2 = _default_exception_handler);
PROVIDE(_usb_hp_can_tx = _default_exception_handler);
PROVIDE(_usb_lp_can_rx0 = _default_exception_handler);
PROVIDE(_can_rx1 = _default_exception_handler);
PROVIDE(_can_sce = _default_exception_handler);
PROVIDE(_exti9_5 = _default_exception_handler);
PROVIDE(_tim1_brk_tim15 = _default_exception_handler);
PROVIDE(_tim1_up_tim16 = _default_exception_handler);
PROVIDE(_tim1_trg_com_tim17 = _default_exception_handler);
PROVIDE(_tim1_cc = _default_exception_handler);
PROVIDE(_tim2 = _default_exception_handler);
PROVIDE(_tim3 = _default_exception_handler);
PROVIDE(_tim4 = _default_exception_handler);
PROVIDE(_i2c1_ev = _default_exception_handler);
PROVIDE(_i2c1_er = _default_exception_handler);
PROVIDE(_i2c2_ev = _default_exception_handler);
PROVIDE(_i2c2_er = _default_exception_handler);
PROVIDE(_spi1 = _default_exception_handler);
PROVIDE(_spi2 = _default_exception_handler);
PROVIDE(_usart1 = _default_exception_handler);
PROVIDE(_usart2 = _default_exception_handler);
PROVIDE(_usart3 = _default_exception_handler);
PROVIDE(_exti15_10 = _default_exception_handler);
PROVIDE(_rtc_alarm = _default_exception_handler);
PROVIDE(_usb_wake_up = _default_exception_handler);
PROVIDE(_tim8_brk = _default_exception_handler);
PROVIDE(_tim8_up = _default_exception_handler);
PROVIDE(_tim8_trg_com = _default_exception_handler);
PROVIDE(_tim8_cc = _default_exception_handler);
PROVIDE(_adc3 = _default_exception_handler);
PROVIDE(_fmc = _default_exception_handler);
PROVIDE(_spi3 = _default_exception_handler);
PROVIDE(_uart4 = _default_exception_handler);
PROVIDE(_uart5 = _default_exception_handler);
PROVIDE(_tim6_dac = _default_exception_handler);
PROVIDE(_tim7 = _default_exception_handler);
PROVIDE(_dma2_channel1 = _default_exception_handler);
PROVIDE(_dma2_channel2 = _default_exception_handler);
PROVIDE(_dma2_channel3 = _default_exception_handler);
PROVIDE(_dma2_channel4 = _default_exception_handler);
PROVIDE(_dma2_channel5 = _default_exception_handler);
PROVIDE(_adc4 = _default_exception_handler);
PROVIDE(_comp1_2_3 = _default_exception_handler);
PROVIDE(_comp4_5_6 = _default_exception_handler);
PROVIDE(_comp7 = _default_exception_handler);
PROVIDE(_i2c3_ev = _default_exception_handler);
PROVIDE(_i2c3_er = _default_exception_handler);
PROVIDE(_usb_hp = _default_exception_handler);
PROVIDE(_usb_lp = _default_exception_handler);
PROVIDE(_usb_wake_up_rmp = _default_exception_handler);
PROVIDE(_tim20_brk = _default_exception_handler);
PROVIDE(_tim20_up = _default_exception_handler);
PROVIDE(_tim20_trg_com = _default_exception_handler);
PROVIDE(_tim20_cc = _default_exception_handler);
PROVIDE(_fpu = _default_exception_handler);
PROVIDE(_spi4 = _default_exception_handler);");
    }

    ld.push_str("
ASSERT(_eexceptions - ORIGIN(FLASH) == 0x40, \"exceptions \
                 not linked where expected\");");

    if interrupts {
        ld.push_str("
ASSERT(_einterrupts - ORIGIN(FLASH) == 0x194, \
                     \"interrupts not linked where expected\");");
    }

    let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    File::create(out.join("stm32f3discovery.ld"))
        .unwrap()
        .write_all(ld.as_bytes())
        .unwrap();

    println!("cargo:rustc-link-search={}", out.display());
}
<|endoftext|>


<commit_before>extern crate gcc;

use std::process::Command;

#[derive(Default)]
struct PGConfig {
    includedir: String,
    includedir_server: String,
    libdir: String
}

fn pg_config() -> PGConfig {
    let output = Command::new("pg_config").output().unwrap_or_else(|e| {
        panic!("Failed to execute process: {}", e)
    });
    /* Sample result:
        ...
        INCLUDEDIR = /usr/local/Cellar/postgresql/9.4.5/include
        PKGINCLUDEDIR = /usr/local/Cellar/postgresql/9.4.5/include
        INCLUDEDIR-SERVER = /usr/local/Cellar/postgresql/9.4.5/include/server
        LIBDIR = /usr/local/Cellar/postgresql/9.4.5/lib
        ...
     */

    let mut config = PGConfig { ..Default::default() };

    let text = String::from_utf8(output.stdout)
                      .expect("Expected UTF-8 from call to `pg_config`.");

    for words in text.lines().map(|line| line.split_whitespace()) {
        let vec: Vec<&str> = words.collect();
        match vec[0] {
            "INCLUDEDIR"        => config.includedir = vec[2].into(),
            "INCLUDEDIR-SERVER" => config.includedir_server = vec[2].into(),
            "LIBDIR"            => config.libdir = vec[2].into(),
            _                   => {}
        }
    }

    config
}

fn main() {
    let config = pg_config();
    gcc::Config::new()
                .file("src/magic.c")
                .include(config.includedir)
                .include(config.includedir_server)
                .compile("libmagic.a");
    println!("cargo:rustc-link-search={}", config.libdir);
    println!("cargo:rustc-link-lib=pgcommon");
    println!("cargo:rustc-link-lib=pgport");
}
<commit_msg>Note linker flags (not sure how to set them)<commit_after>extern crate gcc;

use std::process::Command;

#[derive(Default)]
struct PGConfig {
    includedir: String,
    includedir_server: String,
    libdir: String
}

fn pg_config() -> PGConfig {
    let output = Command::new("pg_config").output().unwrap_or_else(|e| {
        panic!("Failed to execute process: {}", e)
    });
    /* Sample result:
        ...
        INCLUDEDIR = /usr/local/Cellar/postgresql/9.4.5/include
        PKGINCLUDEDIR = /usr/local/Cellar/postgresql/9.4.5/include
        INCLUDEDIR-SERVER = /usr/local/Cellar/postgresql/9.4.5/include/server
        LIBDIR = /usr/local/Cellar/postgresql/9.4.5/lib
        ...
     */

    let mut config = PGConfig { ..Default::default() };

    let text = String::from_utf8(output.stdout)
                      .expect("Expected UTF-8 from call to `pg_config`.");

    for words in text.lines().map(|line| line.split_whitespace()) {
        let vec: Vec<&str> = words.collect();
        match vec[0] {
            "INCLUDEDIR"        => config.includedir = vec[2].into(),
            "INCLUDEDIR-SERVER" => config.includedir_server = vec[2].into(),
            "LIBDIR"            => config.libdir = vec[2].into(),
            _                   => {}
        }
    }

    config
}

fn main() {
    let config = pg_config();
    gcc::Config::new()
                .file("src/magic.c")
                .include(config.includedir)
                .include(config.includedir_server)
                .compile("libmagic.a");
    // println!("cargo:more-args-somehow={}",
    //          "-C link-args='-Wl,-undefined,dynamic_lookup'");
}
<|endoftext|>


<commit_before>extern crate bindgen;
extern crate cc;

use bindgen::RustTarget;
use cc::Build;
use std::env;
use std::path::PathBuf;

fn main() {
	let mut c = Build::new();

	c.flag("-std=c99");
	c.file("src/c/YGEnums.c");
	c.file("src/c/YGNodeList.c");
	c.file("src/c/Yoga.c");
	c.compile("libyoga.a");

	let bindings = bindgen::Builder::default()
		.rust_target(RustTarget::Stable_1_21)
		.blacklist_type("max_align_t") // This fails `cargo test` so disable for now
		.blacklist_type("FP_INFINITE")
		.blacklist_type("FP_NAN")
		.blacklist_type("FP_NORMAL")
		.blacklist_type("FP_SUBNORMAL")
		.blacklist_type("FP_ZERO")
		.rustfmt_bindings(false)
		.rustified_enum("YG.*")
		.header("src/c/wrapper.h")
		.generate()
		.expect("Unable to generate bindings");

	let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

	bindings
		.write_to_file(out_path.join("bindings.rs"))
		.expect("Unable to write bindings!");
}
<commit_msg>Disable -Wall when building libyoga<commit_after>extern crate bindgen;
extern crate cc;

use bindgen::RustTarget;
use cc::Build;
use std::env;
use std::path::PathBuf;

fn main() {
	let mut c = Build::new();

	c.warnings(false);
	c.flag("-std=c99");
	c.file("src/c/YGEnums.c");
	c.file("src/c/YGNodeList.c");
	c.file("src/c/Yoga.c");
	c.compile("libyoga.a");

	let bindings = bindgen::Builder::default()
		.rust_target(RustTarget::Stable_1_21)
		.blacklist_type("max_align_t") // This fails `cargo test` so disable for now
		.blacklist_type("FP_INFINITE")
		.blacklist_type("FP_NAN")
		.blacklist_type("FP_NORMAL")
		.blacklist_type("FP_SUBNORMAL")
		.blacklist_type("FP_ZERO")
		.rustfmt_bindings(false)
		.rustified_enum("YG.*")
		.header("src/c/wrapper.h")
		.generate()
		.expect("Unable to generate bindings");

	let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

	bindings
		.write_to_file(out_path.join("bindings.rs"))
		.expect("Unable to write bindings!");
}
<|endoftext|>


<commit_before>extern crate rustc_version;
extern crate semver;

use std::fs::File;
use std::io::Write;

use semver::Identifier;
use rustc_version::{version_meta, Channel};

fn identifier_to_source(id: &Identifier) -> String {
    match *id {
        Identifier::Numeric(ref n) => format!("Identifier::Numeric({})", n),
        Identifier::AlphaNumeric(ref n) => format!("Identifier::AlphaNumeric({:?}.to_owned())", n),
    }
}

fn identifiers_to_source(ids: &Vec<Identifier>) -> String {
    let mut r = "vec![".as_bytes().to_vec();
    for id in ids {
        write!(r, "{}", identifier_to_source(id)).unwrap();
    }
    write!(r, "]").unwrap();
    String::from_utf8(r).unwrap()
}

fn main() {
    let mut f = File::create("src/version.rs").unwrap();

    write!(f, "
            use rustc_version::{{Channel, VersionMeta}};
            use semver::{{Identifier, Version}};
            ").unwrap();
    let version = version_meta();

    write!(f, "
            /// Returns the `rustc` SemVer version and additional metadata¬
            /// like the git short hash and build date.¬
            pub fn version_meta() -> VersionMeta {{
                VersionMeta {{
                    semver: Version {{
                        major: {major},
                        minor: {minor},
                        patch: {patch},
                        pre: {pre},
                        build: {build},
                    }},
                    git_short_hash: \"{hash}\".to_owned(),
                    date: \"{date}\".to_owned(),
                    channel: Channel::{channel},
                }}
            }}
            ",
            major = version.semver.major,
            minor = version.semver.minor,
            patch = version.semver.patch,
            pre = identifiers_to_source(&version.semver.pre),
            build = identifiers_to_source(&version.semver.build),
            hash = version.git_short_hash,
            date = version.date,
            channel = match version.channel {
                Channel::Dev => "Dev",
                Channel::Nightly => "Nightly",
                Channel::Beta => "Beta",
                Channel::Stable => "Stable",
            }
            ).unwrap();
}
<commit_msg>Fix multi identifiers<commit_after>extern crate rustc_version;
extern crate semver;

use std::fs::File;
use std::io::Write;

use semver::Identifier;
use rustc_version::{version_meta, Channel};

fn identifier_to_source(id: &Identifier) -> String {
    match *id {
        Identifier::Numeric(ref n) => format!("Identifier::Numeric({})", n),
        Identifier::AlphaNumeric(ref n) => format!("Identifier::AlphaNumeric({:?}.to_owned())", n),
    }
}

fn identifiers_to_source(ids: &Vec<Identifier>) -> String {
    let mut r = "vec![".as_bytes().to_vec();
    for id in ids {
        write!(r, "{}, ", identifier_to_source(id)).unwrap();
    }
    write!(r, "]").unwrap();
    String::from_utf8(r).unwrap()
}

fn main() {
    let mut f = File::create("src/version.rs").unwrap();

    write!(f, "
            use rustc_version::{{Channel, VersionMeta}};
            use semver::{{Identifier, Version}};
            ").unwrap();
    let version = version_meta();

    write!(f, "
            /// Returns the `rustc` SemVer version and additional metadata¬
            /// like the git short hash and build date.¬
            pub fn version_meta() -> VersionMeta {{
                VersionMeta {{
                    semver: Version {{
                        major: {major},
                        minor: {minor},
                        patch: {patch},
                        pre: {pre},
                        build: {build},
                    }},
                    git_short_hash: \"{hash}\".to_owned(),
                    date: \"{date}\".to_owned(),
                    channel: Channel::{channel},
                }}
            }}
            ",
            major = version.semver.major,
            minor = version.semver.minor,
            patch = version.semver.patch,
            pre = identifiers_to_source(&version.semver.pre),
            build = identifiers_to_source(&version.semver.build),
            hash = version.git_short_hash,
            date = version.date,
            channel = match version.channel {
                Channel::Dev => "Dev",
                Channel::Nightly => "Nightly",
                Channel::Beta => "Beta",
                Channel::Stable => "Stable",
            }
            ).unwrap();
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::process::Command;
use std::env;

fn main() {
    assert!(Command::new("make")
        .args(&["-R", "-f", "makefile.cargo"])
        .status()
        .unwrap()
        .success());
    println!("cargo:rustc-flags=-L native={}", env::var("OUT_DIR").unwrap());
}
<commit_msg>Use NUM_JOBS to control make -j<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::process::Command;
use std::env;

fn main() {
    assert!(Command::new("make")
        .args(&["-R", "-f", "makefile.cargo", &format!("-j{}", env::var("NUM_JOBS").unwrap())])
        .status()
        .unwrap()
        .success());
    println!("cargo:rustc-flags=-L native={}", env::var("OUT_DIR").unwrap());
}
<|endoftext|>


<commit_before>extern crate gcc;
extern crate bindgen;

use std::{env, process};

fn collect_args_with_prefix<'a>(cmd: &'a str, prefix: &str) -> Vec<&'a str> {
    cmd
        .split_whitespace()
        .filter(|arg| arg.starts_with(prefix))
        .collect()
}

fn main() {
    env::set_var("CC", "mpicc");
    gcc::compile_library("librsmpi.a", &["src/rsmpi.c"]);

    let output = String::from_utf8(
        process::Command::new("mpicc").arg("-show").output().unwrap().stdout).unwrap();
    let libs = collect_args_with_prefix(output.as_ref(), "-l");
    let libdirs = collect_args_with_prefix(output.as_ref(), "-L");
    let headerdirs = collect_args_with_prefix(output.as_ref(), "-I");

    for dir in libdirs.iter() { println!("cargo:rustc-link-search=native={}", &dir[2..]); }

    let mut builder = bindgen::builder();
    for lib in libs.iter() { builder.link(&lib[2..]); }
    for dir in libdirs.iter() { builder.clang_arg(*dir); }
    for dir in headerdirs.iter() { builder.clang_arg(*dir); }
    if let Some(clang_include_dir) = bindgen::get_include_dir() {
        builder.clang_arg("-I");
        builder.clang_arg(clang_include_dir);
    }
    let bindings = builder
        .header("src/rsmpi.h")
        .emit_builtins()
        .generate()
        .unwrap();

    bindings
        .write_to_file("src/ffi/functions_and_types.rs")
        .unwrap()
}
<commit_msg>Add comments to build.rs.<commit_after>// Compiles the `rsmpi` C shim library.
extern crate gcc;
// Generates the Rust header for the C API.
extern crate bindgen;

use std::{env, process};

/// splits a command line by space and collects all arguments that start with `prefix`
fn collect_args_with_prefix<'a>(cmd: &'a str, prefix: &str) -> Vec<&'a str> {
    cmd
        .split_whitespace()
        .filter(|arg| arg.starts_with(prefix))
        .collect()
}

fn main() {
    // Use `mpicc` wrapper rather than the system C compiler.
    env::set_var("CC", "mpicc");
    // Build the `rsmpi` C shim library.
    gcc::compile_library("librsmpi.a", &["src/rsmpi.c"]);

    // Capture the output of `mpicc -show`. This usually gives the actual compiler command line
    // invoked by the `mpicc` compiler wrapper.
    let output = String::from_utf8(
        process::Command::new("mpicc").arg("-show").output().unwrap().stdout).unwrap();
    // Collect the libraries that an MPI C program should be linked to...
    let libs = collect_args_with_prefix(output.as_ref(), "-l");
    // ... and the library search directories...
    let libdirs = collect_args_with_prefix(output.as_ref(), "-L");
    // ... and the header search directories.
    let headerdirs = collect_args_with_prefix(output.as_ref(), "-I");

    // Let `rustc` know about the library search directories.
    for dir in libdirs.iter() { println!("cargo:rustc-link-search=native={}", &dir[2..]); }

    let mut builder = bindgen::builder();
    // Let `bindgen` know about libraries and search directories.
    for lib in libs.iter() { builder.link(&lib[2..]); }
    for dir in libdirs.iter() { builder.clang_arg(*dir); }
    for dir in headerdirs.iter() { builder.clang_arg(*dir); }

    // Tell `bindgen` where to find system headers.
    if let Some(clang_include_dir) = bindgen::get_include_dir() {
        builder.clang_arg("-I");
        builder.clang_arg(clang_include_dir);
    }
    // Generate Rust bindings for the MPI C API.
    let bindings = builder
        .header("src/rsmpi.h")
        .emit_builtins()
        .generate()
        .unwrap();

    // Write the bindings to disk.
    bindings
        .write_to_file("src/ffi/functions_and_types.rs")
        .unwrap()
}
<|endoftext|>


<commit_before>//!
//! https://tools.ietf.org/html/rfc4551
//!
//! IMAP Extension for Conditional STORE Operation
//! or Quick Flag Changes Resynchronization
//!

// rustfmt doesn't do a very good job on nom parser invocations.
#![cfg_attr(rustfmt, rustfmt_skip)]

use crate::{parser::core::number_64, types::*};

// The highest mod-sequence value of all messages in the mailbox.
// Extends resp-test-code defined in rfc3501.
// [RFC4551 - 3.6 HIGHESTMODSEQ Status Data Items](https://tools.ietf.org/html/rfc4551#section-3.6)
// [RFC4551 - 4. Formal Syntax - resp-text-code](https://tools.ietf.org/html/rfc4551#section-4)
named!(pub (crate) resp_text_code_highest_mod_seq<ResponseCode>, do_parse!(
    tag_no_case!("HIGHESTMODSEQ ") >>
    num: number_64 >>
    (ResponseCode::HighestModSeq(num))
));

// Extends status-att/status-att-list defined in rfc3501
// [RFC4551 - 3.6 - HIGHESTMODSEQ Status Data Items](https://tools.ietf.org/html/rfc4551#section-3.6)
// [RFC4551 - 4. Formal Syntax - status-att-val](https://tools.ietf.org/html/rfc4551#section-4)
named!(pub (crate) status_att_val_highest_mod_seq<StatusAttribute>, do_parse!(
    tag_no_case!("HIGHESTMODSEQ ") >>
    mod_sequence_valzer: number_64 >>
    (StatusAttribute::HighestModSeq(mod_sequence_valzer))
));

// [RFC4551 - 4. Formal Syntax - fetch-mod-resp](https://tools.ietf.org/html/rfc4551#section-4)
named!(pub (crate) msg_att_mod_seq<AttributeValue>, do_parse!(
    tag_no_case!("MODSEQ ") >>
    num: paren_delimited!(number_64) >>
    (AttributeValue::ModSeq(num))
));
<commit_msg>Convert RFC 4551 parsers to function style<commit_after>//!
//! https://tools.ietf.org/html/rfc4551
//!
//! IMAP Extension for Conditional STORE Operation
//! or Quick Flag Changes Resynchronization
//!

use nom::{bytes::streaming::tag_no_case, sequence::tuple, IResult};

use crate::{parser::core::number_64, types::*};

// The highest mod-sequence value of all messages in the mailbox.
// Extends resp-test-code defined in rfc3501.
// [RFC4551 - 3.6 HIGHESTMODSEQ Status Data Items](https://tools.ietf.org/html/rfc4551#section-3.6)
// [RFC4551 - 4. Formal Syntax - resp-text-code](https://tools.ietf.org/html/rfc4551#section-4)
pub(crate) fn resp_text_code_highest_mod_seq(i: &[u8]) -> IResult<&[u8], ResponseCode> {
    let (i, (_, num)) = tuple((tag_no_case("HIGHESTMODSEQ "), number_64))(i)?;
    Ok((i, ResponseCode::HighestModSeq(num)))
}

// Extends status-att/status-att-list defined in rfc3501
// [RFC4551 - 3.6 - HIGHESTMODSEQ Status Data Items](https://tools.ietf.org/html/rfc4551#section-3.6)
// [RFC4551 - 4. Formal Syntax - status-att-val](https://tools.ietf.org/html/rfc4551#section-4)
pub(crate) fn status_att_val_highest_mod_seq(i: &[u8]) -> IResult<&[u8], StatusAttribute> {
    let (i, (_, num)) = tuple((tag_no_case("HIGHESTMODSEQ "), number_64))(i)?;
    Ok((i, StatusAttribute::HighestModSeq(num)))
}

// [RFC4551 - 4. Formal Syntax - fetch-mod-resp](https://tools.ietf.org/html/rfc4551#section-4)
pub(crate) fn msg_att_mod_seq(i: &[u8]) -> IResult<&[u8], AttributeValue> {
    let (i, (_, num)) = tuple((tag_no_case("MODSEQ "), number_64))(i)?;
    Ok((i, AttributeValue::ModSeq(num)))
}
<|endoftext|>


<commit_before>use core::prelude::*;
use core::iter::range_step_inclusive;
use platform::vga::{Color, COLS, ROWS, Black, White};
use platform::vga;

pub struct StdioWriter
{
	pub xpos: uint,
	pub ypos: uint,
	pub fg: Color,
	pub bg: Color
}

impl StdioWriter
{
	pub fn new() -> StdioWriter
	{
		StdioWriter
		{
			xpos: 0,
			ypos: 0,
			fg: White,
			bg: Black
		}
	}

	pub fn clear_screen(&mut self)
	{
		for x in range(0u, COLS)
		{
			for y in range(0u, ROWS)
			{
				vga::putc(x, y, 0);
				vga::setfg(x, y, self.fg);
				vga::setbg(x, y, self.bg);
			}
		}
		self.move(0, 0);
	}

	pub fn move(&mut self, x: uint, y: uint)
	{
		self.move_coords(x, y);
		self.set_cursor();
	}

	pub fn backspace(&mut self)
	{
		self.go_left();
		self.raw_print_char(' ' as u8);
		self.set_cursor();
	}

	pub fn tab(&mut self)
	{
		let x = self.xpos;
		for _ in range(0, 4 - (x % 4))
		{
			self.raw_print_char(' ' as u8);
			self.go_right();
		}
		self.set_cursor();
	}

	pub fn crlf(&mut self)
	{
		self.xpos = 0;
		self.ypos = if self.ypos == ROWS - 1 { 0 } else { self.ypos + 1 };
		self.set_cursor();
	}

	fn go_right(&mut self)
	{
		if self.xpos == COLS - 1
		{
			self.xpos = 0;
			self.ypos = (self.ypos + ROWS + 1) % ROWS;
		}
		else
		{
			self.xpos += 1;
		}
	}

	fn go_left(&mut self)
	{
		if self.xpos == 0
		{
			self.xpos = COLS - 1;
			self.ypos = (self.ypos + ROWS - 1) % ROWS;
		}
		else
		{
			self.xpos -= 1;
		}
	}

	fn move_coords(&mut self, x: uint, y: uint)
	{
		let mut newx = x;
		let mut newy = y;
		if newx >= COLS { newx = 0; newy += 1; }
		if newy >= ROWS { newy = 0; }
		self.xpos = newx;
		self.ypos = newy;
	}

	fn set_cursor(&self)
	{
		vga::move_cursor(self.xpos, self.ypos);
	}

	pub fn print_dec(&mut self, v: uint)
	{
		if v == 0
		{
			self.print_char('0');
			return;
		}

		let mut fac = 1;
		let mut nv = v;
		while fac <= v { fac *= 10; }
		fac /= 10;
		while fac > 0
		{
			let n = nv / fac;
			let c = n as u8 + '0' as u8;
			self.raw_print_char(c);
			self.go_right();
			nv -= n * fac;
			fac /= 10;
		}
		self.set_cursor();
	}

	pub fn print_bin(&mut self, v: uint, sz: uint)
	{
		self.print_screen("0b");

		for i in range_step_inclusive(sz as int - 1, 0, -1)
		{
			let c = match (v >> (i as uint)) & 0x1
			{
				0 => '0',
				_ => '1',
			} as u8;
			self.raw_print_char(c);
			self.go_right();
		}
		self.set_cursor();
	}

	pub fn print_hex(&mut self, v: uint, sz: uint)
	{
		self.print_screen("0x");

		for i in range_step_inclusive(sz as int - 4, 0i, -4)
		{
			let c = match (v >> (i as uint)) & 0xF
			{
				c if c <= 9 => c + '0' as uint,
				c => c + -10 + 'A' as uint,
			} as u8;
			self.raw_print_char(c);
			self.go_right();
		}
		self.set_cursor();
	}

	pub fn print_char(&mut self, value: char)
	{
		self.raw_print_char(value as u8);
		self.go_right();
		self.set_cursor();
	}

	fn raw_print_char(&self, value: u8)
	{
		vga::putc(self.xpos, self.ypos, value as u8);
		vga::setfg(self.xpos, self.ypos, self.fg);
		vga::setbg(self.xpos, self.ypos, self.bg);
	}

	pub fn print_screen(&mut self, value: &str)
	{
		for c in value.bytes()
		{
			self.raw_print_char(c);
			self.go_right();
		}
		self.set_cursor();
	}
}

impl ::core::fmt::FormatWriter for StdioWriter
{
	fn write(&mut self, bytes: &[u8]) -> ::core::fmt::Result
	{
		for b in bytes.iter()
		{
			self.raw_print_char(*b);
			self.go_right();
		}
		self.set_cursor();
		Ok(())
	}
}
<commit_msg>More logical way of clearing the screen<commit_after>use core::prelude::*;
use core::iter::range_step_inclusive;
use platform::vga::{Color, COLS, ROWS, Black, White};
use platform::vga;

pub struct StdioWriter
{
	pub xpos: uint,
	pub ypos: uint,
	pub fg: Color,
	pub bg: Color
}

impl StdioWriter
{
	pub fn new() -> StdioWriter
	{
		StdioWriter
		{
			xpos: 0,
			ypos: 0,
			fg: White,
			bg: Black
		}
	}

	pub fn clear_screen(&mut self)
	{
		for y in range(0u, ROWS)
		{
			for x in range(0u, COLS)
			{
				vga::putc(x, y, 0);
				vga::setfg(x, y, self.fg);
				vga::setbg(x, y, self.bg);
			}
		}
		self.move(0, 0);
	}

	pub fn move(&mut self, x: uint, y: uint)
	{
		self.move_coords(x, y);
		self.set_cursor();
	}

	pub fn backspace(&mut self)
	{
		self.go_left();
		self.raw_print_char(' ' as u8);
		self.set_cursor();
	}

	pub fn tab(&mut self)
	{
		let x = self.xpos;
		for _ in range(0, 4 - (x % 4))
		{
			self.raw_print_char(' ' as u8);
			self.go_right();
		}
		self.set_cursor();
	}

	pub fn crlf(&mut self)
	{
		self.xpos = 0;
		self.ypos = if self.ypos == ROWS - 1 { 0 } else { self.ypos + 1 };
		self.set_cursor();
	}

	fn go_right(&mut self)
	{
		if self.xpos == COLS - 1
		{
			self.xpos = 0;
			self.ypos = (self.ypos + ROWS + 1) % ROWS;
		}
		else
		{
			self.xpos += 1;
		}
	}

	fn go_left(&mut self)
	{
		if self.xpos == 0
		{
			self.xpos = COLS - 1;
			self.ypos = (self.ypos + ROWS - 1) % ROWS;
		}
		else
		{
			self.xpos -= 1;
		}
	}

	fn move_coords(&mut self, x: uint, y: uint)
	{
		let mut newx = x;
		let mut newy = y;
		if newx >= COLS { newx = 0; newy += 1; }
		if newy >= ROWS { newy = 0; }
		self.xpos = newx;
		self.ypos = newy;
	}

	fn set_cursor(&self)
	{
		vga::move_cursor(self.xpos, self.ypos);
	}

	pub fn print_dec(&mut self, v: uint)
	{
		if v == 0
		{
			self.print_char('0');
			return;
		}

		let mut fac = 1;
		let mut nv = v;
		while fac <= v { fac *= 10; }
		fac /= 10;
		while fac > 0
		{
			let n = nv / fac;
			let c = n as u8 + '0' as u8;
			self.raw_print_char(c);
			self.go_right();
			nv -= n * fac;
			fac /= 10;
		}
		self.set_cursor();
	}

	pub fn print_bin(&mut self, v: uint, sz: uint)
	{
		self.print_screen("0b");

		for i in range_step_inclusive(sz as int - 1, 0, -1)
		{
			let c = match (v >> (i as uint)) & 0x1
			{
				0 => '0',
				_ => '1',
			} as u8;
			self.raw_print_char(c);
			self.go_right();
		}
		self.set_cursor();
	}

	pub fn print_hex(&mut self, v: uint, sz: uint)
	{
		self.print_screen("0x");

		for i in range_step_inclusive(sz as int - 4, 0i, -4)
		{
			let c = match (v >> (i as uint)) & 0xF
			{
				c if c <= 9 => c + '0' as uint,
				c => c + -10 + 'A' as uint,
			} as u8;
			self.raw_print_char(c);
			self.go_right();
		}
		self.set_cursor();
	}

	pub fn print_char(&mut self, value: char)
	{
		self.raw_print_char(value as u8);
		self.go_right();
		self.set_cursor();
	}

	fn raw_print_char(&self, value: u8)
	{
		vga::putc(self.xpos, self.ypos, value as u8);
		vga::setfg(self.xpos, self.ypos, self.fg);
		vga::setbg(self.xpos, self.ypos, self.bg);
	}

	pub fn print_screen(&mut self, value: &str)
	{
		for c in value.bytes()
		{
			self.raw_print_char(c);
			self.go_right();
		}
		self.set_cursor();
	}
}

impl ::core::fmt::FormatWriter for StdioWriter
{
	fn write(&mut self, bytes: &[u8]) -> ::core::fmt::Result
	{
		for b in bytes.iter()
		{
			self.raw_print_char(*b);
			self.go_right();
		}
		self.set_cursor();
		Ok(())
	}
}
<|endoftext|>


<commit_before>//! [GET /_matrix/client/r0/publicRooms](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-publicrooms)

use js_int::UInt;
use ruma_api::ruma_api;

use super::PublicRoomsChunk;

ruma_api! {
    metadata: {
        description: "Get the list of rooms in this homeserver's public directory.",
        method: GET,
        name: "get_public_rooms",
        path: "/_matrix/client/r0/publicRooms",
        rate_limited: false,
        requires_authentication: false,
    }

    request: {
        /// Limit for the number of results to return.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub limit: Option<UInt>,

        /// Pagination token from a previous request.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub since: Option<&'a str>,

        /// The server to fetch the public room lists from.
        ///
        /// `None` means the server this request is sent to.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub server: Option<&'a str>,
    }

    response: {
        /// A paginated chunk of public rooms.
        pub chunk: Vec<PublicRoomsChunk>,

        /// A pagination token for the response.
        pub next_batch: Option<String>,

        /// A pagination token that allows fetching previous results.
        pub prev_batch: Option<String>,

        /// An estimate on the total number of public rooms, if the server has an estimate.
        pub total_room_count_estimate: Option<UInt>,
    }

    error: crate::Error
}

#[test]
fn construct_request_from_refs() {
    let req: http::Request<Vec<u8>> =
        Request { limit: Some(js_int::uint!(10)), since: Some("hello"), server: Some("address") }
            .try_into_http_request("https://homeserver.tld", Some("auth_tok"))
            .unwrap();

    let uri = req.uri();
    let query = uri.query().unwrap();

    assert_eq!(uri.path(), "/_matrix/client/r0/publicRooms");
    assert!(query.contains("since=hello"));
    assert!(query.contains("limit=10"));
    assert!(query.contains("server=address"));
}

#[test]
fn construct_response_from_refs() {
    use std::convert::TryInto;

    let res: http::Response<Vec<u8>> = Response {
        chunk: vec![],
        next_batch: Some("next_batch_token".into()),
        prev_batch: Some("prev_batch_token".into()),
        total_room_count_estimate: Some(js_int::uint!(10)),
    }
    .try_into()
    .unwrap();

    assert_eq!(
        String::from_utf8_lossy(res.body()),
        r#"{"chunk":[],"next_batch":"next_batch_token","prev_batch":"prev_batch_token","total_room_count_estimate":10}"#
    );
}
<commit_msg>client-api: Move tests in get_public_rooms into tests module<commit_after>//! [GET /_matrix/client/r0/publicRooms](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-publicrooms)

use js_int::UInt;
use ruma_api::ruma_api;

use super::PublicRoomsChunk;

ruma_api! {
    metadata: {
        description: "Get the list of rooms in this homeserver's public directory.",
        method: GET,
        name: "get_public_rooms",
        path: "/_matrix/client/r0/publicRooms",
        rate_limited: false,
        requires_authentication: false,
    }

    request: {
        /// Limit for the number of results to return.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub limit: Option<UInt>,

        /// Pagination token from a previous request.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub since: Option<&'a str>,

        /// The server to fetch the public room lists from.
        ///
        /// `None` means the server this request is sent to.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub server: Option<&'a str>,
    }

    response: {
        /// A paginated chunk of public rooms.
        pub chunk: Vec<PublicRoomsChunk>,

        /// A pagination token for the response.
        pub next_batch: Option<String>,

        /// A pagination token that allows fetching previous results.
        pub prev_batch: Option<String>,

        /// An estimate on the total number of public rooms, if the server has an estimate.
        pub total_room_count_estimate: Option<UInt>,
    }

    error: crate::Error
}

#[cfg(test)]
mod tests {
    use std::convert::TryInto;

    use js_int::uint;
    use ruma_api::Endpoint as _;

    use super::{Request, Response};

    #[test]
    fn construct_request_from_refs() {
        let req: http::Request<Vec<u8>> =
            Request { limit: Some(uint!(10)), since: Some("hello"), server: Some("address") }
                .try_into_http_request("https://homeserver.tld", Some("auth_tok"))
                .unwrap();

        let uri = req.uri();
        let query = uri.query().unwrap();

        assert_eq!(uri.path(), "/_matrix/client/r0/publicRooms");
        assert!(query.contains("since=hello"));
        assert!(query.contains("limit=10"));
        assert!(query.contains("server=address"));
    }

    #[test]
    fn construct_response_from_refs() {
        let res: http::Response<Vec<u8>> = Response {
            chunk: vec![],
            next_batch: Some("next_batch_token".into()),
            prev_batch: Some("prev_batch_token".into()),
            total_room_count_estimate: Some(uint!(10)),
        }
        .try_into()
        .unwrap();

        assert_eq!(
            String::from_utf8_lossy(res.body()),
            r#"{"chunk":[],"next_batch":"next_batch_token","prev_batch":"prev_batch_token","total_room_count_estimate":10}"#
        );
    }
}
<|endoftext|>