<commit_before>// Copyright 2016 bluss and ndarray developers.
//
// 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.

extern crate rand;
extern crate ndarray;

use std::ptr;

use rand::Rng;
use rand::distributions::Sample;
use rand::distributions::IndependentSample;

use ndarray::{
    ArrayBase,
    Dimension,
    DataOwned,
};

/// Constructors for n-dimensional arrays with random elements.
///
/// This trait extends ndarray’s `ArrayBase` and can not be implemented
/// for other types.
///
/// The default Rng is a fast automatically seeded rng (currently `rand::weak_rng`).
pub trait RandomExt<S, D>
    where S: DataOwned,
          D: Dimension,
{
    /// Create an array with shape `dim` with elements drawn from
    /// `distribution`  using the default rng.
    ///
    /// ```
    /// extern crate rand;
    /// extern crate ndarray;
    /// extern crate ndarray_rand;
    ///
    /// use rand::distributions::Range;
    /// use ndarray::OwnedArray;
    /// use ndarray_rand::RandomExt;
    ///
    /// # fn main() {
    /// let a = OwnedArray::random((2, 5), Range::new(0., 10.));
    /// println!("{:8.4}", a);
    /// // Output:
    /// // [[  8.6900,   6.9824,   3.8922,   6.5861,   2.4890],
    /// //  [  0.0914,   5.5186,   5.8135,   5.2361,   3.1879]]
    /// # }
    fn random<IdS>(dim: D, distribution: IdS) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>;

    /// Create an array with shape `dim` with elements drawn from
    /// `distribution`, using a specific Rng `rng`.
    fn random_using<IdS, R>(dim: D, distribution: IdS, rng: &mut R) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>,
              R: Rng;
}

impl<S, D> RandomExt<S, D> for ArrayBase<S, D>
    where S: DataOwned,
          D: Dimension,
{
    fn random<IdS>(dim: D, dist: IdS) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>
    {
        Self::random_using(dim, dist, &mut rand::weak_rng())
    }

    fn random_using<IdS, R>(dim: D, dist: IdS, rng: &mut R) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>,
              R: Rng
    {
        unsafe {
            let elements = to_vec((0..dim.size()).map(move |_| dist.ind_sample(rng)));
            Self::from_vec_dim(dim, elements).unwrap()
        }
    }
}

/// Like Iterator::collect, but only for trusted length iterators
unsafe fn to_vec<I>(iter: I) -> Vec<I::Item>
    where I: ExactSizeIterator
{
    // Use an `unsafe` block to do this efficiently.
    // We know that iter will produce exactly .size() elements,
    // and the loop can vectorize if it's clean (without branch to grow the vector).
    let (size, _) = iter.size_hint();
    let mut result = Vec::with_capacity(size);
    let mut out_ptr = result.as_mut_ptr();
    let mut len = 0;
    for elt in iter {
        ptr::write(out_ptr, elt);
        len += 1;
        result.set_len(len);
        out_ptr = out_ptr.offset(1);
    }
    debug_assert_eq!(size, result.len());
    result
}

/// A wrapper type that allows casting f64 distributions to f32
#[derive(Copy, Clone, Debug)]
pub struct F32<S>(pub S);

impl<S> Sample<f32> for F32<S>
    where S: Sample<f64>
{
    fn sample<R>(&mut self, rng: &mut R) -> f32 where R: Rng {
        self.0.sample(rng) as f32
    }
}

impl<S> IndependentSample<f32> for F32<S>
    where S: IndependentSample<f64>
{
    fn ind_sample<R>(&self, rng: &mut R) -> f32 where R: Rng {
        self.0.ind_sample(rng) as f32
    }
}
<commit_msg>ndarray-rand: kill to_vec because it doesn't make a difference<commit_after>// Copyright 2016 bluss and ndarray developers.
//
// 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.

extern crate rand;
extern crate ndarray;

use std::iter::FromIterator;

use rand::Rng;
use rand::distributions::Sample;
use rand::distributions::IndependentSample;

use ndarray::{
    ArrayBase,
    Dimension,
    DataOwned,
};

/// Constructors for n-dimensional arrays with random elements.
///
/// This trait extends ndarray’s `ArrayBase` and can not be implemented
/// for other types.
///
/// The default Rng is a fast automatically seeded rng (currently `rand::weak_rng`).
pub trait RandomExt<S, D>
    where S: DataOwned,
          D: Dimension,
{
    /// Create an array with shape `dim` with elements drawn from
    /// `distribution`  using the default rng.
    ///
    /// ```
    /// extern crate rand;
    /// extern crate ndarray;
    /// extern crate ndarray_rand;
    ///
    /// use rand::distributions::Range;
    /// use ndarray::OwnedArray;
    /// use ndarray_rand::RandomExt;
    ///
    /// # fn main() {
    /// let a = OwnedArray::random((2, 5), Range::new(0., 10.));
    /// println!("{:8.4}", a);
    /// // Output:
    /// // [[  8.6900,   6.9824,   3.8922,   6.5861,   2.4890],
    /// //  [  0.0914,   5.5186,   5.8135,   5.2361,   3.1879]]
    /// # }
    fn random<IdS>(dim: D, distribution: IdS) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>;

    /// Create an array with shape `dim` with elements drawn from
    /// `distribution`, using a specific Rng `rng`.
    fn random_using<IdS, R>(dim: D, distribution: IdS, rng: &mut R) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>,
              R: Rng;
}

impl<S, D> RandomExt<S, D> for ArrayBase<S, D>
    where S: DataOwned,
          D: Dimension,
{
    fn random<IdS>(dim: D, dist: IdS) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>
    {
        Self::random_using(dim, dist, &mut rand::weak_rng())
    }

    fn random_using<IdS, R>(dim: D, dist: IdS, rng: &mut R) -> ArrayBase<S, D>
        where IdS: IndependentSample<S::Elem>,
              R: Rng
    {
        unsafe {
            let elements = Vec::from_iter((0..dim.size()).map(move |_| dist.ind_sample(rng)));
            Self::from_vec_dim(dim, elements).unwrap()
        }
    }
}

/// A wrapper type that allows casting f64 distributions to f32
#[derive(Copy, Clone, Debug)]
pub struct F32<S>(pub S);

impl<S> Sample<f32> for F32<S>
    where S: Sample<f64>
{
    fn sample<R>(&mut self, rng: &mut R) -> f32 where R: Rng {
        self.0.sample(rng) as f32
    }
}

impl<S> IndependentSample<f32> for F32<S>
    where S: IndependentSample<f64>
{
    fn ind_sample<R>(&self, rng: &mut R) -> f32 where R: Rng {
        self.0.ind_sample(rng) as f32
    }
}
<|endoftext|>


<commit_before>use hir::HirDisplay;
use syntax::{
    ast::{self, AstNode, LetStmt, NameOwner},
    TextRange,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: add_explicit_type
//
// Specify type for a let binding.
//
// ```
// fn main() {
//     let x$0 = 92;
// }
// ```
// ->
// ```
// fn main() {
//     let x: i32 = 92;
// }
// ```
pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let let_stmt = ctx.find_node_at_offset::<LetStmt>()?;
    let module = ctx.sema.scope(let_stmt.syntax()).module()?;
    let expr = let_stmt.initializer()?;
    // Must be a binding
    let pat = match let_stmt.pat()? {
        ast::Pat::IdentPat(bind_pat) => bind_pat,
        _ => return None,
    };
    let pat_range = pat.syntax().text_range();
    // The binding must have a name
    let name = pat.name()?;
    let name_range = name.syntax().text_range();

    // Assist should only be applicable if cursor is between 'let' and '='
    let cursor_in_range = {
        let stmt_range = let_stmt.syntax().text_range();
        let eq_range = let_stmt.eq_token()?.text_range();
        let let_range = TextRange::new(stmt_range.start(), eq_range.start());
        let_range.contains_range(ctx.frange.range)
    };
    if !cursor_in_range {
        cov_mark::hit!(add_explicit_type_not_applicable_if_cursor_after_equals);
        return None;
    }

    // Assist not applicable if the type has already been specified
    // and it has no placeholders
    let ascribed_ty = let_stmt.ty();
    if let Some(ty) = &ascribed_ty {
        if ty.syntax().descendants().find_map(ast::InferType::cast).is_none() {
            cov_mark::hit!(add_explicit_type_not_applicable_if_ty_already_specified);
            return None;
        }
    }

    // Infer type
    let ty = ctx.sema.type_of_expr(&expr)?;
    if ty.contains_unknown() || ty.is_closure() {
        cov_mark::hit!(add_explicit_type_not_applicable_if_ty_not_inferred);
        return None;
    }

    let inferred_type = ty.display_source_code(ctx.db(), module.into()).ok()?;
    acc.add(
        AssistId("add_explicit_type", AssistKind::RefactorRewrite),
        format!("Insert explicit type `{}`", inferred_type),
        pat_range,
        |builder| match ascribed_ty {
            Some(ascribed_ty) => {
                builder.replace(ascribed_ty.syntax().text_range(), inferred_type);
            }
            None => {
                builder.insert(name_range.end(), format!(": {}", inferred_type));
            }
        },
    )
}

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

    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    #[test]
    fn add_explicit_type_target() {
        check_assist_target(add_explicit_type, r#"fn f() { let a$0 = 1; }"#, "a");
    }

    #[test]
    fn add_explicit_type_works_for_simple_expr() {
        check_assist(
            add_explicit_type,
            r#"fn f() { let a$0 = 1; }"#,
            r#"fn f() { let a: i32 = 1; }"#,
        );
    }

    #[test]
    fn add_explicit_type_works_for_underscore() {
        check_assist(
            add_explicit_type,
            r#"fn f() { let a$0: _ = 1; }"#,
            r#"fn f() { let a: i32 = 1; }"#,
        );
    }

    #[test]
    fn add_explicit_type_works_for_nested_underscore() {
        check_assist(
            add_explicit_type,
            r#"
enum Option<T> { Some(T), None }

fn f() {
    let a$0: Option<_> = Option::Some(1);
}
"#,
            r#"
enum Option<T> { Some(T), None }

fn f() {
    let a: Option<i32> = Option::Some(1);
}
"#,
        );
    }

    #[test]
    fn add_explicit_type_works_for_macro_call() {
        check_assist(
            add_explicit_type,
            r"macro_rules! v { () => {0u64} } fn f() { let a$0 = v!(); }",
            r"macro_rules! v { () => {0u64} } fn f() { let a: u64 = v!(); }",
        );
    }

    #[test]
    fn add_explicit_type_works_for_macro_call_recursive() {
        check_assist(
            add_explicit_type,
            r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a$0 = v!(); }"#,
            r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a: u64 = v!(); }"#,
        );
    }

    #[test]
    fn add_explicit_type_not_applicable_if_ty_not_inferred() {
        cov_mark::check!(add_explicit_type_not_applicable_if_ty_not_inferred);
        check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0 = None; }"#);
    }

    #[test]
    fn add_explicit_type_not_applicable_if_ty_already_specified() {
        cov_mark::check!(add_explicit_type_not_applicable_if_ty_already_specified);
        check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0: i32 = 1; }"#);
    }

    #[test]
    fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() {
        check_assist_not_applicable(
            add_explicit_type,
            r#"fn f() { let a$0: (i32, i32) = (3, 4); }"#,
        );
    }

    #[test]
    fn add_explicit_type_not_applicable_if_cursor_after_equals() {
        cov_mark::check!(add_explicit_type_not_applicable_if_cursor_after_equals);
        check_assist_not_applicable(
            add_explicit_type,
            r#"fn f() {let a =$0 match 1 {2 => 3, 3 => 5};}"#,
        )
    }

    #[test]
    fn add_explicit_type_not_applicable_if_cursor_before_let() {
        check_assist_not_applicable(
            add_explicit_type,
            r#"fn f() $0{let a = match 1 {2 => 3, 3 => 5};}"#,
        )
    }

    #[test]
    fn closure_parameters_are_not_added() {
        check_assist_not_applicable(
            add_explicit_type,
            r#"
fn main() {
    let multiply_by_two$0 = |i| i * 3;
    let six = multiply_by_two(2);
}
"#,
        )
    }

    /// https://github.com/rust-analyzer/rust-analyzer/issues/2922
    #[test]
    fn regression_issue_2922() {
        check_assist(
            add_explicit_type,
            r#"
fn main() {
    let $0v = [0.0; 2];
}
"#,
            r#"
fn main() {
    let v: [f64; 2] = [0.0; 2];
}
"#,
        );
        // note: this may break later if we add more consteval. it just needs to be something that our
        // consteval engine doesn't understand
        check_assist_not_applicable(
            add_explicit_type,
            r#"
fn main() {
    let $0l = [0.0; 2+2];
}
"#,
        );
    }

    #[test]
    fn default_generics_should_not_be_added() {
        check_assist(
            add_explicit_type,
            r#"
struct Test<K, T = u8> { k: K, t: T }

fn main() {
    let test$0 = Test { t: 23u8, k: 33 };
}
"#,
            r#"
struct Test<K, T = u8> { k: K, t: T }

fn main() {
    let test: Test<i32> = Test { t: 23u8, k: 33 };
}
"#,
        );
    }
}
<commit_msg>add_explicit_type respects `@` patterns<commit_after>use hir::HirDisplay;
use syntax::{
    ast::{self, AstNode, LetStmt},
    TextRange,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: add_explicit_type
//
// Specify type for a let binding.
//
// ```
// fn main() {
//     let x$0 = 92;
// }
// ```
// ->
// ```
// fn main() {
//     let x: i32 = 92;
// }
// ```
pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let let_stmt = ctx.find_node_at_offset::<LetStmt>()?;
    let module = ctx.sema.scope(let_stmt.syntax()).module()?;
    let expr = let_stmt.initializer()?;
    // Must be a binding
    let pat = match let_stmt.pat()? {
        ast::Pat::IdentPat(bind_pat) => bind_pat,
        _ => return None,
    };
    let pat_range = pat.syntax().text_range();

    // Assist should only be applicable if cursor is between 'let' and '='
    let cursor_in_range = {
        let stmt_range = let_stmt.syntax().text_range();
        let eq_range = let_stmt.eq_token()?.text_range();
        let let_range = TextRange::new(stmt_range.start(), eq_range.start());
        let_range.contains_range(ctx.frange.range)
    };
    if !cursor_in_range {
        cov_mark::hit!(add_explicit_type_not_applicable_if_cursor_after_equals);
        return None;
    }

    // Assist not applicable if the type has already been specified
    // and it has no placeholders
    let ascribed_ty = let_stmt.ty();
    if let Some(ty) = &ascribed_ty {
        if ty.syntax().descendants().find_map(ast::InferType::cast).is_none() {
            cov_mark::hit!(add_explicit_type_not_applicable_if_ty_already_specified);
            return None;
        }
    }

    // Infer type
    let ty = ctx.sema.type_of_expr(&expr)?;
    if ty.contains_unknown() || ty.is_closure() {
        cov_mark::hit!(add_explicit_type_not_applicable_if_ty_not_inferred);
        return None;
    }

    let inferred_type = ty.display_source_code(ctx.db(), module.into()).ok()?;
    acc.add(
        AssistId("add_explicit_type", AssistKind::RefactorRewrite),
        format!("Insert explicit type `{}`", inferred_type),
        pat_range,
        |builder| match ascribed_ty {
            Some(ascribed_ty) => {
                builder.replace(ascribed_ty.syntax().text_range(), inferred_type);
            }
            None => {
                builder.insert(pat_range.end(), format!(": {}", inferred_type));
            }
        },
    )
}

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

    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};

    #[test]
    fn add_explicit_type_target() {
        check_assist_target(add_explicit_type, r#"fn f() { let a$0 = 1; }"#, "a");
    }

    #[test]
    fn add_explicit_type_works_for_simple_expr() {
        check_assist(
            add_explicit_type,
            r#"fn f() { let a$0 = 1; }"#,
            r#"fn f() { let a: i32 = 1; }"#,
        );
    }

    #[test]
    fn add_explicit_type_works_for_underscore() {
        check_assist(
            add_explicit_type,
            r#"fn f() { let a$0: _ = 1; }"#,
            r#"fn f() { let a: i32 = 1; }"#,
        );
    }

    #[test]
    fn add_explicit_type_works_for_nested_underscore() {
        check_assist(
            add_explicit_type,
            r#"
enum Option<T> { Some(T), None }

fn f() {
    let a$0: Option<_> = Option::Some(1);
}
"#,
            r#"
enum Option<T> { Some(T), None }

fn f() {
    let a: Option<i32> = Option::Some(1);
}
"#,
        );
    }

    #[test]
    fn add_explicit_type_works_for_macro_call() {
        check_assist(
            add_explicit_type,
            r"macro_rules! v { () => {0u64} } fn f() { let a$0 = v!(); }",
            r"macro_rules! v { () => {0u64} } fn f() { let a: u64 = v!(); }",
        );
    }

    #[test]
    fn add_explicit_type_works_for_macro_call_recursive() {
        check_assist(
            add_explicit_type,
            r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a$0 = v!(); }"#,
            r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a: u64 = v!(); }"#,
        );
    }

    #[test]
    fn add_explicit_type_not_applicable_if_ty_not_inferred() {
        cov_mark::check!(add_explicit_type_not_applicable_if_ty_not_inferred);
        check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0 = None; }"#);
    }

    #[test]
    fn add_explicit_type_not_applicable_if_ty_already_specified() {
        cov_mark::check!(add_explicit_type_not_applicable_if_ty_already_specified);
        check_assist_not_applicable(add_explicit_type, r#"fn f() { let a$0: i32 = 1; }"#);
    }

    #[test]
    fn add_explicit_type_not_applicable_if_specified_ty_is_tuple() {
        check_assist_not_applicable(
            add_explicit_type,
            r#"fn f() { let a$0: (i32, i32) = (3, 4); }"#,
        );
    }

    #[test]
    fn add_explicit_type_not_applicable_if_cursor_after_equals() {
        cov_mark::check!(add_explicit_type_not_applicable_if_cursor_after_equals);
        check_assist_not_applicable(
            add_explicit_type,
            r#"fn f() {let a =$0 match 1 {2 => 3, 3 => 5};}"#,
        )
    }

    #[test]
    fn add_explicit_type_not_applicable_if_cursor_before_let() {
        check_assist_not_applicable(
            add_explicit_type,
            r#"fn f() $0{let a = match 1 {2 => 3, 3 => 5};}"#,
        )
    }

    #[test]
    fn closure_parameters_are_not_added() {
        check_assist_not_applicable(
            add_explicit_type,
            r#"
fn main() {
    let multiply_by_two$0 = |i| i * 3;
    let six = multiply_by_two(2);
}
"#,
        )
    }

    /// https://github.com/rust-analyzer/rust-analyzer/issues/2922
    #[test]
    fn regression_issue_2922() {
        check_assist(
            add_explicit_type,
            r#"
fn main() {
    let $0v = [0.0; 2];
}
"#,
            r#"
fn main() {
    let v: [f64; 2] = [0.0; 2];
}
"#,
        );
        // note: this may break later if we add more consteval. it just needs to be something that our
        // consteval engine doesn't understand
        check_assist_not_applicable(
            add_explicit_type,
            r#"
fn main() {
    let $0l = [0.0; 2+2];
}
"#,
        );
    }

    #[test]
    fn default_generics_should_not_be_added() {
        check_assist(
            add_explicit_type,
            r#"
struct Test<K, T = u8> { k: K, t: T }

fn main() {
    let test$0 = Test { t: 23u8, k: 33 };
}
"#,
            r#"
struct Test<K, T = u8> { k: K, t: T }

fn main() {
    let test: Test<i32> = Test { t: 23u8, k: 33 };
}
"#,
        );
    }

    #[test]
    fn type_should_be_added_after_pattern() {
        // LetStmt = Attr* 'let' Pat (':' Type)? '=' initializer:Expr ';'
        check_assist(
            add_explicit_type,
            r#"
fn main() {
    let $0test @ () = ();
}
"#,
            r#"
fn main() {
    let test @ (): () = ();
}
"#,
        );
    }
}
<|endoftext|>


<commit_before>//! Name resolution algorithm
use std::{
    sync::Arc,
    time::Instant,
};

use rustc_hash::FxHashMap;

use ra_syntax::{
    SmolStr, SyntaxKind::{self, *},
    ast::{self, NameOwner, AstNode, ModuleItemOwner}
};

use crate::{
    Cancelable,
    loc2id::{DefId, DefLoc},
    descriptors::{
        DescriptorDatabase,
        module::{ModuleId, ModuleTree, ModuleSourceNode},
    },
    syntax_ptr::{LocalSyntaxPtr},
    input::SourceRootId,
};

/// A set of items and imports declared inside a module, without relation to
/// other modules.
///
/// This stands in-between raw syntax and name resolution and alow us to avoid
/// recomputing name res: if `InputModuleItems` are the same, we can avoid
/// running name resolution.
#[derive(Debug, Default, PartialEq, Eq)]
pub(crate) struct InputModuleItems {
    items: Vec<ModuleItem>,
    glob_imports: Vec<Path>,
    imports: Vec<Path>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct Path {
    kind: PathKind,
    segments: Vec<(LocalSyntaxPtr, SmolStr)>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum PathKind {
    Abs,
    Self_,
    Super,
    Crate,
}

pub(crate) fn input_module_items(
    db: &impl DescriptorDatabase,
    source_root: SourceRootId,
    module_id: ModuleId,
) -> Cancelable<Arc<InputModuleItems>> {
    let module_tree = db._module_tree(source_root)?;
    let source = module_id.source(&module_tree);
    let res = match source.resolve(db) {
        ModuleSourceNode::SourceFile(it) => {
            let items = it.borrowed().items();
            InputModuleItems::new(items)
        }
        ModuleSourceNode::Module(it) => {
            let items = it
                .borrowed()
                .item_list()
                .into_iter()
                .flat_map(|it| it.items());
            InputModuleItems::new(items)
        }
    };
    Ok(Arc::new(res))
}

pub(crate) fn item_map(
    db: &impl DescriptorDatabase,
    source_root: SourceRootId,
) -> Cancelable<Arc<ItemMap>> {
    let start = Instant::now();
    let module_tree = db._module_tree(source_root)?;
    let input = module_tree
        .modules()
        .map(|id| {
            let items = db._input_module_items(source_root, id)?;
            Ok((id, items))
        })
        .collect::<Cancelable<FxHashMap<_, _>>>()?;

    let mut resolver = Resolver {
        db: db,
        input: &input,
        source_root,
        module_tree,
        result: ItemMap::default(),
    };
    resolver.resolve()?;
    let res = resolver.result;
    let elapsed = start.elapsed();
    log::info!("item_map: {:?}", elapsed);
    Ok(Arc::new(res))
}

/// Item map is the result of the name resolution. Item map contains, for each
/// module, the set of visible items.
#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct ItemMap {
    per_module: FxHashMap<ModuleId, ModuleItems>,
}

#[derive(Debug, Default, PartialEq, Eq)]
struct ModuleItems {
    items: FxHashMap<SmolStr, Resolution>,
    import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>,
}

/// Resolution is basically `DefId` atm, but it should account for stuff like
/// multiple namespaces, ambiguity and errors.
#[derive(Debug, Clone, PartialEq, Eq)]
struct Resolution {
    /// None for unresolved
    def_id: Option<DefId>,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum Namespace {
    Types,
    Values,
}

#[derive(Debug)]
struct PerNs<T> {
    types: Option<T>,
    values: Option<T>,
}

#[derive(Debug, PartialEq, Eq)]
struct ModuleItem {
    ptr: LocalSyntaxPtr,
    name: SmolStr,
    kind: SyntaxKind,
    vis: Vis,
}

#[derive(Debug, PartialEq, Eq)]
enum Vis {
    Priv,
    Other,
}

impl InputModuleItems {
    fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> InputModuleItems {
        let mut res = InputModuleItems::default();
        for item in items {
            res.add_item(item);
        }
        res
    }

    fn add_item(&mut self, item: ast::ModuleItem) -> Option<()> {
        match item {
            ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::ImplItem(_) => {
                // impls don't define items
            }
            ast::ModuleItem::UseItem(it) => self.add_use_item(it),
            ast::ModuleItem::ExternCrateItem(_) => {
                // TODO
            }
            ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?),
        }
        Some(())
    }

    fn add_use_item(&mut self, item: ast::UseItem) {
        if let Some(tree) = item.use_tree() {
            self.add_use_tree(None, tree);
        }
    }

    fn add_use_tree(&mut self, prefix: Option<Path>, tree: ast::UseTree) {
        if let Some(use_tree_list) = tree.use_tree_list() {
            let prefix = match tree.path() {
                None => prefix,
                Some(path) => match convert_path(prefix, path) {
                    Some(it) => Some(it),
                    None => return, // TODO: report errors somewhere
                },
            };
            for tree in use_tree_list.use_trees() {
                self.add_use_tree(prefix.clone(), tree);
            }
        } else {
            if let Some(path) = tree.path() {
                if let Some(path) = convert_path(prefix, path) {
                    if tree.has_star() {
                        &mut self.glob_imports
                    } else {
                        &mut self.imports
                    }
                    .push(path);
                }
            }
        }
    }
}

fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
    let prefix = if let Some(qual) = path.qualifier() {
        Some(convert_path(prefix, qual)?)
    } else {
        None
    };
    let segment = path.segment()?;
    let res = match segment.kind()? {
        ast::PathSegmentKind::Name(name) => {
            let mut res = prefix.unwrap_or_else(|| Path {
                kind: PathKind::Abs,
                segments: Vec::with_capacity(1),
            });
            let ptr = LocalSyntaxPtr::new(name.syntax());
            res.segments.push((ptr, name.text()));
            res
        }
        ast::PathSegmentKind::CrateKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Crate,
                segments: Vec::new(),
            }
        }
        ast::PathSegmentKind::SelfKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Self_,
                segments: Vec::new(),
            }
        }
        ast::PathSegmentKind::SuperKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Super,
                segments: Vec::new(),
            }
        }
    };
    Some(res)
}

impl ModuleItem {
    fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
        let name = item.name()?.text();
        let ptr = LocalSyntaxPtr::new(item.syntax());
        let kind = item.syntax().kind();
        let vis = Vis::Other;
        let res = ModuleItem {
            ptr,
            name,
            kind,
            vis,
        };
        Some(res)
    }
}

struct Resolver<'a, DB> {
    db: &'a DB,
    input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>,
    source_root: SourceRootId,
    module_tree: Arc<ModuleTree>,
    result: ItemMap,
}

impl<'a, DB> Resolver<'a, DB>
where
    DB: DescriptorDatabase,
{
    fn resolve(&mut self) -> Cancelable<()> {
        for (&module_id, items) in self.input.iter() {
            self.populate_module(module_id, items)
        }

        for &module_id in self.input.keys() {
            crate::db::check_canceled(self.db)?;
            self.resolve_imports(module_id);
        }
        Ok(())
    }

    fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) {
        let file_id = module_id.source(&self.module_tree).file_id();

        let mut module_items = ModuleItems::default();

        for import in input.imports.iter() {
            if let Some((_, name)) = import.segments.last() {
                module_items
                    .items
                    .insert(name.clone(), Resolution { def_id: None });
            }
        }

        for item in input.items.iter() {
            if item.kind == MODULE {
                // handle submodules separatelly
                continue;
            }
            let ptr = item.ptr.into_global(file_id);
            let def_loc = DefLoc::Item { ptr };
            let def_id = self.db.id_maps().def_id(def_loc);
            let resolution = Resolution {
                def_id: Some(def_id),
            };
            module_items.items.insert(item.name.clone(), resolution);
        }

        for (name, mod_id) in module_id.children(&self.module_tree) {
            let def_loc = DefLoc::Module {
                id: mod_id,
                source_root: self.source_root,
            };
            let def_id = self.db.id_maps().def_id(def_loc);
            let resolution = Resolution {
                def_id: Some(def_id),
            };
            module_items.items.insert(name, resolution);
        }

        self.result.per_module.insert(module_id, module_items);
    }

    fn resolve_imports(&mut self, module_id: ModuleId) {
        for import in self.input[&module_id].imports.iter() {
            self.resolve_import(module_id, import);
        }
    }

    fn resolve_import(&mut self, module_id: ModuleId, import: &Path) {
        let mut curr = match import.kind {
            // TODO: handle extern crates
            PathKind::Abs => return,
            PathKind::Self_ => module_id,
            PathKind::Super => {
                match module_id.parent(&self.module_tree) {
                    Some(it) => it,
                    // TODO: error
                    None => return,
                }
            }
            PathKind::Crate => module_id.crate_root(&self.module_tree),
        };

        for (i, (ptr, name)) in import.segments.iter().enumerate() {
            let is_last = i == import.segments.len() - 1;

            let def_id = match self.result.per_module[&curr].items.get(name) {
                None => return,
                Some(res) => match res.def_id {
                    Some(it) => it,
                    None => return,
                },
            };

            self.update(module_id, |items| {
                items.import_resolutions.insert(*ptr, def_id);
            });

            if !is_last {
                curr = match self.db.id_maps().def_loc(def_id) {
                    DefLoc::Module { id, .. } => id,
                    _ => return,
                }
            } else {
                self.update(module_id, |items| {
                    let res = Resolution {
                        def_id: Some(def_id),
                    };
                    items.items.insert(name.clone(), res);
                })
            }
        }
    }

    fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleItems)) {
        let module_items = self.result.per_module.get_mut(&module_id).unwrap();
        f(module_items)
    }
}

#[cfg(test)]
mod tests {
    use crate::{
        mock_analysis::analysis_and_position,
        descriptors::{DescriptorDatabase, module::ModuleDescriptor},
        input::FilesDatabase,
};
    use super::*;

    fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
        let (analysis, pos) = analysis_and_position(fixture);
        let db = analysis.imp.db;
        let source_root = db.file_source_root(pos.file_id);
        let descr = ModuleDescriptor::guess_from_position(&*db, pos)
            .unwrap()
            .unwrap();
        let module_id = descr.module_id;
        (db._item_map(source_root).unwrap(), module_id)
    }

    #[test]
    fn test_item_map() {
        let (item_map, module_id) = item_map(
            "
            //- /lib.rs
            mod foo;

            use crate::foo::bar::Baz;
            <|>

            //- /foo/mod.rs
            pub mod bar;

            //- /foo/bar.rs
            pub struct Baz;
        ",
        );
        let name = SmolStr::from("Baz");
        let resolution = &item_map.per_module[&module_id].items[&name];
        assert!(resolution.def_id.is_some());
    }
}
<commit_msg>Move to top<commit_after>//! Name resolution algorithm
use std::{
    sync::Arc,
    time::Instant,
};

use rustc_hash::FxHashMap;

use ra_syntax::{
    SmolStr, SyntaxKind::{self, *},
    ast::{self, NameOwner, AstNode, ModuleItemOwner}
};

use crate::{
    Cancelable,
    loc2id::{DefId, DefLoc},
    descriptors::{
        DescriptorDatabase,
        module::{ModuleId, ModuleTree, ModuleSourceNode},
    },
    syntax_ptr::{LocalSyntaxPtr},
    input::SourceRootId,
};

/// Item map is the result of the name resolution. Item map contains, for each
/// module, the set of visible items.
#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct ItemMap {
    per_module: FxHashMap<ModuleId, ModuleItems>,
}

#[derive(Debug, Default, PartialEq, Eq)]
struct ModuleItems {
    items: FxHashMap<SmolStr, Resolution>,
    import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>,
}

/// A set of items and imports declared inside a module, without relation to
/// other modules.
///
/// This stands in-between raw syntax and name resolution and alow us to avoid
/// recomputing name res: if `InputModuleItems` are the same, we can avoid
/// running name resolution.
#[derive(Debug, Default, PartialEq, Eq)]
pub(crate) struct InputModuleItems {
    items: Vec<ModuleItem>,
    glob_imports: Vec<Path>,
    imports: Vec<Path>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct Path {
    kind: PathKind,
    segments: Vec<(LocalSyntaxPtr, SmolStr)>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum PathKind {
    Abs,
    Self_,
    Super,
    Crate,
}

pub(crate) fn input_module_items(
    db: &impl DescriptorDatabase,
    source_root: SourceRootId,
    module_id: ModuleId,
) -> Cancelable<Arc<InputModuleItems>> {
    let module_tree = db._module_tree(source_root)?;
    let source = module_id.source(&module_tree);
    let res = match source.resolve(db) {
        ModuleSourceNode::SourceFile(it) => {
            let items = it.borrowed().items();
            InputModuleItems::new(items)
        }
        ModuleSourceNode::Module(it) => {
            let items = it
                .borrowed()
                .item_list()
                .into_iter()
                .flat_map(|it| it.items());
            InputModuleItems::new(items)
        }
    };
    Ok(Arc::new(res))
}

pub(crate) fn item_map(
    db: &impl DescriptorDatabase,
    source_root: SourceRootId,
) -> Cancelable<Arc<ItemMap>> {
    let start = Instant::now();
    let module_tree = db._module_tree(source_root)?;
    let input = module_tree
        .modules()
        .map(|id| {
            let items = db._input_module_items(source_root, id)?;
            Ok((id, items))
        })
        .collect::<Cancelable<FxHashMap<_, _>>>()?;

    let mut resolver = Resolver {
        db: db,
        input: &input,
        source_root,
        module_tree,
        result: ItemMap::default(),
    };
    resolver.resolve()?;
    let res = resolver.result;
    let elapsed = start.elapsed();
    log::info!("item_map: {:?}", elapsed);
    Ok(Arc::new(res))
}

/// Resolution is basically `DefId` atm, but it should account for stuff like
/// multiple namespaces, ambiguity and errors.
#[derive(Debug, Clone, PartialEq, Eq)]
struct Resolution {
    /// None for unresolved
    def_id: Option<DefId>,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum Namespace {
    Types,
    Values,
}

#[derive(Debug)]
struct PerNs<T> {
    types: Option<T>,
    values: Option<T>,
}

#[derive(Debug, PartialEq, Eq)]
struct ModuleItem {
    ptr: LocalSyntaxPtr,
    name: SmolStr,
    kind: SyntaxKind,
    vis: Vis,
}

#[derive(Debug, PartialEq, Eq)]
enum Vis {
    Priv,
    Other,
}

impl InputModuleItems {
    fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> InputModuleItems {
        let mut res = InputModuleItems::default();
        for item in items {
            res.add_item(item);
        }
        res
    }

    fn add_item(&mut self, item: ast::ModuleItem) -> Option<()> {
        match item {
            ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::ImplItem(_) => {
                // impls don't define items
            }
            ast::ModuleItem::UseItem(it) => self.add_use_item(it),
            ast::ModuleItem::ExternCrateItem(_) => {
                // TODO
            }
            ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?),
        }
        Some(())
    }

    fn add_use_item(&mut self, item: ast::UseItem) {
        if let Some(tree) = item.use_tree() {
            self.add_use_tree(None, tree);
        }
    }

    fn add_use_tree(&mut self, prefix: Option<Path>, tree: ast::UseTree) {
        if let Some(use_tree_list) = tree.use_tree_list() {
            let prefix = match tree.path() {
                None => prefix,
                Some(path) => match convert_path(prefix, path) {
                    Some(it) => Some(it),
                    None => return, // TODO: report errors somewhere
                },
            };
            for tree in use_tree_list.use_trees() {
                self.add_use_tree(prefix.clone(), tree);
            }
        } else {
            if let Some(path) = tree.path() {
                if let Some(path) = convert_path(prefix, path) {
                    if tree.has_star() {
                        &mut self.glob_imports
                    } else {
                        &mut self.imports
                    }
                    .push(path);
                }
            }
        }
    }
}

fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
    let prefix = if let Some(qual) = path.qualifier() {
        Some(convert_path(prefix, qual)?)
    } else {
        None
    };
    let segment = path.segment()?;
    let res = match segment.kind()? {
        ast::PathSegmentKind::Name(name) => {
            let mut res = prefix.unwrap_or_else(|| Path {
                kind: PathKind::Abs,
                segments: Vec::with_capacity(1),
            });
            let ptr = LocalSyntaxPtr::new(name.syntax());
            res.segments.push((ptr, name.text()));
            res
        }
        ast::PathSegmentKind::CrateKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Crate,
                segments: Vec::new(),
            }
        }
        ast::PathSegmentKind::SelfKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Self_,
                segments: Vec::new(),
            }
        }
        ast::PathSegmentKind::SuperKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Super,
                segments: Vec::new(),
            }
        }
    };
    Some(res)
}

impl ModuleItem {
    fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
        let name = item.name()?.text();
        let ptr = LocalSyntaxPtr::new(item.syntax());
        let kind = item.syntax().kind();
        let vis = Vis::Other;
        let res = ModuleItem {
            ptr,
            name,
            kind,
            vis,
        };
        Some(res)
    }
}

struct Resolver<'a, DB> {
    db: &'a DB,
    input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>,
    source_root: SourceRootId,
    module_tree: Arc<ModuleTree>,
    result: ItemMap,
}

impl<'a, DB> Resolver<'a, DB>
where
    DB: DescriptorDatabase,
{
    fn resolve(&mut self) -> Cancelable<()> {
        for (&module_id, items) in self.input.iter() {
            self.populate_module(module_id, items)
        }

        for &module_id in self.input.keys() {
            crate::db::check_canceled(self.db)?;
            self.resolve_imports(module_id);
        }
        Ok(())
    }

    fn populate_module(&mut self, module_id: ModuleId, input: &InputModuleItems) {
        let file_id = module_id.source(&self.module_tree).file_id();

        let mut module_items = ModuleItems::default();

        for import in input.imports.iter() {
            if let Some((_, name)) = import.segments.last() {
                module_items
                    .items
                    .insert(name.clone(), Resolution { def_id: None });
            }
        }

        for item in input.items.iter() {
            if item.kind == MODULE {
                // handle submodules separatelly
                continue;
            }
            let ptr = item.ptr.into_global(file_id);
            let def_loc = DefLoc::Item { ptr };
            let def_id = self.db.id_maps().def_id(def_loc);
            let resolution = Resolution {
                def_id: Some(def_id),
            };
            module_items.items.insert(item.name.clone(), resolution);
        }

        for (name, mod_id) in module_id.children(&self.module_tree) {
            let def_loc = DefLoc::Module {
                id: mod_id,
                source_root: self.source_root,
            };
            let def_id = self.db.id_maps().def_id(def_loc);
            let resolution = Resolution {
                def_id: Some(def_id),
            };
            module_items.items.insert(name, resolution);
        }

        self.result.per_module.insert(module_id, module_items);
    }

    fn resolve_imports(&mut self, module_id: ModuleId) {
        for import in self.input[&module_id].imports.iter() {
            self.resolve_import(module_id, import);
        }
    }

    fn resolve_import(&mut self, module_id: ModuleId, import: &Path) {
        let mut curr = match import.kind {
            // TODO: handle extern crates
            PathKind::Abs => return,
            PathKind::Self_ => module_id,
            PathKind::Super => {
                match module_id.parent(&self.module_tree) {
                    Some(it) => it,
                    // TODO: error
                    None => return,
                }
            }
            PathKind::Crate => module_id.crate_root(&self.module_tree),
        };

        for (i, (ptr, name)) in import.segments.iter().enumerate() {
            let is_last = i == import.segments.len() - 1;

            let def_id = match self.result.per_module[&curr].items.get(name) {
                None => return,
                Some(res) => match res.def_id {
                    Some(it) => it,
                    None => return,
                },
            };

            self.update(module_id, |items| {
                items.import_resolutions.insert(*ptr, def_id);
            });

            if !is_last {
                curr = match self.db.id_maps().def_loc(def_id) {
                    DefLoc::Module { id, .. } => id,
                    _ => return,
                }
            } else {
                self.update(module_id, |items| {
                    let res = Resolution {
                        def_id: Some(def_id),
                    };
                    items.items.insert(name.clone(), res);
                })
            }
        }
    }

    fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleItems)) {
        let module_items = self.result.per_module.get_mut(&module_id).unwrap();
        f(module_items)
    }
}

#[cfg(test)]
mod tests {
    use crate::{
        mock_analysis::analysis_and_position,
        descriptors::{DescriptorDatabase, module::ModuleDescriptor},
        input::FilesDatabase,
};
    use super::*;

    fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
        let (analysis, pos) = analysis_and_position(fixture);
        let db = analysis.imp.db;
        let source_root = db.file_source_root(pos.file_id);
        let descr = ModuleDescriptor::guess_from_position(&*db, pos)
            .unwrap()
            .unwrap();
        let module_id = descr.module_id;
        (db._item_map(source_root).unwrap(), module_id)
    }

    #[test]
    fn test_item_map() {
        let (item_map, module_id) = item_map(
            "
            //- /lib.rs
            mod foo;

            use crate::foo::bar::Baz;
            <|>

            //- /foo/mod.rs
            pub mod bar;

            //- /foo/bar.rs
            pub struct Baz;
        ",
        );
        let name = SmolStr::from("Baz");
        let resolution = &item_map.per_module[&module_id].items[&name];
        assert!(resolution.def_id.is_some());
    }
}
<|endoftext|>


<commit_before>// rustc overflows when compiling this see:
// https://github.com/rust-lang/rust/issues/55779
extern crate serde;

use ruma_events::{StateEventContent, Unsigned};
use ruma_events_macros::Event;

/// State event.
#[derive(Clone, Debug, Event)]
pub struct StateEvent<C: StateEventContent> {
    pub content: C,
    pub state_key: String,
    pub prev_content: Option<C>,
    pub unsigned: Unsigned,
}

fn main() {}
<commit_msg>events: Fix a test case<commit_after>// rustc overflows when compiling this see:
// https://github.com/rust-lang/rust/issues/55779
extern crate serde;

use ruma_common::MilliSecondsSinceUnixEpoch;
use ruma_events::{StateEventContent, Unsigned};
use ruma_events_macros::Event;
use ruma_identifiers::{EventId, RoomId, UserId};

/// State event.
#[derive(Clone, Debug, Event)]
pub struct StateEvent<C: StateEventContent> {
    pub content: C,
    pub event_id: EventId,
    pub sender: UserId,
    pub origin_server_ts: MilliSecondsSinceUnixEpoch,
    pub room_id: RoomId,
    pub state_key: String,
    pub prev_content: Option<C>,
    pub unsigned: Unsigned,
}

fn main() {}
<|endoftext|>


<commit_before>#![feature(no_panic_pow)]
#![feature(test)]

extern crate test;

use can_dbc::{ByteOrder, Message, MessageId, Signal, ValueDescription, DBC, MultiplexIndicator};
use codegen::{Enum, Function, Impl, Scope, Struct};
use heck::{CamelCase, ShoutySnakeCase};
use log::warn;
use socketcan::{SFF_MASK, EFF_MASK};

use std::fmt::Write;

#[cfg(test)]
mod tests {
    use byteorder;
    use byteorder::{ByteOrder, LE};
    use test::{black_box, Bencher};

    #[bench]
    fn bench_read_signal(b: &mut Bencher) {
        const byte_payload: &[u8] = &[
            0x4, 0x2, 0xA, 0xA, 0xF, 0xF, 0xE, 0xE, 0xD, 0xD, 0xA, 0xA, 0xF, 0xF, 0xD, 0xD,
        ];

        b.iter(|| {
            let frame_payload: u64 = LE::read_u64(byte_payload);
            let bit_msk_const = 2u64.saturating_pow(8 as u32) - 1;
            let factor: f64 = test::black_box(2.0);
            let start_bit: u64 = test::black_box(8);
            let offset: f64 = test::black_box(10.0);

            (((frame_payload >> start_bit) & bit_msk_const) as f64) * factor + offset
        });
    }
}

/// Character that is prefixed before type names that are
/// are not starting with an alphabetic char.
const PREFIX_CHAR: char = 'X';

/// Character that is used to replace invalid characters
/// in type names.
const REPLACEMENT_CHAR: char = 'X';

/// Suffix that is append to the raw signal function
const RAW_FN_SUFFIX: &str = "raw_value";

type Result<T> = std::result::Result<T, std::fmt::Error>;

#[derive(Debug)]
pub struct DbccOpt {
    /// Should tokio SocketCan BCM streams be generated.
    /// This requires the `tokio-socketcan-bcm` crate.
    pub with_tokio: bool,
}

pub trait TypeName: ToOwned {
    fn to_type_name(&self) -> Self::Owned;
}

impl TypeName for str {
    fn to_type_name(&self) -> String {
        let mut out = String::with_capacity(self.len() + 1);
        let mut chars = self.chars();
        if let Some(first) = chars.next() {
            if !first.is_alphabetic() && first != '_' {
                warn!("string: {} is prefixed with `{}`", self, PREFIX_CHAR);
                out.push(PREFIX_CHAR);
            }
            out.push(first);
        }

        while let Some(chr) = chars.next() {
            if chr.is_digit(10) || chr.is_alphabetic() || chr == '_' {
                out.push(chr);
            } else {
                warn!(
                    "`{}` character in string: {} is replaced by `{}`",
                    chr, self, REPLACEMENT_CHAR
                );
                out.push(REPLACEMENT_CHAR);
            }
        }

        out
    }
}

fn to_enum_name(message_id: &MessageId, signal_name: &str) -> String {
    format!("{}{}", &signal_name.to_camel_case(), message_id.0)
}

pub fn signal_enum(val_desc: &ValueDescription) -> Option<Enum> {
    if let ValueDescription::Signal {
        ref message_id,
        ref signal_name,
        ref value_descriptions,
    } = val_desc
    {
        let mut sig_enum = Enum::new(&to_enum_name(message_id, signal_name));
        sig_enum.allow("dead_code");
        sig_enum.vis("pub");
        sig_enum.repr("u64");
        sig_enum.derive("Debug");
        sig_enum.derive("Clone");
        sig_enum.derive("Copy");
        sig_enum.derive("PartialEq");
        sig_enum.derive("Eq");
        for desc in value_descriptions {
            sig_enum.new_variant(&desc.b().to_camel_case().to_type_name());
        }
        sig_enum.new_variant("XValue(u64)");
        return Some(sig_enum);
    }
    None
}

pub fn signal_enum_impl_from(val_desc: &ValueDescription) -> Option<Impl> {
    if let ValueDescription::Signal {
        ref message_id,
        ref signal_name,
        ref value_descriptions,
    } = val_desc
    {
        let enum_name = to_enum_name(message_id, signal_name);
        let mut enum_impl = Impl::new(codegen::Type::new(&enum_name));
        enum_impl.impl_trait("From<u64>");

        let from_fn = enum_impl.new_fn("from");
        from_fn.allow("dead_code");
        from_fn.arg("val", codegen::Type::new("u64"));
        from_fn.ret(codegen::Type::new("Self"));

        let mut matching = String::new();
        write!(&mut matching, "match val {{\n").unwrap();
        for value_description in value_descriptions {
            write!(
                &mut matching,
                "    {} => {}::{},\n",
                value_description.a(),
                enum_name,
                value_description.b().to_camel_case().to_type_name()
            )
            .unwrap();
        }
        write!(
            &mut matching,
            "    value => {}::XValue(value),\n",
            enum_name
        )
        .unwrap();
        write!(&mut matching, "}}").unwrap();

        from_fn.line(matching);

        return Some(enum_impl);
    }
    None
}

pub fn signal_fn_raw(dbc: &DBC, signal: &Signal, message_id: &MessageId) -> Result<Function> {
    let raw_fn_name = format!("{}_{}", signal.name().to_lowercase(), RAW_FN_SUFFIX);

    let mut signal_fn = codegen::Function::new(&raw_fn_name);
    signal_fn.allow("dead_code");
    signal_fn.vis("pub");
    signal_fn.arg_ref_self();

    let signal_return_type = signal_return_type(signal);
    signal_fn.ret(codegen::Type::new(&signal_return_type));

    let default_signal_comment = format!("Read {} signal from can frame", signal.name());
    let signal_comment = dbc
        .signal_comment(message_id, signal.name())
        .unwrap_or(&default_signal_comment);

    let signal_unit = if !signal.unit().is_empty() {
        format!("\nUnit: {}", signal.unit())
    } else {
        String::default()
    };

    signal_fn.doc(&format!("{}{}", signal_comment, signal_unit));

    let read_byte_order = match signal.byte_order() {
        ByteOrder::LittleEndian => "let frame_payload: u64 = LE::read_u64(&self.frame_payload);",
        ByteOrder::BigEndian => "let  frame_payload: u64 = BE::read_u64(&self.frame_payload);",
    };
    signal_fn.line(read_byte_order);

    let bit_msk_const = 2u64.saturating_pow(*signal.signal_size() as u32) - 1;
    let signal_shift = shift_amount(
        *signal.byte_order(),
        *signal.start_bit(),
        *signal.signal_size(),
    );

    let calc = calc_raw(signal, signal_return_type, signal_shift, bit_msk_const)?;
    signal_fn.line(calc);

    Ok(signal_fn)
}

pub fn signal_fn_enum(signal: &Signal, enum_type: String) -> Result<Function> {
    let mut signal_fn = codegen::Function::new(&signal.name().to_lowercase());
    signal_fn.allow("dead_code");
    signal_fn.vis("pub");
    signal_fn.arg_ref_self();

    signal_fn.ret(enum_type.clone());

    let raw_fn_name = format!("{}_{}", signal.name().to_lowercase(), RAW_FN_SUFFIX);

    signal_fn.line(format!(
        "{}::from(self.{}() as u64)",
        enum_type, raw_fn_name
    ));

    Ok(signal_fn)
}

fn calc_raw(
    signal: &Signal,
    signal_return_type: String,
    signal_shift: u64,
    bit_msk_const: u64,
) -> Result<String> {
    let mut calc = String::new();

    // No shift required if start_bit == 0
    let shift = if signal_shift != 0 {
        format!("(frame_payload >> {})", signal_shift)
    } else {
        format!("frame_payload")
    };

    write!(&mut calc, "({} & {:#X})", shift, bit_msk_const)?;

    if *signal.signal_size() != 1 {
        write!(&mut calc, " as {}", signal_return_type)?;
    }

    if *signal.factor() != 1.0 {
        write!(&mut calc, " * {:.6}", signal.factor())?;
    }

    if *signal.offset() != 0.0 && *signal.signal_size() <= 32 {
        write!(&mut calc, " + {}f32", signal.offset())?;
    } else if *signal.offset() != 0.0 {
        write!(&mut calc, " + {}f64", signal.offset())?;
    }

    // boolean signal
    if *signal.signal_size() == 1 {
        write!(&mut calc, " == 1")?;
    }

    Ok(calc)
}

fn signal_return_type(signal: &Signal) -> String {
    match signal.signal_size() {
        _ if *signal.signal_size() == 1 => "bool".to_string(),
        _ if *signal.signal_size() > 1 && *signal.signal_size() <= 32 => "f32".to_string(),
        _ => "f64".to_string(),
    }
}

fn shift_amount(byte_order: ByteOrder, start_bit: u64, signal_size: u64) -> u64 {
    match byte_order {
        ByteOrder::LittleEndian => start_bit,
        ByteOrder::BigEndian => 64 - signal_size - ((start_bit / 8) * 8 + (7 - (start_bit % 8))),
    }
}

fn message_const(message: &Message) -> String {
    format!(
        "#[allow(dead_code)]\npub const MESSAGE_ID_{}: u32 = {};",
        message.message_name().to_shouty_snake_case(),
        message.message_id().0
    )
}

fn message_struct(dbc: &DBC, message: &Message) -> Struct {
    let mut message_struct = Struct::new(&message.message_name().to_camel_case());
    if let Some(message_comment) = dbc.message_comment(message.message_id()) {
        message_struct.doc(message_comment);
    }
    message_struct.allow("dead_code");
    message_struct.derive("Debug");
    message_struct.vis("pub");
    message_struct.field("frame_payload", "Vec<u8>");
    message_struct
}

fn message_impl(opt: &DbccOpt, dbc: &DBC, message: &Message) -> Result<Impl> {
    let mut msg_impl = Impl::new(codegen::Type::new(&message.message_name().to_camel_case()));

    let new_fn = msg_impl.new_fn("new");
    new_fn.allow("dead_code");
    new_fn.vis("pub");
    new_fn.arg("mut frame_payload", codegen::Type::new("Vec<u8>"));
    new_fn.line("frame_payload.resize(8, 0);");
    new_fn.line(format!(
        "{} {{ frame_payload }}",
        message.message_name().to_camel_case()
    ));
    new_fn.ret(codegen::Type::new(&message.message_name().to_camel_case()));

    if opt.with_tokio {
        msg_impl.push_fn(message_stream(message));
    }

    for signal in message.signals() {

        if *signal.multiplexer_indicator() != MultiplexIndicator::Plain {
            warn!("Multiplexed signals are currently not supported, the message `{}` signal `{}` will be skipped", message.message_name(), signal.name());
            continue;
        }

        msg_impl.push_fn(signal_fn_raw(dbc, signal, message.message_id())?);

        // Check if this signal can be turned into an enum
        let enum_type = dbc
            .value_descriptions_for_signal(message.message_id(), signal.name())
            .map(|_| to_enum_name(message.message_id(), signal.name()));
        if let Some(enum_type) = enum_type {
            msg_impl.push_fn(signal_fn_enum(signal, enum_type)?);
        }
    }

    Ok(msg_impl)
}

/// Generate message stream using socketcan's Broadcast Manager filters via socketcan-tokio.
fn message_stream(message: &Message) -> Function {
    let mut stream_fn = codegen::Function::new("stream");
    stream_fn.allow("dead_code");
    stream_fn.vis("pub");

    stream_fn.arg("can_interface", codegen::Type::new("&str"));
    stream_fn.arg("ival1", codegen::Type::new("&std::time::Duration"));
    stream_fn.arg("ival2", codegen::Type::new("&std::time::Duration"));

    let ret = format!(
        "std::io::Result<Box<Stream<Item = {}, Error = std::io::Error> + Sync + Send>>",
        message.message_name().to_camel_case()
    );
    stream_fn.ret(ret);

    stream_fn.line("let socket = BCMSocket::open_nb(&can_interface)?;");

    let message_id = match message.message_id().0 {
            0...SFF_MASK => format!("let message_id = CANMessageId::SFF({} as u16);", message.message_id().0.to_string()),
            SFF_MASK...EFF_MASK => format!("let message_id = CANMessageId::EFF({} as u16);", message.message_id().0.to_string()),
            _ => panic!(format!("can message identifier `{}` exceeds max size", message.message_id().0)),
    };
    stream_fn.line(message_id);

    stream_fn.line("let frame_stream = socket.filter_id_incoming_frames(message_id, ival1.clone(), ival2.clone())?;");
    stream_fn.line(format!(
        "let f = frame_stream.map(|frame| {}::new(frame.data().to_vec()));",
        message.message_name().to_camel_case()
    ));
    stream_fn.line("Ok(Box::new(f))");

    stream_fn
}

pub fn can_reader(opt: &DbccOpt, dbc: &DBC) -> Result<Scope> {
    let mut scope = Scope::new();
    scope.import("byteorder", "{ByteOrder, LE, BE}");

    if opt.with_tokio {
        scope.import("tokio_socketcan_bcm", "{CANMessageId, BCMSocket}");
        scope.import("futures", "Stream");
        scope.import("std::convert", "TryFrom");
    }

    for message in dbc.messages() {
        scope.raw(&message_const(message));
    }

    for value_description in dbc.value_descriptions() {
        if let Some(signal_enum) = signal_enum(value_description) {
            scope.push_enum(signal_enum);
        }

        if let Some(enum_impl) = signal_enum_impl_from(value_description) {
            scope.push_impl(enum_impl);
        }
    }

    for message in dbc.messages() {
        scope.push_struct(message_struct(&dbc, message));
        scope.push_impl(message_impl(opt, &dbc, message)?);
    }

    Ok(scope)
}
<commit_msg>Remove EFF etc flags in CAN ID<commit_after>#![feature(no_panic_pow)]
#![feature(test)]

extern crate test;

use can_dbc::{ByteOrder, Message, MessageId, Signal, ValueDescription, DBC, MultiplexIndicator};
use codegen::{Enum, Function, Impl, Scope, Struct};
use heck::{CamelCase, ShoutySnakeCase};
use log::warn;
use socketcan::{SFF_MASK, EFF_MASK};

use std::fmt::Write;

#[cfg(test)]
mod tests {
    use byteorder;
    use byteorder::{ByteOrder, LE};
    use test::{black_box, Bencher};

    #[bench]
    fn bench_read_signal(b: &mut Bencher) {
        const byte_payload: &[u8] = &[
            0x4, 0x2, 0xA, 0xA, 0xF, 0xF, 0xE, 0xE, 0xD, 0xD, 0xA, 0xA, 0xF, 0xF, 0xD, 0xD,
        ];

        b.iter(|| {
            let frame_payload: u64 = LE::read_u64(byte_payload);
            let bit_msk_const = 2u64.saturating_pow(8 as u32) - 1;
            let factor: f64 = test::black_box(2.0);
            let start_bit: u64 = test::black_box(8);
            let offset: f64 = test::black_box(10.0);

            (((frame_payload >> start_bit) & bit_msk_const) as f64) * factor + offset
        });
    }
}

/// Character that is prefixed before type names that are
/// are not starting with an alphabetic char.
const PREFIX_CHAR: char = 'X';

/// Character that is used to replace invalid characters
/// in type names.
const REPLACEMENT_CHAR: char = 'X';

/// Suffix that is append to the raw signal function
const RAW_FN_SUFFIX: &str = "raw_value";

type Result<T> = std::result::Result<T, std::fmt::Error>;

#[derive(Debug)]
pub struct DbccOpt {
    /// Should tokio SocketCan BCM streams be generated.
    /// This requires the `tokio-socketcan-bcm` crate.
    pub with_tokio: bool,
}

pub trait TypeName: ToOwned {
    fn to_type_name(&self) -> Self::Owned;
}

impl TypeName for str {
    fn to_type_name(&self) -> String {
        let mut out = String::with_capacity(self.len() + 1);
        let mut chars = self.chars();
        if let Some(first) = chars.next() {
            if !first.is_alphabetic() && first != '_' {
                warn!("string: {} is prefixed with `{}`", self, PREFIX_CHAR);
                out.push(PREFIX_CHAR);
            }
            out.push(first);
        }

        while let Some(chr) = chars.next() {
            if chr.is_digit(10) || chr.is_alphabetic() || chr == '_' {
                out.push(chr);
            } else {
                warn!(
                    "`{}` character in string: {} is replaced by `{}`",
                    chr, self, REPLACEMENT_CHAR
                );
                out.push(REPLACEMENT_CHAR);
            }
        }

        out
    }
}

fn to_enum_name(message_id: &MessageId, signal_name: &str) -> String {
    format!("{}{}", &signal_name.to_camel_case(), message_id.0)
}

pub fn signal_enum(val_desc: &ValueDescription) -> Option<Enum> {
    if let ValueDescription::Signal {
        ref message_id,
        ref signal_name,
        ref value_descriptions,
    } = val_desc
    {
        let mut sig_enum = Enum::new(&to_enum_name(message_id, signal_name));
        sig_enum.allow("dead_code");
        sig_enum.vis("pub");
        sig_enum.repr("u64");
        sig_enum.derive("Debug");
        sig_enum.derive("Clone");
        sig_enum.derive("Copy");
        sig_enum.derive("PartialEq");
        sig_enum.derive("Eq");
        for desc in value_descriptions {
            sig_enum.new_variant(&desc.b().to_camel_case().to_type_name());
        }
        sig_enum.new_variant("XValue(u64)");
        return Some(sig_enum);
    }
    None
}

pub fn signal_enum_impl_from(val_desc: &ValueDescription) -> Option<Impl> {
    if let ValueDescription::Signal {
        ref message_id,
        ref signal_name,
        ref value_descriptions,
    } = val_desc
    {
        let enum_name = to_enum_name(message_id, signal_name);
        let mut enum_impl = Impl::new(codegen::Type::new(&enum_name));
        enum_impl.impl_trait("From<u64>");

        let from_fn = enum_impl.new_fn("from");
        from_fn.allow("dead_code");
        from_fn.arg("val", codegen::Type::new("u64"));
        from_fn.ret(codegen::Type::new("Self"));

        let mut matching = String::new();
        write!(&mut matching, "match val {{\n").unwrap();
        for value_description in value_descriptions {
            write!(
                &mut matching,
                "    {} => {}::{},\n",
                value_description.a(),
                enum_name,
                value_description.b().to_camel_case().to_type_name()
            )
            .unwrap();
        }
        write!(
            &mut matching,
            "    value => {}::XValue(value),\n",
            enum_name
        )
        .unwrap();
        write!(&mut matching, "}}").unwrap();

        from_fn.line(matching);

        return Some(enum_impl);
    }
    None
}

pub fn signal_fn_raw(dbc: &DBC, signal: &Signal, message_id: &MessageId) -> Result<Function> {
    let raw_fn_name = format!("{}_{}", signal.name().to_lowercase(), RAW_FN_SUFFIX);

    let mut signal_fn = codegen::Function::new(&raw_fn_name);
    signal_fn.allow("dead_code");
    signal_fn.vis("pub");
    signal_fn.arg_ref_self();

    let signal_return_type = signal_return_type(signal);
    signal_fn.ret(codegen::Type::new(&signal_return_type));

    let default_signal_comment = format!("Read {} signal from can frame", signal.name());
    let signal_comment = dbc
        .signal_comment(message_id, signal.name())
        .unwrap_or(&default_signal_comment);

    let signal_unit = if !signal.unit().is_empty() {
        format!("\nUnit: {}", signal.unit())
    } else {
        String::default()
    };

    signal_fn.doc(&format!("{}{}", signal_comment, signal_unit));

    let read_byte_order = match signal.byte_order() {
        ByteOrder::LittleEndian => "let frame_payload: u64 = LE::read_u64(&self.frame_payload);",
        ByteOrder::BigEndian => "let  frame_payload: u64 = BE::read_u64(&self.frame_payload);",
    };
    signal_fn.line(read_byte_order);

    let bit_msk_const = 2u64.saturating_pow(*signal.signal_size() as u32) - 1;
    let signal_shift = shift_amount(
        *signal.byte_order(),
        *signal.start_bit(),
        *signal.signal_size(),
    );

    let calc = calc_raw(signal, signal_return_type, signal_shift, bit_msk_const)?;
    signal_fn.line(calc);

    Ok(signal_fn)
}

pub fn signal_fn_enum(signal: &Signal, enum_type: String) -> Result<Function> {
    let mut signal_fn = codegen::Function::new(&signal.name().to_lowercase());
    signal_fn.allow("dead_code");
    signal_fn.vis("pub");
    signal_fn.arg_ref_self();

    signal_fn.ret(enum_type.clone());

    let raw_fn_name = format!("{}_{}", signal.name().to_lowercase(), RAW_FN_SUFFIX);

    signal_fn.line(format!(
        "{}::from(self.{}() as u64)",
        enum_type, raw_fn_name
    ));

    Ok(signal_fn)
}

fn calc_raw(
    signal: &Signal,
    signal_return_type: String,
    signal_shift: u64,
    bit_msk_const: u64,
) -> Result<String> {
    let mut calc = String::new();

    // No shift required if start_bit == 0
    let shift = if signal_shift != 0 {
        format!("(frame_payload >> {})", signal_shift)
    } else {
        format!("frame_payload")
    };

    write!(&mut calc, "({} & {:#X})", shift, bit_msk_const)?;

    if *signal.signal_size() != 1 {
        write!(&mut calc, " as {}", signal_return_type)?;
    }

    if *signal.factor() != 1.0 {
        write!(&mut calc, " * {:.6}", signal.factor())?;
    }

    if *signal.offset() != 0.0 && *signal.signal_size() <= 32 {
        write!(&mut calc, " + {}f32", signal.offset())?;
    } else if *signal.offset() != 0.0 {
        write!(&mut calc, " + {}f64", signal.offset())?;
    }

    // boolean signal
    if *signal.signal_size() == 1 {
        write!(&mut calc, " == 1")?;
    }

    Ok(calc)
}

fn signal_return_type(signal: &Signal) -> String {
    match signal.signal_size() {
        _ if *signal.signal_size() == 1 => "bool".to_string(),
        _ if *signal.signal_size() > 1 && *signal.signal_size() <= 32 => "f32".to_string(),
        _ => "f64".to_string(),
    }
}

fn shift_amount(byte_order: ByteOrder, start_bit: u64, signal_size: u64) -> u64 {
    match byte_order {
        ByteOrder::LittleEndian => start_bit,
        ByteOrder::BigEndian => 64 - signal_size - ((start_bit / 8) * 8 + (7 - (start_bit % 8))),
    }
}

fn message_const(message: &Message) -> String {
    format!(
        "#[allow(dead_code)]\npub const MESSAGE_ID_{}: u32 = {};",
        message.message_name().to_shouty_snake_case(),
        message.message_id().0
    )
}

fn message_struct(dbc: &DBC, message: &Message) -> Struct {
    let mut message_struct = Struct::new(&message.message_name().to_camel_case());
    if let Some(message_comment) = dbc.message_comment(message.message_id()) {
        message_struct.doc(message_comment);
    }
    message_struct.allow("dead_code");
    message_struct.derive("Debug");
    message_struct.vis("pub");
    message_struct.field("frame_payload", "Vec<u8>");
    message_struct
}

fn message_impl(opt: &DbccOpt, dbc: &DBC, message: &Message) -> Result<Impl> {
    let mut msg_impl = Impl::new(codegen::Type::new(&message.message_name().to_camel_case()));

    let new_fn = msg_impl.new_fn("new");
    new_fn.allow("dead_code");
    new_fn.vis("pub");
    new_fn.arg("mut frame_payload", codegen::Type::new("Vec<u8>"));
    new_fn.line("frame_payload.resize(8, 0);");
    new_fn.line(format!(
        "{} {{ frame_payload }}",
        message.message_name().to_camel_case()
    ));
    new_fn.ret(codegen::Type::new(&message.message_name().to_camel_case()));

    if opt.with_tokio {
        msg_impl.push_fn(message_stream(message));
    }

    for signal in message.signals() {

        if *signal.multiplexer_indicator() != MultiplexIndicator::Plain {
            warn!("Multiplexed signals are currently not supported, the message `{}` signal `{}` will be skipped", message.message_name(), signal.name());
            continue;
        }

        msg_impl.push_fn(signal_fn_raw(dbc, signal, message.message_id())?);

        // Check if this signal can be turned into an enum
        let enum_type = dbc
            .value_descriptions_for_signal(message.message_id(), signal.name())
            .map(|_| to_enum_name(message.message_id(), signal.name()));
        if let Some(enum_type) = enum_type {
            msg_impl.push_fn(signal_fn_enum(signal, enum_type)?);
        }
    }

    Ok(msg_impl)
}

/// Generate message stream using socketcan's Broadcast Manager filters via socketcan-tokio.
fn message_stream(message: &Message) -> Function {
    let mut stream_fn = codegen::Function::new("stream");
    stream_fn.allow("dead_code");
    stream_fn.vis("pub");

    stream_fn.arg("can_interface", codegen::Type::new("&str"));
    stream_fn.arg("ival1", codegen::Type::new("&std::time::Duration"));
    stream_fn.arg("ival2", codegen::Type::new("&std::time::Duration"));

    let ret = format!(
        "std::io::Result<Box<Stream<Item = {}, Error = std::io::Error> + Sync + Send>>",
        message.message_name().to_camel_case()
    );
    stream_fn.ret(ret);

    stream_fn.line("let socket = BCMSocket::open_nb(&can_interface)?;");

    let message_id = match message.message_id().0 & EFF_MASK {
            0...SFF_MASK => format!("let message_id = CANMessageId::SFF({} as u16);", (message.message_id().0 & EFF_MASK).to_string()),
            SFF_MASK...EFF_MASK => format!("let message_id = CANMessageId::EFF({} as u16);", (message.message_id().0 & SFF_MASK).to_string()),
            _ => unreachable!(),
    };
    stream_fn.line(message_id);

    stream_fn.line("let frame_stream = socket.filter_id_incoming_frames(message_id, ival1.clone(), ival2.clone())?;");
    stream_fn.line(format!(
        "let f = frame_stream.map(|frame| {}::new(frame.data().to_vec()));",
        message.message_name().to_camel_case()
    ));
    stream_fn.line("Ok(Box::new(f))");

    stream_fn
}

pub fn can_reader(opt: &DbccOpt, dbc: &DBC) -> Result<Scope> {
    let mut scope = Scope::new();
    scope.import("byteorder", "{ByteOrder, LE, BE}");

    if opt.with_tokio {
        scope.import("tokio_socketcan_bcm", "{CANMessageId, BCMSocket}");
        scope.import("futures", "Stream");
        scope.import("std::convert", "TryFrom");
    }

    for message in dbc.messages() {
        scope.raw(&message_const(message));
    }

    for value_description in dbc.value_descriptions() {
        if let Some(signal_enum) = signal_enum(value_description) {
            scope.push_enum(signal_enum);
        }

        if let Some(enum_impl) = signal_enum_impl_from(value_description) {
            scope.push_impl(enum_impl);
        }
    }

    for message in dbc.messages() {
        scope.push_struct(message_struct(&dbc, message));
        scope.push_impl(message_impl(opt, &dbc, message)?);
    }

    Ok(scope)
}
<|endoftext|>


<commit_before>type box[T] = tup(@T);

fn unbox[T](box[T] b) -> T { ret *b._0; }

fn main() {
  let int foo = 17;
  let box[int] bfoo = tup(@foo);
  log "see what's in our box";
  check (unbox[int](bfoo) == foo);
}
<commit_msg>Fix bug in box-unbox.rs test.<commit_after>type box[T] = tup(@T);

fn unbox[T](&box[T] b) -> T { ret *b._0; }

fn main() {
  let int foo = 17;
  let box[int] bfoo = tup(@foo);
  log "see what's in our box";
  check (unbox[int](bfoo) == foo);
}
<|endoftext|>


<commit_before>//! Tidy check to ensure below in UI test directories:
//! - the number of entries in each directory must be less than `ENTRY_LIMIT`
//! - there are no stray `.stderr` files

use std::fs;
use std::path::Path;

const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually.
const ROOT_ENTRY_LIMIT: usize = 1330;
const ISSUES_ENTRY_LIMIT: usize = 2488;

fn check_entries(path: &Path, bad: &mut bool) {
    let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
        .into_iter()
        .filter_entry(|e| e.file_type().is_dir());
    for dir in dirs {
        if let Ok(dir) = dir {
            let dir_path = dir.path();

            // Use special values for these dirs.
            let is_root = path.join("test/ui") == dir_path;
            let is_issues_dir = path.join("test/ui/issues") == dir_path;
            let limit = if is_root {
                ROOT_ENTRY_LIMIT
            } else if is_issues_dir {
                ISSUES_ENTRY_LIMIT
            } else {
                ENTRY_LIMIT
            };

            let count = std::fs::read_dir(dir_path).unwrap().count();
            if count > limit {
                tidy_error!(
                    bad,
                    "following path contains more than {} entries, \
                    you should move the test to some relevant subdirectory (current: {}): {}",
                    limit,
                    count,
                    dir_path.display()
                );
            }
        }
    }
}

pub fn check(path: &Path, bad: &mut bool) {
    check_entries(&path, bad);
    for path in &[&path.join("test/ui"), &path.join("test/ui-fulldeps")] {
        super::walk_no_read(path, &mut |_| false, &mut |entry| {
            let file_path = entry.path();
            if let Some(ext) = file_path.extension() {
                if ext == "stderr" || ext == "stdout" {
                    // Test output filenames have one of the formats:
                    // ```
                    // $testname.stderr
                    // $testname.$mode.stderr
                    // $testname.$revision.stderr
                    // $testname.$revision.$mode.stderr
                    // ```
                    //
                    // For now, just make sure that there is a corresponding
                    // `$testname.rs` file.
                    //
                    // NB: We do not use file_stem() as some file names have multiple `.`s and we
                    // must strip all of them.
                    let testname =
                        file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0;
                    if !file_path.with_file_name(testname).with_extension("rs").exists() {
                        tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
                    }

                    if let Ok(metadata) = fs::metadata(file_path) {
                        if metadata.len() == 0 {
                            tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
                        }
                    }
                }
            }
        });
    }
}
<commit_msg>Increase `ROOT_ENTRY_LIMIT` to 1331<commit_after>//! Tidy check to ensure below in UI test directories:
//! - the number of entries in each directory must be less than `ENTRY_LIMIT`
//! - there are no stray `.stderr` files

use std::fs;
use std::path::Path;

const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually.
const ROOT_ENTRY_LIMIT: usize = 1331;
const ISSUES_ENTRY_LIMIT: usize = 2488;

fn check_entries(path: &Path, bad: &mut bool) {
    let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
        .into_iter()
        .filter_entry(|e| e.file_type().is_dir());
    for dir in dirs {
        if let Ok(dir) = dir {
            let dir_path = dir.path();

            // Use special values for these dirs.
            let is_root = path.join("test/ui") == dir_path;
            let is_issues_dir = path.join("test/ui/issues") == dir_path;
            let limit = if is_root {
                ROOT_ENTRY_LIMIT
            } else if is_issues_dir {
                ISSUES_ENTRY_LIMIT
            } else {
                ENTRY_LIMIT
            };

            let count = std::fs::read_dir(dir_path).unwrap().count();
            if count > limit {
                tidy_error!(
                    bad,
                    "following path contains more than {} entries, \
                    you should move the test to some relevant subdirectory (current: {}): {}",
                    limit,
                    count,
                    dir_path.display()
                );
            }
        }
    }
}

pub fn check(path: &Path, bad: &mut bool) {
    check_entries(&path, bad);
    for path in &[&path.join("test/ui"), &path.join("test/ui-fulldeps")] {
        super::walk_no_read(path, &mut |_| false, &mut |entry| {
            let file_path = entry.path();
            if let Some(ext) = file_path.extension() {
                if ext == "stderr" || ext == "stdout" {
                    // Test output filenames have one of the formats:
                    // ```
                    // $testname.stderr
                    // $testname.$mode.stderr
                    // $testname.$revision.stderr
                    // $testname.$revision.$mode.stderr
                    // ```
                    //
                    // For now, just make sure that there is a corresponding
                    // `$testname.rs` file.
                    //
                    // NB: We do not use file_stem() as some file names have multiple `.`s and we
                    // must strip all of them.
                    let testname =
                        file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0;
                    if !file_path.with_file_name(testname).with_extension("rs").exists() {
                        tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
                    }

                    if let Ok(metadata) = fs::metadata(file_path) {
                        if metadata.len() == 0 {
                            tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
                        }
                    }
                }
            }
        });
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use base::{ioctl_ior_nr, ioctl_iow_nr, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_ref};
use data_model::Le32;

use super::constants::*;
use super::virtio_input_absinfo;
use super::virtio_input_bitmap;
use super::virtio_input_device_ids;
use super::InputError;
use super::Result;

use std::collections::BTreeMap;
use std::os::raw::c_uint;
use std::ptr::null;

use base::{AsRawDescriptor, Descriptor};

const EVDEV: c_uint = 69;

#[repr(C)]
#[derive(Copy, Clone)]
struct evdev_buffer {
    buffer: [std::os::raw::c_uchar; 128],
}

impl evdev_buffer {
    fn new() -> evdev_buffer {
        evdev_buffer { buffer: [0u8; 128] }
    }

    fn get(&self, bit: usize) -> bool {
        let idx = bit / 8;
        let inner_bit = bit % 8;
        self.buffer
            .get(idx)
            .map_or(false, |val| val & (1u8 << inner_bit) != 0)
    }
}

#[repr(C)]
#[derive(Copy, Clone)]
struct evdev_id {
    bustype: u16,
    vendor: u16,
    product: u16,
    version: u16,
}

impl evdev_id {
    fn new() -> evdev_id {
        evdev_id {
            bustype: 0,
            vendor: 0,
            product: 0,
            version: 0,
        }
    }
}

#[repr(C)]
#[derive(Copy, Clone)]
struct evdev_abs_info {
    // These should technically by signed ints, but Le32 is only compatible with u32 and we only
    // forward the bytes but don't care about its actual values.
    value: u32,
    minimum: u32,
    maximum: u32,
    fuzz: u32,
    flat: u32,
    resolution: u32,
}

impl evdev_abs_info {
    fn new() -> evdev_abs_info {
        evdev_abs_info {
            value: 0,
            minimum: 0,
            maximum: 0,
            fuzz: 0,
            flat: 0,
            resolution: 0,
        }
    }
}

impl From<evdev_abs_info> for virtio_input_absinfo {
    fn from(other: evdev_abs_info) -> Self {
        virtio_input_absinfo {
            min: Le32::from(other.minimum),
            max: Le32::from(other.maximum),
            fuzz: Le32::from(other.fuzz),
            flat: Le32::from(other.flat),
        }
    }
}

ioctl_ior_nr!(EVIOCGID, EVDEV, 0x02, evdev_id);
ioctl_ior_nr!(EVIOCGNAME, EVDEV, 0x06, evdev_buffer);
ioctl_ior_nr!(EVIOCGUNIQ, EVDEV, 0x08, evdev_buffer);
ioctl_ior_nr!(EVIOCGPROP, EVDEV, 0x09, evdev_buffer);
ioctl_ior_nr!(EVIOCGBIT, EVDEV, 0x20 + evt, evdev_buffer, evt);
ioctl_ior_nr!(EVIOCGABS, EVDEV, 0x40 + abs, evdev_abs_info, abs);
ioctl_iow_nr!(EVIOCGRAB, EVDEV, 0x90, u32);

fn errno() -> base::Error {
    base::Error::last()
}

/// Gets id information from an event device (see EVIOCGID ioctl for details).
pub fn device_ids<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_device_ids> {
    let mut dev_id = evdev_id::new();
    let len = unsafe {
        // Safe because the kernel won't write more than size of evdev_id and we check the return
        // value
        ioctl_with_mut_ref(
            &Descriptor(descriptor.as_raw_descriptor()),
            EVIOCGID(),
            &mut dev_id,
        )
    };
    if len < 0 {
        return Err(InputError::EvdevIdError(errno()));
    }
    Ok(virtio_input_device_ids::new(
        dev_id.bustype,
        dev_id.vendor,
        dev_id.product,
        dev_id.version,
    ))
}

/// Gets the name of an event device (see EVIOCGNAME ioctl for details).
pub fn name<T: AsRawDescriptor>(descriptor: &T) -> Result<Vec<u8>> {
    let mut name = evdev_buffer::new();
    let len = unsafe {
        // Safe because the kernel won't write more than size of evdev_buffer and we check the
        // return value
        ioctl_with_mut_ref(
            &Descriptor(descriptor.as_raw_descriptor()),
            EVIOCGNAME(),
            &mut name,
        )
    };
    if len < 0 {
        return Err(InputError::EvdevNameError(errno()));
    }
    Ok(name.buffer[0..len as usize].to_vec())
}

/// Gets the unique (serial) name of an event device (see EVIOCGUNIQ ioctl for details).
pub fn serial_name<T: AsRawDescriptor>(descriptor: &T) -> Result<Vec<u8>> {
    let mut uniq = evdev_buffer::new();
    let len = unsafe {
        // Safe because the kernel won't write more than size of evdev_buffer and we check the
        // return value
        ioctl_with_mut_ref(
            &Descriptor(descriptor.as_raw_descriptor()),
            EVIOCGUNIQ(),
            &mut uniq,
        )
    };
    if len < 0 {
        return Err(InputError::EvdevSerialError(errno()));
    }
    Ok(uniq.buffer[0..len as usize].to_vec())
}

/// Gets the properties of an event device (see EVIOCGPROP ioctl for details).
pub fn properties<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_bitmap> {
    let mut props = evdev_buffer::new();
    let len = unsafe {
        // Safe because the kernel won't write more than size of evdev_buffer and we check the
        // return value
        ioctl_with_mut_ref(
            &Descriptor(descriptor.as_raw_descriptor()),
            EVIOCGPROP(),
            &mut props,
        )
    };
    if len < 0 {
        return Err(InputError::EvdevPropertiesError(errno()));
    }
    Ok(virtio_input_bitmap::new(props.buffer))
}

/// Gets the event types supported by an event device as well as the event codes supported for each
/// type (see EVIOCGBIT ioctl for details).
pub fn supported_events<T: AsRawDescriptor>(
    descriptor: &T,
) -> Result<BTreeMap<u16, virtio_input_bitmap>> {
    let mut evts: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();

    let mut evt_types = evdev_buffer::new();
    let len = unsafe {
        // Safe because the kernel won't write more than size of evdev_buffer and we check the
        // return value
        ioctl_with_mut_ref(
            &Descriptor(descriptor.as_raw_descriptor()),
            EVIOCGBIT(0),
            &mut evt_types,
        )
    };
    if len < 0 {
        return Err(InputError::EvdevEventTypesError(errno()));
    }

    // no need to ask for zero (EV_SYN) since it's always supported and treated as a special case
    for ev in 1..EV_MAX {
        if ev == EV_REP || !evt_types.get(ev as usize) {
            // Event type not supported, skip it.
            continue;
        }
        // Create a new zero-filled buffer every time to avoid carry-overs.
        let mut evt_codes = evdev_buffer::new();
        let len = unsafe {
            // Safe because the kernel won't write more than size of evdev_buffer and we check the
            // return value
            ioctl_with_mut_ref(
                &Descriptor(descriptor.as_raw_descriptor()),
                EVIOCGBIT(ev as c_uint),
                &mut evt_codes,
            )
        };
        if len < 0 {
            return Err(InputError::EvdevEventTypesError(errno()));
        }
        evts.insert(ev, virtio_input_bitmap::new(evt_codes.buffer));
    }
    Ok(evts)
}

/// Gets the absolute axes of an event device (see EVIOCGABS ioctl for details).
pub fn abs_info<T: AsRawDescriptor>(descriptor: &T) -> BTreeMap<u16, virtio_input_absinfo> {
    let mut map: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();

    for abs in 0..ABS_MAX {
        // Create a new one, zero-ed out every time to avoid carry-overs.
        let mut abs_info = evdev_abs_info::new();
        let ret = unsafe {
            // Safe because the kernel won't write more than size of evdev_buffer and we check the
            // return value
            ioctl_with_mut_ref(
                &Descriptor(descriptor.as_raw_descriptor()),
                EVIOCGABS(abs as c_uint),
                &mut abs_info,
            )
        };
        if ret == 0 {
            map.insert(abs, virtio_input_absinfo::from(abs_info));
        }
    }
    map
}

/// Grabs an event device (see EVIOCGGRAB ioctl for details). After this function succeeds the given
/// descriptor has exclusive access to the device, effectively making it unusable for any other process in
/// the host.
pub fn grab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()> {
    let val: u32 = 1;
    let ret = unsafe {
        // Safe because the kernel only read the value of the ptr and we check the return value
        ioctl_with_ref(
            &Descriptor(descriptor.as_raw_descriptor()),
            EVIOCGRAB(),
            &val,
        )
    };
    if ret == 0 {
        Ok(())
    } else {
        Err(InputError::EvdevGrabError(errno()))
    }
}

pub fn ungrab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()> {
    let ret = unsafe {
        // Safe because the kernel only reads the value of the ptr (doesn't dereference) and
        // we check the return value
        ioctl_with_ptr(
            &Descriptor(descriptor.as_raw_descriptor()),
            EVIOCGRAB(),
            null::<u32>(),
        )
    };
    if ret == 0 {
        Ok(())
    } else {
        Err(InputError::EvdevGrabError(errno()))
    }
}
<commit_msg>devices: input: stop using Descriptor in evdev<commit_after>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use base::{ioctl_ior_nr, ioctl_iow_nr, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_ref};
use data_model::Le32;

use super::constants::*;
use super::virtio_input_absinfo;
use super::virtio_input_bitmap;
use super::virtio_input_device_ids;
use super::InputError;
use super::Result;

use std::collections::BTreeMap;
use std::os::raw::c_uint;
use std::ptr::null;

use base::AsRawDescriptor;

const EVDEV: c_uint = 69;

#[repr(C)]
#[derive(Copy, Clone)]
struct evdev_buffer {
    buffer: [std::os::raw::c_uchar; 128],
}

impl evdev_buffer {
    fn new() -> evdev_buffer {
        evdev_buffer { buffer: [0u8; 128] }
    }

    fn get(&self, bit: usize) -> bool {
        let idx = bit / 8;
        let inner_bit = bit % 8;
        self.buffer
            .get(idx)
            .map_or(false, |val| val & (1u8 << inner_bit) != 0)
    }
}

#[repr(C)]
#[derive(Copy, Clone)]
struct evdev_id {
    bustype: u16,
    vendor: u16,
    product: u16,
    version: u16,
}

impl evdev_id {
    fn new() -> evdev_id {
        evdev_id {
            bustype: 0,
            vendor: 0,
            product: 0,
            version: 0,
        }
    }
}

#[repr(C)]
#[derive(Copy, Clone)]
struct evdev_abs_info {
    // These should technically by signed ints, but Le32 is only compatible with u32 and we only
    // forward the bytes but don't care about its actual values.
    value: u32,
    minimum: u32,
    maximum: u32,
    fuzz: u32,
    flat: u32,
    resolution: u32,
}

impl evdev_abs_info {
    fn new() -> evdev_abs_info {
        evdev_abs_info {
            value: 0,
            minimum: 0,
            maximum: 0,
            fuzz: 0,
            flat: 0,
            resolution: 0,
        }
    }
}

impl From<evdev_abs_info> for virtio_input_absinfo {
    fn from(other: evdev_abs_info) -> Self {
        virtio_input_absinfo {
            min: Le32::from(other.minimum),
            max: Le32::from(other.maximum),
            fuzz: Le32::from(other.fuzz),
            flat: Le32::from(other.flat),
        }
    }
}

ioctl_ior_nr!(EVIOCGID, EVDEV, 0x02, evdev_id);
ioctl_ior_nr!(EVIOCGNAME, EVDEV, 0x06, evdev_buffer);
ioctl_ior_nr!(EVIOCGUNIQ, EVDEV, 0x08, evdev_buffer);
ioctl_ior_nr!(EVIOCGPROP, EVDEV, 0x09, evdev_buffer);
ioctl_ior_nr!(EVIOCGBIT, EVDEV, 0x20 + evt, evdev_buffer, evt);
ioctl_ior_nr!(EVIOCGABS, EVDEV, 0x40 + abs, evdev_abs_info, abs);
ioctl_iow_nr!(EVIOCGRAB, EVDEV, 0x90, u32);

fn errno() -> base::Error {
    base::Error::last()
}

/// Gets id information from an event device (see EVIOCGID ioctl for details).
pub fn device_ids<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_device_ids> {
    let mut dev_id = evdev_id::new();
    let len = unsafe {
        // Safe because the kernel won't write more than size of evdev_id and we check the return
        // value
        ioctl_with_mut_ref(descriptor, EVIOCGID(), &mut dev_id)
    };
    if len < 0 {
        return Err(InputError::EvdevIdError(errno()));
    }
    Ok(virtio_input_device_ids::new(
        dev_id.bustype,
        dev_id.vendor,
        dev_id.product,
        dev_id.version,
    ))
}

/// Gets the name of an event device (see EVIOCGNAME ioctl for details).
pub fn name<T: AsRawDescriptor>(descriptor: &T) -> Result<Vec<u8>> {
    let mut name = evdev_buffer::new();
    let len = unsafe {
        // Safe because the kernel won't write more than size of evdev_buffer and we check the
        // return value
        ioctl_with_mut_ref(descriptor, EVIOCGNAME(), &mut name)
    };
    if len < 0 {
        return Err(InputError::EvdevNameError(errno()));
    }
    Ok(name.buffer[0..len as usize].to_vec())
}

/// Gets the unique (serial) name of an event device (see EVIOCGUNIQ ioctl for details).
pub fn serial_name<T: AsRawDescriptor>(descriptor: &T) -> Result<Vec<u8>> {
    let mut uniq = evdev_buffer::new();
    let len = unsafe {
        // Safe because the kernel won't write more than size of evdev_buffer and we check the
        // return value
        ioctl_with_mut_ref(descriptor, EVIOCGUNIQ(), &mut uniq)
    };
    if len < 0 {
        return Err(InputError::EvdevSerialError(errno()));
    }
    Ok(uniq.buffer[0..len as usize].to_vec())
}

/// Gets the properties of an event device (see EVIOCGPROP ioctl for details).
pub fn properties<T: AsRawDescriptor>(descriptor: &T) -> Result<virtio_input_bitmap> {
    let mut props = evdev_buffer::new();
    let len = unsafe {
        // Safe because the kernel won't write more than size of evdev_buffer and we check the
        // return value
        ioctl_with_mut_ref(descriptor, EVIOCGPROP(), &mut props)
    };
    if len < 0 {
        return Err(InputError::EvdevPropertiesError(errno()));
    }
    Ok(virtio_input_bitmap::new(props.buffer))
}

/// Gets the event types supported by an event device as well as the event codes supported for each
/// type (see EVIOCGBIT ioctl for details).
pub fn supported_events<T: AsRawDescriptor>(
    descriptor: &T,
) -> Result<BTreeMap<u16, virtio_input_bitmap>> {
    let mut evts: BTreeMap<u16, virtio_input_bitmap> = BTreeMap::new();

    let mut evt_types = evdev_buffer::new();
    let len = unsafe {
        // Safe because the kernel won't write more than size of evdev_buffer and we check the
        // return value
        ioctl_with_mut_ref(descriptor, EVIOCGBIT(0), &mut evt_types)
    };
    if len < 0 {
        return Err(InputError::EvdevEventTypesError(errno()));
    }

    // no need to ask for zero (EV_SYN) since it's always supported and treated as a special case
    for ev in 1..EV_MAX {
        if ev == EV_REP || !evt_types.get(ev as usize) {
            // Event type not supported, skip it.
            continue;
        }
        // Create a new zero-filled buffer every time to avoid carry-overs.
        let mut evt_codes = evdev_buffer::new();
        let len = unsafe {
            // Safe because the kernel won't write more than size of evdev_buffer and we check the
            // return value
            ioctl_with_mut_ref(descriptor, EVIOCGBIT(ev as c_uint), &mut evt_codes)
        };
        if len < 0 {
            return Err(InputError::EvdevEventTypesError(errno()));
        }
        evts.insert(ev, virtio_input_bitmap::new(evt_codes.buffer));
    }
    Ok(evts)
}

/// Gets the absolute axes of an event device (see EVIOCGABS ioctl for details).
pub fn abs_info<T: AsRawDescriptor>(descriptor: &T) -> BTreeMap<u16, virtio_input_absinfo> {
    let mut map: BTreeMap<u16, virtio_input_absinfo> = BTreeMap::new();

    for abs in 0..ABS_MAX {
        // Create a new one, zero-ed out every time to avoid carry-overs.
        let mut abs_info = evdev_abs_info::new();
        let ret = unsafe {
            // Safe because the kernel won't write more than size of evdev_buffer and we check the
            // return value
            ioctl_with_mut_ref(descriptor, EVIOCGABS(abs as c_uint), &mut abs_info)
        };
        if ret == 0 {
            map.insert(abs, virtio_input_absinfo::from(abs_info));
        }
    }
    map
}

/// Grabs an event device (see EVIOCGGRAB ioctl for details). After this function succeeds the given
/// descriptor has exclusive access to the device, effectively making it unusable for any other process in
/// the host.
pub fn grab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()> {
    let val: u32 = 1;
    let ret = unsafe {
        // Safe because the kernel only read the value of the ptr and we check the return value
        ioctl_with_ref(descriptor, EVIOCGRAB(), &val)
    };
    if ret == 0 {
        Ok(())
    } else {
        Err(InputError::EvdevGrabError(errno()))
    }
}

pub fn ungrab_evdev<T: AsRawDescriptor>(descriptor: &mut T) -> Result<()> {
    let ret = unsafe {
        // Safe because the kernel only reads the value of the ptr (doesn't dereference) and
        // we check the return value
        ioctl_with_ptr(descriptor, EVIOCGRAB(), null::<u32>())
    };
    if ret == 0 {
        Ok(())
    } else {
        Err(InputError::EvdevGrabError(errno()))
    }
}
<|endoftext|>