<commit_before>#[ link(name = "rust-quickcheck",
        vers = "0.1",
        uuid = "510d3dae-f7b1-11e2-83f1-bb59638dec3b") ];

#[ desc = "Property based randomized testing library" ];
#[ license = "ISC" ];
#[ author = "Daniel Patterson" ];

#[ crate_type = "lib" ];

#[ warn(non_camel_case_types) ];

extern mod extra;
use std::rand;
use std::vec;
use std::num;
use extra::sort;

/**
 * Arbitrary is a trait for types that you can generate arbitrary
 * instances of. You should also be able to ask for their size, so
 * you can report small failing examples instead of large ones.
 *
 */
pub trait Arbitrary : Clone {
    fn gen() -> Self;
    fn size(&self) -> uint;
}

impl Arbitrary for uint {
    fn gen() -> uint {
        let n : uint = rand::random();
         n % num::pow_with_uint(2,10)
    }
    fn size(&self) -> uint {
        self.clone()
    }
}

impl Arbitrary for int {
    fn gen() -> int {
        let n : int = rand::random();
        n % num::pow_with_uint(2,10)
    }

    fn size(&self) -> uint {
        self.clone().to_uint()
    }
}

impl<T:Arbitrary> Arbitrary for ~[T] {
    fn gen() -> ~[T] {
        let _n : uint = rand::random();
        let n = _n % 100;
        vec::build_sized(n, |p| {
            for n.times {
                p(Arbitrary::gen());
            }
        })
    }

    fn size(&self) -> uint {
        self.len()
    }
}

/**
 * Result is what is returned from property tests; it includes
 * representations of the generated input in the case of failure.
 */
#[deriving(Clone)]
enum Result {
    Pass,
    Failure(uint, ~str)
}

fn result_str(r : ~Result) -> ~str {
    match r {
        ~Pass => ~"",
        ~Failure(_, s) => s.clone()
    }
}

/**
 * Testable is a trait for things that can be tested. This generally means
 * functions that take arguments of trait Arbitrary.
 */
pub trait Testable {
    fn apply(&self) -> ~Result;
}

impl<T:Arbitrary> Testable for extern fn(T) -> bool {
    fn apply(&self) -> ~Result {
        let t : T = Arbitrary::gen();
        if (*self)(t.clone()) {
            ~Pass
        } else {
            ~Failure(t.size(), fmt!("%?",t))
        }
    }
}

impl<T:Arbitrary, U:Arbitrary> Testable for extern fn(T,U) -> bool {
    fn apply(&self) -> ~Result {
        let t : T = Arbitrary::gen();
        let u : U = Arbitrary::gen();
        if (*self)(t.clone(), u.clone()) {
            ~Pass
        } else {
            ~Failure(t.size() + u.size(), fmt!("%?, %?",t, u))
        }
    }
}

/**
 * quick_check
 *   description: a string describing what the property being tested is
 *   f: a Testable (ie, function taking arguments that are Arbitrary)
 *
 *   returns whether all the tests passed.
 */
pub fn quick_check<F:Testable>(description: &str, f: F) -> bool {
    quick_check_internal(description, f, false)
}

/**
 * quick_check_silent
 *   description: a string describing what the property being tested is
 *   f: a Testable (ie, function taking arguments that are Arbitrary)
 *
 *   returns whether all the tests passed.
 *
 * note: does not print out any output.
 */
pub fn quick_check_silent<F:Testable>(description: &str, f: F) -> bool {
    quick_check_internal(description, f, true)
}

fn quick_check_internal<F:Testable>(description: &str,
                                    f: F,
                                    silent: bool) -> bool {
    let num_tests = 100;
    let mut passing = 0;
    let mut failed = ~[];
    for num_tests.times {
        match f.apply() {
            ~Pass            => { passing += 1; }
            ~Failure(s,args) => { failed.push(~Failure(s,args)); }
        }
    }
    if passing == num_tests {
        if !silent {
            println(fmt!("+++ OK, passed 100 tests for %s", description));
        }
        return true;
    } else {
        if !silent {
            println(fmt!("*** Failed '%s' on:", description));
            if failed.len() < 5 {
                // is this really the best way? can't be...
                let mut i = 0;
                for failed.len().times {
                    println(fmt!("%?", failed[i].clone()));
                    i += 1;
                }
            } else {
                sort::quick_sort(failed, |e1, e2| {
                    match (e1,e2) {
                        (&~Failure(s1,_), &~Failure(s2,_)) => { s1 <= s2 }
                        _ => { fail!() }
                    }
                });
                let mut i = 0;
                for 5.times {
                    println(fmt!("%?", result_str(failed[i].clone())));
                    i += 1;
                }
                println("...and more");
            }
        }
        return false;
    }
}

#[test]
fn reverse_uint_vecs() {
    fn reverse<A:Clone>(v : ~[A]) -> ~[A] {
        let mut newvec = ~[];
        for v.iter().advance |e| {
            // NOTE(dbp 2013-07-25): This is intentionally buggy - should be unshift.
            newvec.push(e.clone());
        }
        return newvec;
    }

    fn prop_reverse_reverse_uints(v : ~[uint]) -> bool {
        reverse(reverse(v.clone())) == v
    }

    fn prop_reverse_moves_first_to_last(v : ~[uint]) -> bool {
        if v.len() > 0 {
            reverse(v.clone())[v.len() - 1] == v[0]
        } else {
            true // trivially
        }
    }

    assert!(
        quick_check_silent("reversing a list twice yields the same list",
                           prop_reverse_reverse_uints));
    assert!(
        !quick_check_silent("reversing a list moves first to last",
                       prop_reverse_moves_first_to_last));
}

#[test]
fn struct_gen() {

    #[deriving(Clone, Eq)]
    struct Foo { n: uint, xs: ~[int] }

    impl Arbitrary for Foo {
        fn gen() -> Foo {
            Foo { n: Arbitrary::gen(), xs: Arbitrary::gen() }
        }
        fn size(&self) -> uint {
            self.xs.len()
        }
    }
    // NOTE(dbp 2013-07-27): Not sure why this isn't covered by `deriving`,
    // is it a not-yet-implemented feature?
    impl Clone for Foo {
        fn clone(&self) -> Foo {
            Foo { n: self.n, xs: self.xs.clone() }
        }
    }
    impl Eq for Foo {
        fn eq(&self, other: &Foo) -> bool {
            self.n == other.n && self.xs == other.xs
        }
    }

    fn add_foos(a1: &Foo, a2: &Foo) -> Foo {
        let mut new_xs = ~[];
        new_xs = vec::append(new_xs, a1.xs);
        new_xs = vec::append(new_xs, a2.xs);
        Foo {n: a1.n + a2.n, xs: new_xs}
    }

    // NOTE(dbp 2013-07-27): This is obviously not true.
    fn prop_add_foos_commutes(a1: Foo, a2: Foo) -> bool {
        add_foos(&a1, &a2) == add_foos(&a2, &a1)
    }

    fn prop_add_zero_foo_identity(a: Foo) -> bool {
        add_foos(&a, &Foo {n: 0, xs: ~[]}) == a
    }

    assert!(
        !quick_check_silent("add_foos is commutative",
                            prop_add_foos_commutes));

    assert!(
        quick_check_silent("add_foos with a zero Foo is an identity",
                           prop_add_zero_foo_identity));
}<commit_msg>change name of lib to just quickcheck<commit_after>#[ link(name = "quickcheck",
        vers = "0.1",
        uuid = "510d3dae-f7b1-11e2-83f1-bb59638dec3b") ];

#[ desc = "Property based randomized testing library" ];
#[ license = "ISC" ];
#[ author = "Daniel Patterson" ];

#[ crate_type = "lib" ];

#[ warn(non_camel_case_types) ];

extern mod extra;
use std::rand;
use std::vec;
use std::num;
use extra::sort;

/**
 * Arbitrary is a trait for types that you can generate arbitrary
 * instances of. You should also be able to ask for their size, so
 * you can report small failing examples instead of large ones.
 *
 */
pub trait Arbitrary : Clone {
    fn gen() -> Self;
    fn size(&self) -> uint;
}

impl Arbitrary for uint {
    fn gen() -> uint {
        let n : uint = rand::random();
         n % num::pow_with_uint(2,10)
    }
    fn size(&self) -> uint {
        self.clone()
    }
}

impl Arbitrary for int {
    fn gen() -> int {
        let n : int = rand::random();
        n % num::pow_with_uint(2,10)
    }

    fn size(&self) -> uint {
        self.clone().to_uint()
    }
}

impl<T:Arbitrary> Arbitrary for ~[T] {
    fn gen() -> ~[T] {
        let _n : uint = rand::random();
        let n = _n % 100;
        vec::build_sized(n, |p| {
            for n.times {
                p(Arbitrary::gen());
            }
        })
    }

    fn size(&self) -> uint {
        self.len()
    }
}

/**
 * Result is what is returned from property tests; it includes
 * representations of the generated input in the case of failure.
 */
#[deriving(Clone)]
enum Result {
    Pass,
    Failure(uint, ~str)
}

fn result_str(r : ~Result) -> ~str {
    match r {
        ~Pass => ~"",
        ~Failure(_, s) => s.clone()
    }
}

/**
 * Testable is a trait for things that can be tested. This generally means
 * functions that take arguments of trait Arbitrary.
 */
pub trait Testable {
    fn apply(&self) -> ~Result;
}

impl<T:Arbitrary> Testable for extern fn(T) -> bool {
    fn apply(&self) -> ~Result {
        let t : T = Arbitrary::gen();
        if (*self)(t.clone()) {
            ~Pass
        } else {
            ~Failure(t.size(), fmt!("%?",t))
        }
    }
}

impl<T:Arbitrary, U:Arbitrary> Testable for extern fn(T,U) -> bool {
    fn apply(&self) -> ~Result {
        let t : T = Arbitrary::gen();
        let u : U = Arbitrary::gen();
        if (*self)(t.clone(), u.clone()) {
            ~Pass
        } else {
            ~Failure(t.size() + u.size(), fmt!("%?, %?",t, u))
        }
    }
}

/**
 * quick_check
 *   description: a string describing what the property being tested is
 *   f: a Testable (ie, function taking arguments that are Arbitrary)
 *
 *   returns whether all the tests passed.
 */
pub fn quick_check<F:Testable>(description: &str, f: F) -> bool {
    quick_check_internal(description, f, false)
}

/**
 * quick_check_silent
 *   description: a string describing what the property being tested is
 *   f: a Testable (ie, function taking arguments that are Arbitrary)
 *
 *   returns whether all the tests passed.
 *
 * note: does not print out any output.
 */
pub fn quick_check_silent<F:Testable>(description: &str, f: F) -> bool {
    quick_check_internal(description, f, true)
}

fn quick_check_internal<F:Testable>(description: &str,
                                    f: F,
                                    silent: bool) -> bool {
    let num_tests = 100;
    let mut passing = 0;
    let mut failed = ~[];
    for num_tests.times {
        match f.apply() {
            ~Pass            => { passing += 1; }
            ~Failure(s,args) => { failed.push(~Failure(s,args)); }
        }
    }
    if passing == num_tests {
        if !silent {
            println(fmt!("+++ OK, passed 100 tests for %s", description));
        }
        return true;
    } else {
        if !silent {
            println(fmt!("*** Failed '%s' on:", description));
            if failed.len() < 5 {
                // is this really the best way? can't be...
                let mut i = 0;
                for failed.len().times {
                    println(fmt!("%?", failed[i].clone()));
                    i += 1;
                }
            } else {
                sort::quick_sort(failed, |e1, e2| {
                    match (e1,e2) {
                        (&~Failure(s1,_), &~Failure(s2,_)) => { s1 <= s2 }
                        _ => { fail!() }
                    }
                });
                let mut i = 0;
                for 5.times {
                    println(fmt!("%?", result_str(failed[i].clone())));
                    i += 1;
                }
                println("...and more");
            }
        }
        return false;
    }
}

#[test]
fn reverse_uint_vecs() {
    fn reverse<A:Clone>(v : ~[A]) -> ~[A] {
        let mut newvec = ~[];
        for v.iter().advance |e| {
            // NOTE(dbp 2013-07-25): This is intentionally buggy - should be unshift.
            newvec.push(e.clone());
        }
        return newvec;
    }

    fn prop_reverse_reverse_uints(v : ~[uint]) -> bool {
        reverse(reverse(v.clone())) == v
    }

    fn prop_reverse_moves_first_to_last(v : ~[uint]) -> bool {
        if v.len() > 0 {
            reverse(v.clone())[v.len() - 1] == v[0]
        } else {
            true // trivially
        }
    }

    assert!(
        quick_check_silent("reversing a list twice yields the same list",
                           prop_reverse_reverse_uints));
    assert!(
        !quick_check_silent("reversing a list moves first to last",
                       prop_reverse_moves_first_to_last));
}

#[test]
fn struct_gen() {

    #[deriving(Clone, Eq)]
    struct Foo { n: uint, xs: ~[int] }

    impl Arbitrary for Foo {
        fn gen() -> Foo {
            Foo { n: Arbitrary::gen(), xs: Arbitrary::gen() }
        }
        fn size(&self) -> uint {
            self.xs.len()
        }
    }
    // NOTE(dbp 2013-07-27): Not sure why this isn't covered by `deriving`,
    // is it a not-yet-implemented feature?
    impl Clone for Foo {
        fn clone(&self) -> Foo {
            Foo { n: self.n, xs: self.xs.clone() }
        }
    }
    impl Eq for Foo {
        fn eq(&self, other: &Foo) -> bool {
            self.n == other.n && self.xs == other.xs
        }
    }

    fn add_foos(a1: &Foo, a2: &Foo) -> Foo {
        let mut new_xs = ~[];
        new_xs = vec::append(new_xs, a1.xs);
        new_xs = vec::append(new_xs, a2.xs);
        Foo {n: a1.n + a2.n, xs: new_xs}
    }

    // NOTE(dbp 2013-07-27): This is obviously not true.
    fn prop_add_foos_commutes(a1: Foo, a2: Foo) -> bool {
        add_foos(&a1, &a2) == add_foos(&a2, &a1)
    }

    fn prop_add_zero_foo_identity(a: Foo) -> bool {
        add_foos(&a, &Foo {n: 0, xs: ~[]}) == a
    }

    assert!(
        !quick_check_silent("add_foos is commutative",
                            prop_add_foos_commutes));

    assert!(
        quick_check_silent("add_foos with a zero Foo is an identity",
                           prop_add_zero_foo_identity));
}<|endoftext|>


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

use syntax::ast;
use syntax::ast::P;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ToTokens;
use syntax::parse::token;

use super::Builder;
use super::utils;
use super::super::node;

/// A visitor to build accessor functions for each register struct
pub struct BuildAccessors<'a, 'b, 'c> {
  builder: &'a mut Builder,
  cx: &'b ExtCtxt<'c>,
}

impl<'a, 'b, 'c> node::RegVisitor for BuildAccessors<'a, 'b, 'c> {
  fn visit_prim_reg(&mut self, path: &Vec<String>, reg: &node::Reg,
                    _width: node::RegWidth, fields: &Vec<node::Field>) {
    let item = build_get_fn(self.cx, path, reg);
    self.builder.push_item(item);

    for field in fields.iter() {
      match build_field_accessors(self.cx, path, reg, field) {
        Some(item) => self.builder.push_item(item),
        None       => {}
      }
    }
  }
}

impl<'a, 'b, 'c> BuildAccessors<'a, 'b, 'c> {
  pub fn new(builder: &'a mut Builder, cx: &'b ExtCtxt<'c>)
             -> BuildAccessors<'a, 'b, 'c> {
    BuildAccessors {builder: builder, cx: cx}
  }
}

fn build_field_accessors<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
                             reg: &node::Reg, field: &node::Field)
                             -> Option<P<ast::Item>>
{
  let reg_ty: P<ast::Ty> =
    cx.ty_ident(DUMMY_SP, utils::path_ident(cx, path));

  let items = match field.access {
    node::ReadWrite => vec!(build_field_set_fn(cx, path, reg, field),
                            build_field_get_fn(cx, path, reg, field)),
    node::ReadOnly  => vec!(build_field_get_fn(cx, path, reg, field)),
    node::WriteOnly => vec!(build_field_set_fn(cx, path, reg, field)),
    node::SetToClear => vec!(build_field_clear_fn(cx, path, reg, field)),
  };

  let access_tag = match field.access {
    node::ReadWrite => "read/write",
    node::ReadOnly  => "read-only",
    node::WriteOnly => "write-only",
    node::SetToClear => "set-to-clear",
  };

  let field_doc = match field.docstring {
    Some(ref d) => {
      let s = token::get_ident(d.node);
      s.get().into_string()
    },
    None => "no documentation".into_string()
  };
  let docstring = format!("*[{}]* Field `{}`: {}",
                          access_tag,
                          field.name.node,
                          field_doc);
  let doc_attr = utils::doc_attribute(cx, utils::intern_string(cx, docstring));

  quote_item!(cx,
    $doc_attr
    impl $reg_ty {
      $items
    }
  )
}

fn build_get_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>, reg: &node::Reg)
                    -> P<ast::Item>
{
  let reg_ty: P<ast::Ty> =
    cx.ty_ident(DUMMY_SP, utils::path_ident(cx, path));
  let getter_ty = utils::getter_name(cx, path);

  let docstring = format!("Fetch the value of the `{}` register",
                          reg.name.node);
  let doc_attr = utils::doc_attribute(cx, utils::intern_string(cx, docstring));

  let item = quote_item!(cx,
    impl $reg_ty {
      $doc_attr
      #[allow(dead_code)]
      pub fn get(&'static self) -> $getter_ty {
        $getter_ty::new(self)
      }
    }
    );
  item.unwrap()
}

fn build_field_set_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
                          reg: &node::Reg, field: &node::Field)
                          -> P<ast::Method>
{
  let fn_name =
    cx.ident_of((String::from_str("set_")+field.name.node).as_slice());
  let field_ty: P<ast::Ty> =
    cx.ty_path(utils::field_type_path(cx, path, reg, field), None);
  let setter_ty = utils::setter_name(cx, path);
  if field.count.node == 1 {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self, new_value: $field_ty) -> $setter_ty {
        let mut setter: $setter_ty = $setter_ty::new(self);
        setter.$fn_name(new_value);
        setter
      }
    )
  } else {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self, idx: uint, new_value: $field_ty) -> $setter_ty {
        let mut setter: $setter_ty = $setter_ty::new(self);
        setter.$fn_name(idx, new_value);
        setter
      }
    )
  }
}

fn build_field_get_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
                          reg: &node::Reg, field: &node::Field)
                          -> P<ast::Method>
{
  let fn_name = cx.ident_of(field.name.node.as_slice());
  let field_ty: P<ast::Ty> =
    cx.ty_path(utils::field_type_path(cx, path, reg, field), None);
  let getter_ty = utils::getter_name(cx, path);
  if field.count.node == 1 {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self) -> $field_ty {
        $getter_ty::new(self).$fn_name()
      }
    )
  } else {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self, idx: uint) -> $field_ty {
        $getter_ty::new(self).$fn_name(idx)
      }
    )
  }
}

fn build_field_clear_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
                            _reg: &node::Reg, field: &node::Field)
                            -> P<ast::Method>
{
  let fn_name =
    cx.ident_of((String::from_str("clear_")+field.name.node).as_slice());
  let setter_ty = utils::setter_name(cx, path);
  if field.count.node == 1 {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self) -> $setter_ty {
        let mut setter: $setter_ty = $setter_ty::new(self);
        setter.$fn_name();
        setter
      }
    )
  } else {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self, idx: uint) -> $setter_ty {
        let mut setter: $setter_ty = $setter_ty::new(self);
        setter.$fn_name(idx);
        setter
      }
    )
  }
}
<commit_msg>Fix getters for register with only wo fields<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Ben Gamari <bgamari@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use syntax::ast;
use syntax::ast::P;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ToTokens;
use syntax::parse::token;

use super::Builder;
use super::utils;
use super::super::node;

/// A visitor to build accessor functions for each register struct
pub struct BuildAccessors<'a, 'b, 'c> {
  builder: &'a mut Builder,
  cx: &'b ExtCtxt<'c>,
}

impl<'a, 'b, 'c> node::RegVisitor for BuildAccessors<'a, 'b, 'c> {
  fn visit_prim_reg(&mut self, path: &Vec<String>, reg: &node::Reg,
                    _width: node::RegWidth, fields: &Vec<node::Field>) {
    if fields.iter().any(|f| f.access != node::WriteOnly) {
      let item = build_get_fn(self.cx, path, reg);
      self.builder.push_item(item);
    }

    for field in fields.iter() {
      match build_field_accessors(self.cx, path, reg, field) {
        Some(item) => self.builder.push_item(item),
        None       => {}
      }
    }
  }
}

impl<'a, 'b, 'c> BuildAccessors<'a, 'b, 'c> {
  pub fn new(builder: &'a mut Builder, cx: &'b ExtCtxt<'c>)
             -> BuildAccessors<'a, 'b, 'c> {
    BuildAccessors {builder: builder, cx: cx}
  }
}

fn build_field_accessors<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
                             reg: &node::Reg, field: &node::Field)
                             -> Option<P<ast::Item>>
{
  let reg_ty: P<ast::Ty> =
    cx.ty_ident(DUMMY_SP, utils::path_ident(cx, path));

  let items = match field.access {
    node::ReadWrite => vec!(build_field_set_fn(cx, path, reg, field),
                            build_field_get_fn(cx, path, reg, field)),
    node::ReadOnly  => vec!(build_field_get_fn(cx, path, reg, field)),
    node::WriteOnly => vec!(build_field_set_fn(cx, path, reg, field)),
    node::SetToClear => vec!(build_field_clear_fn(cx, path, reg, field)),
  };

  let access_tag = match field.access {
    node::ReadWrite => "read/write",
    node::ReadOnly  => "read-only",
    node::WriteOnly => "write-only",
    node::SetToClear => "set-to-clear",
  };

  let field_doc = match field.docstring {
    Some(ref d) => {
      let s = token::get_ident(d.node);
      s.get().into_string()
    },
    None => "no documentation".into_string()
  };
  let docstring = format!("*[{}]* Field `{}`: {}",
                          access_tag,
                          field.name.node,
                          field_doc);
  let doc_attr = utils::doc_attribute(cx, utils::intern_string(cx, docstring));

  quote_item!(cx,
    $doc_attr
    impl $reg_ty {
      $items
    }
  )
}

fn build_get_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>, reg: &node::Reg)
                    -> P<ast::Item>
{
  let reg_ty: P<ast::Ty> =
    cx.ty_ident(DUMMY_SP, utils::path_ident(cx, path));
  let getter_ty = utils::getter_name(cx, path);

  let docstring = format!("Fetch the value of the `{}` register",
                          reg.name.node);
  let doc_attr = utils::doc_attribute(cx, utils::intern_string(cx, docstring));

  let item = quote_item!(cx,
    impl $reg_ty {
      $doc_attr
      #[allow(dead_code)]
      pub fn get(&'static self) -> $getter_ty {
        $getter_ty::new(self)
      }
    }
    );
  item.unwrap()
}

fn build_field_set_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
                          reg: &node::Reg, field: &node::Field)
                          -> P<ast::Method>
{
  let fn_name =
    cx.ident_of((String::from_str("set_")+field.name.node).as_slice());
  let field_ty: P<ast::Ty> =
    cx.ty_path(utils::field_type_path(cx, path, reg, field), None);
  let setter_ty = utils::setter_name(cx, path);
  if field.count.node == 1 {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self, new_value: $field_ty) -> $setter_ty {
        let mut setter: $setter_ty = $setter_ty::new(self);
        setter.$fn_name(new_value);
        setter
      }
    )
  } else {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self, idx: uint, new_value: $field_ty) -> $setter_ty {
        let mut setter: $setter_ty = $setter_ty::new(self);
        setter.$fn_name(idx, new_value);
        setter
      }
    )
  }
}

fn build_field_get_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
                          reg: &node::Reg, field: &node::Field)
                          -> P<ast::Method>
{
  let fn_name = cx.ident_of(field.name.node.as_slice());
  let field_ty: P<ast::Ty> =
    cx.ty_path(utils::field_type_path(cx, path, reg, field), None);
  let getter_ty = utils::getter_name(cx, path);
  if field.count.node == 1 {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self) -> $field_ty {
        $getter_ty::new(self).$fn_name()
      }
    )
  } else {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self, idx: uint) -> $field_ty {
        $getter_ty::new(self).$fn_name(idx)
      }
    )
  }
}

fn build_field_clear_fn<'a>(cx: &'a ExtCtxt, path: &Vec<String>,
                            _reg: &node::Reg, field: &node::Field)
                            -> P<ast::Method>
{
  let fn_name =
    cx.ident_of((String::from_str("clear_")+field.name.node).as_slice());
  let setter_ty = utils::setter_name(cx, path);
  if field.count.node == 1 {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self) -> $setter_ty {
        let mut setter: $setter_ty = $setter_ty::new(self);
        setter.$fn_name();
        setter
      }
    )
  } else {
    quote_method!(cx,
      #[allow(dead_code, missing_doc)]
      pub fn $fn_name(&'static self, idx: uint) -> $setter_ty {
        let mut setter: $setter_ty = $setter_ty::new(self);
        setter.$fn_name(idx);
        setter
      }
    )
  }
}
<|endoftext|>


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

//! Check license of third-party deps by inspecting src/vendor

use std::fs::File;
use std::io::Read;
use std::path::Path;

static LICENSES: &'static [&'static str] = &[
    "MIT/Apache-2.0",
    "MIT / Apache-2.0",
    "Apache-2.0/MIT",
    "Apache-2.0 / MIT",
    "MIT OR Apache-2.0",
    "MIT",
    "Unlicense/MIT",
];

// These are exceptions to Rust's permissive licensing policy, and
// should be considered bugs. Exceptions are only allowed in Rust
// tooling. It is _crucial_ that no exception crates be dependencies
// of the Rust runtime (std / test).
static EXCEPTIONS: &'static [&'static str] = &[
    "mdbook", // MPL2, mdbook
    "openssl", // BSD+advertising clause, cargo, mdbook
    "pest", // MPL2, mdbook via handlebars
    "thread-id", // Apache-2.0, mdbook
    "toml-query", // MPL-2.0, mdbook
    "is-match", // MPL-2.0, mdbook
    "cssparser", // MPL-2.0, rustdoc
    "smallvec", // MPL-2.0, rustdoc
    "fuchsia-zircon-sys", // BSD-3-Clause, rustdoc, rustc, cargo
    "fuchsia-zircon", // BSD-3-Clause, rustdoc, rustc, cargo (jobserver & tempdir)
    "cssparser-macros", // MPL-2.0, rustdoc
    "selectors", // MPL-2.0, rustdoc
    "clippy_lints", // MPL-2.0 rls
];

pub fn check(path: &Path, bad: &mut bool) {
    let path = path.join("vendor");
    assert!(path.exists(), "vendor directory missing");
    let mut saw_dir = false;
    'next_path: for dir in t!(path.read_dir()) {
        saw_dir = true;
        let dir = t!(dir);

        // skip our exceptions
        for exception in EXCEPTIONS {
            if dir.path()
                .to_str()
                .unwrap()
                .contains(&format!("src/vendor/{}", exception)) {
                continue 'next_path;
            }
        }

        let toml = dir.path().join("Cargo.toml");
        if !check_license(&toml) {
            *bad = true;
        }
    }
    assert!(saw_dir, "no vendored source");
}

fn check_license(path: &Path) -> bool {
    if !path.exists() {
        panic!("{} does not exist", path.display());
    }
    let mut contents = String::new();
    t!(t!(File::open(path)).read_to_string(&mut contents));

    let mut found_license = false;
    for line in contents.lines() {
        if !line.starts_with("license") {
            continue;
        }
        let license = extract_license(line);
        if !LICENSES.contains(&&*license) {
            println!("invalid license {} in {}", license, path.display());
            return false;
        }
        found_license = true;
        break;
    }
    if !found_license {
        println!("no license in {}", path.display());
        return false;
    }

    true
}

fn extract_license(line: &str) -> String {
    let first_quote = line.find('"');
    let last_quote = line.rfind('"');
    if let (Some(f), Some(l)) = (first_quote, last_quote) {
        let license = &line[f + 1 .. l];
        license.into()
    } else {
        "bad-license-parse".into()
    }
}
<commit_msg>Run rustfmt on tidy/src/deps.rs<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Check license of third-party deps by inspecting src/vendor

use std::fs::File;
use std::io::Read;
use std::path::Path;

static LICENSES: &'static [&'static str] = &[
    "MIT/Apache-2.0",
    "MIT / Apache-2.0",
    "Apache-2.0/MIT",
    "Apache-2.0 / MIT",
    "MIT OR Apache-2.0",
    "MIT",
    "Unlicense/MIT",
];

// These are exceptions to Rust's permissive licensing policy, and
// should be considered bugs. Exceptions are only allowed in Rust
// tooling. It is _crucial_ that no exception crates be dependencies
// of the Rust runtime (std / test).
static EXCEPTIONS: &'static [&'static str] = &[
    "mdbook",             // MPL2, mdbook
    "openssl",            // BSD+advertising clause, cargo, mdbook
    "pest",               // MPL2, mdbook via handlebars
    "thread-id",          // Apache-2.0, mdbook
    "toml-query",         // MPL-2.0, mdbook
    "is-match",           // MPL-2.0, mdbook
    "cssparser",          // MPL-2.0, rustdoc
    "smallvec",           // MPL-2.0, rustdoc
    "fuchsia-zircon-sys", // BSD-3-Clause, rustdoc, rustc, cargo
    "fuchsia-zircon",     // BSD-3-Clause, rustdoc, rustc, cargo (jobserver & tempdir)
    "cssparser-macros",   // MPL-2.0, rustdoc
    "selectors",          // MPL-2.0, rustdoc
    "clippy_lints",       // MPL-2.0 rls
];

pub fn check(path: &Path, bad: &mut bool) {
    let path = path.join("vendor");
    assert!(path.exists(), "vendor directory missing");
    let mut saw_dir = false;
    'next_path: for dir in t!(path.read_dir()) {
        saw_dir = true;
        let dir = t!(dir);

        // skip our exceptions
        for exception in EXCEPTIONS {
            if dir.path()
                .to_str()
                .unwrap()
                .contains(&format!("src/vendor/{}", exception))
            {
                continue 'next_path;
            }
        }

        let toml = dir.path().join("Cargo.toml");
        if !check_license(&toml) {
            *bad = true;
        }
    }
    assert!(saw_dir, "no vendored source");
}

fn check_license(path: &Path) -> bool {
    if !path.exists() {
        panic!("{} does not exist", path.display());
    }
    let mut contents = String::new();
    t!(t!(File::open(path)).read_to_string(&mut contents));

    let mut found_license = false;
    for line in contents.lines() {
        if !line.starts_with("license") {
            continue;
        }
        let license = extract_license(line);
        if !LICENSES.contains(&&*license) {
            println!("invalid license {} in {}", license, path.display());
            return false;
        }
        found_license = true;
        break;
    }
    if !found_license {
        println!("no license in {}", path.display());
        return false;
    }

    true
}

fn extract_license(line: &str) -> String {
    let first_quote = line.find('"');
    let last_quote = line.rfind('"');
    if let (Some(f), Some(l)) = (first_quote, last_quote) {
        let license = &line[f + 1..l];
        license.into()
    } else {
        "bad-license-parse".into()
    }
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use std::{
    convert::From,
    fmt::{self, Display},
};

use hir::{Docs, Documentation, HasSource, HirDisplay};
use ra_ide_db::RootDatabase;
use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
use stdx::SepBy;

use crate::display::{generic_parameters, where_predicates};

#[derive(Debug)]
pub enum CallableKind {
    Function,
    StructConstructor,
    VariantConstructor,
    Macro,
}

/// Contains information about a function signature
#[derive(Debug)]
pub struct FunctionSignature {
    pub kind: CallableKind,
    /// Optional visibility
    pub visibility: Option<String>,
    /// Qualifiers like `async`, `unsafe`, ...
    pub qualifier: FunctionQualifier,
    /// Name of the function
    pub name: Option<String>,
    /// Documentation for the function
    pub doc: Option<Documentation>,
    /// Generic parameters
    pub generic_parameters: Vec<String>,
    /// Parameters of the function
    pub parameters: Vec<String>,
    /// Parameter names of the function
    pub parameter_names: Vec<String>,
    /// Parameter types of the function
    pub parameter_types: Vec<String>,
    /// Optional return type
    pub ret_type: Option<String>,
    /// Where predicates
    pub where_predicates: Vec<String>,
    /// Self param presence
    pub has_self_param: bool,
}

#[derive(Debug, Default)]
pub struct FunctionQualifier {
    // `async` and `const` are mutually exclusive. Do we need to enforcing it here?
    pub is_async: bool,
    pub is_const: bool,
    pub is_unsafe: bool,
    /// The string `extern ".."`
    pub extern_abi: Option<String>,
}

impl FunctionSignature {
    pub(crate) fn with_doc_opt(mut self, doc: Option<Documentation>) -> Self {
        self.doc = doc;
        self
    }

    pub(crate) fn from_hir(db: &RootDatabase, function: hir::Function) -> Self {
        let doc = function.docs(db);
        let ast_node = function.source(db).value;
        FunctionSignature::from(&ast_node).with_doc_opt(doc)
    }

    pub(crate) fn from_struct(db: &RootDatabase, st: hir::Struct) -> Option<Self> {
        let node: ast::StructDef = st.source(db).value;
        if let ast::StructKind::Record(_) = node.kind() {
            return None;
        };

        let mut params = vec![];
        let mut parameter_types = vec![];
        for field in st.fields(db).into_iter() {
            let ty = field.signature_ty(db);
            let raw_param = format!("{}", ty.display(db));

            if let Some(param_type) = raw_param.split(':').nth(1) {
                parameter_types.push(param_type[1..].to_string());
            } else {
                // useful when you have tuple struct
                parameter_types.push(raw_param.clone());
            }
            params.push(raw_param);
        }

        Some(
            FunctionSignature {
                kind: CallableKind::StructConstructor,
                visibility: node.visibility().map(|n| n.syntax().text().to_string()),
                // Do we need `const`?
                qualifier: Default::default(),
                name: node.name().map(|n| n.text().to_string()),
                ret_type: node.name().map(|n| n.text().to_string()),
                parameters: params,
                parameter_names: vec![],
                parameter_types,
                generic_parameters: generic_parameters(&node),
                where_predicates: where_predicates(&node),
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(st.docs(db)),
        )
    }

    pub(crate) fn from_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option<Self> {
        let node: ast::EnumVariant = variant.source(db).value;
        match node.kind() {
            ast::StructKind::Record(_) | ast::StructKind::Unit => return None,
            _ => (),
        };

        let parent_name = variant.parent_enum(db).name(db).to_string();

        let name = format!("{}::{}", parent_name, variant.name(db));

        let mut params = vec![];
        let mut parameter_types = vec![];
        for field in variant.fields(db).into_iter() {
            let ty = field.signature_ty(db);
            let raw_param = format!("{}", ty.display(db));
            if let Some(param_type) = raw_param.split(':').nth(1) {
                parameter_types.push(param_type[1..].to_string());
            } else {
                // The unwrap_or_else is useful when you have tuple
                parameter_types.push(raw_param);
            }
            let name = field.name(db);

            params.push(format!("{}: {}", name, ty.display(db)));
        }

        Some(
            FunctionSignature {
                kind: CallableKind::VariantConstructor,
                visibility: None,
                // Do we need `const`?
                qualifier: Default::default(),
                name: Some(name),
                ret_type: None,
                parameters: params,
                parameter_names: vec![],
                parameter_types,
                generic_parameters: vec![],
                where_predicates: vec![],
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(variant.docs(db)),
        )
    }

    pub(crate) fn from_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
        let node: ast::MacroCall = macro_def.source(db).value;

        let params = vec![];

        Some(
            FunctionSignature {
                kind: CallableKind::Macro,
                visibility: None,
                qualifier: Default::default(),
                name: node.name().map(|n| n.text().to_string()),
                ret_type: None,
                parameters: params,
                parameter_names: vec![],
                parameter_types: vec![],
                generic_parameters: vec![],
                where_predicates: vec![],
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(macro_def.docs(db)),
        )
    }
}

impl From<&'_ ast::FnDef> for FunctionSignature {
    fn from(node: &ast::FnDef) -> FunctionSignature {
        fn param_list(node: &ast::FnDef) -> (bool, Vec<String>, Vec<String>) {
            let mut res = vec![];
            let mut res_types = vec![];
            let mut has_self_param = false;
            if let Some(param_list) = node.param_list() {
                if let Some(self_param) = param_list.self_param() {
                    has_self_param = true;
                    let raw_param = self_param.syntax().text().to_string();

                    res_types.push(
                        raw_param.split(':').nth(1).unwrap_or_else(|| " Self")[1..].to_string(),
                    );
                    res.push(raw_param);
                }

                res.extend(param_list.params().map(|param| param.syntax().text().to_string()));
                res_types.extend(param_list.params().map(|param| {
                    param.syntax().text().to_string().split(':').nth(1).unwrap()[1..].to_string()
                }));
            }
            (has_self_param, res, res_types)
        }

        fn param_name_list(node: &ast::FnDef) -> Vec<String> {
            let mut res = vec![];
            if let Some(param_list) = node.param_list() {
                if let Some(self_param) = param_list.self_param() {
                    res.push(self_param.syntax().text().to_string())
                }

                res.extend(
                    param_list
                        .params()
                        .map(|param| {
                            Some(
                                param
                                    .pat()?
                                    .syntax()
                                    .descendants()
                                    .find_map(ast::Name::cast)?
                                    .text()
                                    .to_string(),
                            )
                        })
                        .map(|param| param.unwrap_or_default()),
                );
            }
            res
        }

        let (has_self_param, parameters, parameter_types) = param_list(node);

        FunctionSignature {
            kind: CallableKind::Function,
            visibility: node.visibility().map(|n| n.syntax().text().to_string()),
            qualifier: FunctionQualifier {
                is_async: node.async_token().is_some(),
                is_const: node.const_token().is_some(),
                is_unsafe: node.unsafe_token().is_some(),
                extern_abi: node.abi().map(|n| n.to_string()),
            },
            name: node.name().map(|n| n.text().to_string()),
            ret_type: node
                .ret_type()
                .and_then(|r| r.type_ref())
                .map(|n| n.syntax().text().to_string()),
            parameters,
            parameter_names: param_name_list(node),
            parameter_types,
            generic_parameters: generic_parameters(node),
            where_predicates: where_predicates(node),
            // docs are processed separately
            doc: None,
            has_self_param,
        }
    }
}

impl Display for FunctionSignature {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(t) = &self.visibility {
            write!(f, "{} ", t)?;
        }

        if self.qualifier.is_async {
            write!(f, "async ")?;
        }

        if self.qualifier.is_const {
            write!(f, "const ")?;
        }

        if self.qualifier.is_unsafe {
            write!(f, "unsafe ")?;
        }

        if let Some(extern_abi) = &self.qualifier.extern_abi {
            // Keyword `extern` is included in the string.
            write!(f, "{} ", extern_abi)?;
        }

        if let Some(name) = &self.name {
            match self.kind {
                CallableKind::Function => write!(f, "fn {}", name)?,
                CallableKind::StructConstructor => write!(f, "struct {}", name)?,
                CallableKind::VariantConstructor => write!(f, "{}", name)?,
                CallableKind::Macro => write!(f, "{}!", name)?,
            }
        }

        if !self.generic_parameters.is_empty() {
            write!(f, "{}", self.generic_parameters.iter().sep_by(", ").surround_with("<", ">"))?;
        }

        write!(f, "{}", self.parameters.iter().sep_by(", ").surround_with("(", ")"))?;

        if let Some(t) = &self.ret_type {
            write!(f, " -> {}", t)?;
        }

        if !self.where_predicates.is_empty() {
            write!(f, "\nwhere {}", self.where_predicates.iter().sep_by(",\n      "))?;
        }

        Ok(())
    }
}
<commit_msg>Fix panic in FunctionSignature<commit_after>//! FIXME: write short doc here

// FIXME: this modules relies on strings and AST way too much, and it should be
// rewritten (matklad 2020-05-07)
use std::{
    convert::From,
    fmt::{self, Display},
};

use hir::{Docs, Documentation, HasSource, HirDisplay};
use ra_ide_db::RootDatabase;
use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
use stdx::SepBy;

use crate::display::{generic_parameters, where_predicates};

#[derive(Debug)]
pub enum CallableKind {
    Function,
    StructConstructor,
    VariantConstructor,
    Macro,
}

/// Contains information about a function signature
#[derive(Debug)]
pub struct FunctionSignature {
    pub kind: CallableKind,
    /// Optional visibility
    pub visibility: Option<String>,
    /// Qualifiers like `async`, `unsafe`, ...
    pub qualifier: FunctionQualifier,
    /// Name of the function
    pub name: Option<String>,
    /// Documentation for the function
    pub doc: Option<Documentation>,
    /// Generic parameters
    pub generic_parameters: Vec<String>,
    /// Parameters of the function
    pub parameters: Vec<String>,
    /// Parameter names of the function
    pub parameter_names: Vec<String>,
    /// Parameter types of the function
    pub parameter_types: Vec<String>,
    /// Optional return type
    pub ret_type: Option<String>,
    /// Where predicates
    pub where_predicates: Vec<String>,
    /// Self param presence
    pub has_self_param: bool,
}

#[derive(Debug, Default)]
pub struct FunctionQualifier {
    // `async` and `const` are mutually exclusive. Do we need to enforcing it here?
    pub is_async: bool,
    pub is_const: bool,
    pub is_unsafe: bool,
    /// The string `extern ".."`
    pub extern_abi: Option<String>,
}

impl FunctionSignature {
    pub(crate) fn with_doc_opt(mut self, doc: Option<Documentation>) -> Self {
        self.doc = doc;
        self
    }

    pub(crate) fn from_hir(db: &RootDatabase, function: hir::Function) -> Self {
        let doc = function.docs(db);
        let ast_node = function.source(db).value;
        FunctionSignature::from(&ast_node).with_doc_opt(doc)
    }

    pub(crate) fn from_struct(db: &RootDatabase, st: hir::Struct) -> Option<Self> {
        let node: ast::StructDef = st.source(db).value;
        if let ast::StructKind::Record(_) = node.kind() {
            return None;
        };

        let mut params = vec![];
        let mut parameter_types = vec![];
        for field in st.fields(db).into_iter() {
            let ty = field.signature_ty(db);
            let raw_param = format!("{}", ty.display(db));

            if let Some(param_type) = raw_param.split(':').nth(1) {
                parameter_types.push(param_type[1..].to_string());
            } else {
                // useful when you have tuple struct
                parameter_types.push(raw_param.clone());
            }
            params.push(raw_param);
        }

        Some(
            FunctionSignature {
                kind: CallableKind::StructConstructor,
                visibility: node.visibility().map(|n| n.syntax().text().to_string()),
                // Do we need `const`?
                qualifier: Default::default(),
                name: node.name().map(|n| n.text().to_string()),
                ret_type: node.name().map(|n| n.text().to_string()),
                parameters: params,
                parameter_names: vec![],
                parameter_types,
                generic_parameters: generic_parameters(&node),
                where_predicates: where_predicates(&node),
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(st.docs(db)),
        )
    }

    pub(crate) fn from_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option<Self> {
        let node: ast::EnumVariant = variant.source(db).value;
        match node.kind() {
            ast::StructKind::Record(_) | ast::StructKind::Unit => return None,
            _ => (),
        };

        let parent_name = variant.parent_enum(db).name(db).to_string();

        let name = format!("{}::{}", parent_name, variant.name(db));

        let mut params = vec![];
        let mut parameter_types = vec![];
        for field in variant.fields(db).into_iter() {
            let ty = field.signature_ty(db);
            let raw_param = format!("{}", ty.display(db));
            if let Some(param_type) = raw_param.split(':').nth(1) {
                parameter_types.push(param_type[1..].to_string());
            } else {
                // The unwrap_or_else is useful when you have tuple
                parameter_types.push(raw_param);
            }
            let name = field.name(db);

            params.push(format!("{}: {}", name, ty.display(db)));
        }

        Some(
            FunctionSignature {
                kind: CallableKind::VariantConstructor,
                visibility: None,
                // Do we need `const`?
                qualifier: Default::default(),
                name: Some(name),
                ret_type: None,
                parameters: params,
                parameter_names: vec![],
                parameter_types,
                generic_parameters: vec![],
                where_predicates: vec![],
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(variant.docs(db)),
        )
    }

    pub(crate) fn from_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
        let node: ast::MacroCall = macro_def.source(db).value;

        let params = vec![];

        Some(
            FunctionSignature {
                kind: CallableKind::Macro,
                visibility: None,
                qualifier: Default::default(),
                name: node.name().map(|n| n.text().to_string()),
                ret_type: None,
                parameters: params,
                parameter_names: vec![],
                parameter_types: vec![],
                generic_parameters: vec![],
                where_predicates: vec![],
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(macro_def.docs(db)),
        )
    }
}

impl From<&'_ ast::FnDef> for FunctionSignature {
    fn from(node: &ast::FnDef) -> FunctionSignature {
        fn param_list(node: &ast::FnDef) -> (bool, Vec<String>, Vec<String>) {
            let mut res = vec![];
            let mut res_types = vec![];
            let mut has_self_param = false;
            if let Some(param_list) = node.param_list() {
                if let Some(self_param) = param_list.self_param() {
                    has_self_param = true;
                    let raw_param = self_param.syntax().text().to_string();

                    res_types.push(
                        raw_param.split(':').nth(1).unwrap_or_else(|| " Self")[1..].to_string(),
                    );
                    res.push(raw_param);
                }

                res.extend(param_list.params().map(|param| param.syntax().text().to_string()));
                res_types.extend(param_list.params().map(|param| {
                    let param_text = param.syntax().text().to_string();
                    match param_text.split(':').nth(1) {
                        Some(it) => it[1..].to_string(),
                        None => param_text,
                    }
                }));
            }
            (has_self_param, res, res_types)
        }

        fn param_name_list(node: &ast::FnDef) -> Vec<String> {
            let mut res = vec![];
            if let Some(param_list) = node.param_list() {
                if let Some(self_param) = param_list.self_param() {
                    res.push(self_param.syntax().text().to_string())
                }

                res.extend(
                    param_list
                        .params()
                        .map(|param| {
                            Some(
                                param
                                    .pat()?
                                    .syntax()
                                    .descendants()
                                    .find_map(ast::Name::cast)?
                                    .text()
                                    .to_string(),
                            )
                        })
                        .map(|param| param.unwrap_or_default()),
                );
            }
            res
        }

        let (has_self_param, parameters, parameter_types) = param_list(node);

        FunctionSignature {
            kind: CallableKind::Function,
            visibility: node.visibility().map(|n| n.syntax().text().to_string()),
            qualifier: FunctionQualifier {
                is_async: node.async_token().is_some(),
                is_const: node.const_token().is_some(),
                is_unsafe: node.unsafe_token().is_some(),
                extern_abi: node.abi().map(|n| n.to_string()),
            },
            name: node.name().map(|n| n.text().to_string()),
            ret_type: node
                .ret_type()
                .and_then(|r| r.type_ref())
                .map(|n| n.syntax().text().to_string()),
            parameters,
            parameter_names: param_name_list(node),
            parameter_types,
            generic_parameters: generic_parameters(node),
            where_predicates: where_predicates(node),
            // docs are processed separately
            doc: None,
            has_self_param,
        }
    }
}

impl Display for FunctionSignature {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(t) = &self.visibility {
            write!(f, "{} ", t)?;
        }

        if self.qualifier.is_async {
            write!(f, "async ")?;
        }

        if self.qualifier.is_const {
            write!(f, "const ")?;
        }

        if self.qualifier.is_unsafe {
            write!(f, "unsafe ")?;
        }

        if let Some(extern_abi) = &self.qualifier.extern_abi {
            // Keyword `extern` is included in the string.
            write!(f, "{} ", extern_abi)?;
        }

        if let Some(name) = &self.name {
            match self.kind {
                CallableKind::Function => write!(f, "fn {}", name)?,
                CallableKind::StructConstructor => write!(f, "struct {}", name)?,
                CallableKind::VariantConstructor => write!(f, "{}", name)?,
                CallableKind::Macro => write!(f, "{}!", name)?,
            }
        }

        if !self.generic_parameters.is_empty() {
            write!(f, "{}", self.generic_parameters.iter().sep_by(", ").surround_with("<", ">"))?;
        }

        write!(f, "{}", self.parameters.iter().sep_by(", ").surround_with("(", ")"))?;

        if let Some(t) = &self.ret_type {
            write!(f, " -> {}", t)?;
        }

        if !self.where_predicates.is_empty() {
            write!(f, "\nwhere {}", self.where_predicates.iter().sep_by(",\n      "))?;
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>#[cfg(target_arch = "x86_64")]
pub use self::x64::*;

#[cfg(target_arch = "x86_64")]
pub mod x64;

#[cfg(target_arch = "aarch64")]
use self::arm64::*;

#[cfg(target_arch = "aarch64")]
pub mod arm64;

use std::convert::TryInto;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Register(u8);

impl Register {
    pub fn new(value: u8) -> Register {
        Register(value)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct FloatRegister(u8);

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Label(usize);

pub struct Assembler {
    code: Vec<u8>,
    labels: Vec<Option<u32>>,
    unresolved_jumps: Vec<(u32, Label, JumpKind)>,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler {
            code: Vec::new(),
            labels: Vec::new(),
            unresolved_jumps: Vec::new(),
        }
    }

    pub fn pc(&self) -> usize {
        self.code.len()
    }

    pub fn code_mut(&mut self) -> &mut Vec<u8> {
        &mut self.code
    }

    pub fn code(&self) -> &[u8] {
        &self.code
    }

    pub fn create_label(&mut self) -> Label {
        self.labels.push(None);

        Label(self.labels.len() - 1)
    }

    pub fn create_and_bind_label(&mut self) -> Label {
        self.labels.push(Some(self.pc().try_into().unwrap()));
        Label(self.labels.len() - 1)
    }

    pub fn bind_label(&mut self, lbl: Label) {
        let Label(idx) = lbl;
        debug_assert!(self.labels[idx].is_none());
        self.labels[idx] = Some(self.pc().try_into().unwrap());
    }

    pub fn bind_label_to(&mut self, lbl: Label, offset: u32) {
        let Label(idx) = lbl;
        debug_assert!(self.labels[idx].is_none());
        self.labels[idx] = Some(offset);
    }

    fn offset(&self, lbl: Label) -> Option<u32> {
        let Label(idx) = lbl;
        self.labels[idx]
    }

    pub fn finalize(mut self) -> Vec<u8> {
        self.resolve_jumps();
        self.code
    }

    fn emit_u8(&mut self, value: u8) {
        self.code.push(value);
    }

    fn emit_u32(&mut self, value: u32) {
        self.emit_u8(value as u8);
        self.emit_u8((value >> 8) as u8);
        self.emit_u8((value >> 16) as u8);
        self.emit_u8((value >> 24) as u8);
    }

    fn emit_u64(&mut self, value: u64) {
        self.emit_u32(value as u32);
        self.emit_u32((value >> 32) as u32);
    }

    fn patch_u8(&mut self, idx: u32, value: u8) {
        self.code[idx as usize] = value;
    }

    fn patch_u32(&mut self, idx: u32, value: u32) {
        self.code[idx as usize] = (value & 0xFF) as u8;
        self.code[idx as usize + 1] = ((value >> 8) & 0xFF) as u8;
        self.code[idx as usize + 2] = ((value >> 16) & 0xFF) as u8;
        self.code[idx as usize + 3] = ((value >> 24) & 0xFF) as u8;
    }
}
<commit_msg>asm: use assert instead of debug_assert<commit_after>#[cfg(target_arch = "x86_64")]
pub use self::x64::*;

#[cfg(target_arch = "x86_64")]
pub mod x64;

#[cfg(target_arch = "aarch64")]
use self::arm64::*;

#[cfg(target_arch = "aarch64")]
pub mod arm64;

use std::convert::TryInto;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Register(u8);

impl Register {
    pub fn new(value: u8) -> Register {
        Register(value)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct FloatRegister(u8);

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Label(usize);

pub struct Assembler {
    code: Vec<u8>,
    labels: Vec<Option<u32>>,
    unresolved_jumps: Vec<(u32, Label, JumpKind)>,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler {
            code: Vec::new(),
            labels: Vec::new(),
            unresolved_jumps: Vec::new(),
        }
    }

    pub fn pc(&self) -> usize {
        self.code.len()
    }

    pub fn code_mut(&mut self) -> &mut Vec<u8> {
        &mut self.code
    }

    pub fn code(&self) -> &[u8] {
        &self.code
    }

    pub fn create_label(&mut self) -> Label {
        self.labels.push(None);

        Label(self.labels.len() - 1)
    }

    pub fn create_and_bind_label(&mut self) -> Label {
        self.labels.push(Some(self.pc().try_into().unwrap()));
        Label(self.labels.len() - 1)
    }

    pub fn bind_label(&mut self, lbl: Label) {
        let Label(idx) = lbl;
        assert!(self.labels[idx].is_none());
        self.labels[idx] = Some(self.pc().try_into().unwrap());
    }

    pub fn bind_label_to(&mut self, lbl: Label, offset: u32) {
        let Label(idx) = lbl;
        assert!(self.labels[idx].is_none());
        self.labels[idx] = Some(offset);
    }

    fn offset(&self, lbl: Label) -> Option<u32> {
        let Label(idx) = lbl;
        self.labels[idx]
    }

    pub fn finalize(mut self) -> Vec<u8> {
        self.resolve_jumps();
        self.code
    }

    fn emit_u8(&mut self, value: u8) {
        self.code.push(value);
    }

    fn emit_u32(&mut self, value: u32) {
        self.emit_u8(value as u8);
        self.emit_u8((value >> 8) as u8);
        self.emit_u8((value >> 16) as u8);
        self.emit_u8((value >> 24) as u8);
    }

    fn emit_u64(&mut self, value: u64) {
        self.emit_u32(value as u32);
        self.emit_u32((value >> 32) as u32);
    }

    fn patch_u8(&mut self, idx: u32, value: u8) {
        self.code[idx as usize] = value;
    }

    fn patch_u32(&mut self, idx: u32, value: u32) {
        self.code[idx as usize] = (value & 0xFF) as u8;
        self.code[idx as usize + 1] = ((value >> 8) & 0xFF) as u8;
        self.code[idx as usize + 2] = ((value >> 16) & 0xFF) as u8;
        self.code[idx as usize + 3] = ((value >> 24) & 0xFF) as u8;
    }
}
<|endoftext|>


<commit_before>//! AES New Instructions (AES-NI)
//!
//! The intrinsics here correspond to those in the `wmmintrin.h` C header.
//!
//! The reference is [Intel 64 and IA-32 Architectures Software Developer's
//! Manual Volume 2: Instruction Set Reference, A-Z][intel64_ref].
//!
//! [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf

use crate::core_arch::x86::__m128i;

#[cfg(test)]
use stdarch_test::assert_instr;

#[allow(improper_ctypes)]
extern "C" {
    #[link_name = "llvm.x86.aesni.aesdec"]
    fn aesdec(a: __m128i, round_key: __m128i) -> __m128i;
    #[link_name = "llvm.x86.aesni.aesdeclast"]
    fn aesdeclast(a: __m128i, round_key: __m128i) -> __m128i;
    #[link_name = "llvm.x86.aesni.aesenc"]
    fn aesenc(a: __m128i, round_key: __m128i) -> __m128i;
    #[link_name = "llvm.x86.aesni.aesenclast"]
    fn aesenclast(a: __m128i, round_key: __m128i) -> __m128i;
    #[link_name = "llvm.x86.aesni.aesimc"]
    fn aesimc(a: __m128i) -> __m128i;
    #[link_name = "llvm.x86.aesni.aeskeygenassist"]
    fn aeskeygenassist(a: __m128i, imm8: u8) -> __m128i;
}

/// Performs one round of an AES decryption flow on data (state) in `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesdec_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aesdec))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aesdec_si128(a: __m128i, round_key: __m128i) -> __m128i {
    aesdec(a, round_key)
}

/// Performs the last round of an AES decryption flow on data (state) in `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesdeclast_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aesdeclast))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aesdeclast_si128(a: __m128i, round_key: __m128i) -> __m128i {
    aesdeclast(a, round_key)
}

/// Performs one round of an AES encryption flow on data (state) in `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenc_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aesenc))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aesenc_si128(a: __m128i, round_key: __m128i) -> __m128i {
    aesenc(a, round_key)
}

/// Performs the last round of an AES encryption flow on data (state) in `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenclast_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aesenclast))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aesenclast_si128(a: __m128i, round_key: __m128i) -> __m128i {
    aesenclast(a, round_key)
}

/// Performs the `InvMixColumns` transformation on `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesimc_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aesimc))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aesimc_si128(a: __m128i) -> __m128i {
    aesimc(a)
}

/// Assist in expanding the AES cipher key.
///
/// Assist in expanding the AES cipher key by computing steps towards
/// generating a round key for encryption cipher using data from `a` and an
/// 8-bit round constant `imm8`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aeskeygenassist_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aeskeygenassist, imm8 = 0))]
#[rustc_args_required_const(1)]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aeskeygenassist_si128(a: __m128i, imm8: i32) -> __m128i {
    macro_rules! call {
        ($imm8:expr) => {
            aeskeygenassist(a, $imm8)
        };
    }
    constify_imm8!(imm8, call)
}

#[cfg(test)]
mod tests {
    // The constants in the tests below are just bit patterns. They should not
    // be interpreted as integers; signedness does not make sense for them, but
    // __m128i happens to be defined in terms of signed integers.
    #![allow(overflowing_literals)]

    use stdarch_test::simd_test;

    use crate::core_arch::x86::*;

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aesdec_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc664949.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
        let e = _mm_set_epi64x(0x044e4f5176fec48f, 0xb57ecfa381da39ee);
        let r = _mm_aesdec_si128(a, k);
        assert_eq_m128i(r, e);
    }

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aesdeclast_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714178.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
        let e = _mm_set_epi64x(0x36cad57d9072bf9e, 0xf210dd981fa4a493);
        let r = _mm_aesdeclast_si128(a, k);
        assert_eq_m128i(r, e);
    }

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aesenc_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc664810.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
        let e = _mm_set_epi64x(0x16ab0e57dfc442ed, 0x28e4ee1884504333);
        let r = _mm_aesenc_si128(a, k);
        assert_eq_m128i(r, e);
    }

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aesenclast_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714136.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
        let e = _mm_set_epi64x(0xb6dd7df25d7ab320, 0x4b04f98cf4c860f8);
        let r = _mm_aesenclast_si128(a, k);
        assert_eq_m128i(r, e);
    }

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aesimc_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714195.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let e = _mm_set_epi64x(0xc66c82284ee40aa0, 0x6633441122770055);
        let r = _mm_aesimc_si128(a);
        assert_eq_m128i(r, e);
    }

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aeskeygenassist_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714138.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let e = _mm_set_epi64x(0x857c266b7c266e85, 0xeac4eea9c4eeacea);
        let r = _mm_aeskeygenassist_si128(a, 5);
        assert_eq_m128i(r, e);
    }
}
<commit_msg>convert `_mm_aeskeygenassist_si128` to const generics<commit_after>//! AES New Instructions (AES-NI)
//!
//! The intrinsics here correspond to those in the `wmmintrin.h` C header.
//!
//! The reference is [Intel 64 and IA-32 Architectures Software Developer's
//! Manual Volume 2: Instruction Set Reference, A-Z][intel64_ref].
//!
//! [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf

use crate::core_arch::x86::__m128i;

#[cfg(test)]
use stdarch_test::assert_instr;

#[allow(improper_ctypes)]
extern "C" {
    #[link_name = "llvm.x86.aesni.aesdec"]
    fn aesdec(a: __m128i, round_key: __m128i) -> __m128i;
    #[link_name = "llvm.x86.aesni.aesdeclast"]
    fn aesdeclast(a: __m128i, round_key: __m128i) -> __m128i;
    #[link_name = "llvm.x86.aesni.aesenc"]
    fn aesenc(a: __m128i, round_key: __m128i) -> __m128i;
    #[link_name = "llvm.x86.aesni.aesenclast"]
    fn aesenclast(a: __m128i, round_key: __m128i) -> __m128i;
    #[link_name = "llvm.x86.aesni.aesimc"]
    fn aesimc(a: __m128i) -> __m128i;
    #[link_name = "llvm.x86.aesni.aeskeygenassist"]
    fn aeskeygenassist(a: __m128i, imm8: u8) -> __m128i;
}

/// Performs one round of an AES decryption flow on data (state) in `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesdec_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aesdec))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aesdec_si128(a: __m128i, round_key: __m128i) -> __m128i {
    aesdec(a, round_key)
}

/// Performs the last round of an AES decryption flow on data (state) in `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesdeclast_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aesdeclast))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aesdeclast_si128(a: __m128i, round_key: __m128i) -> __m128i {
    aesdeclast(a, round_key)
}

/// Performs one round of an AES encryption flow on data (state) in `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenc_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aesenc))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aesenc_si128(a: __m128i, round_key: __m128i) -> __m128i {
    aesenc(a, round_key)
}

/// Performs the last round of an AES encryption flow on data (state) in `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenclast_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aesenclast))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aesenclast_si128(a: __m128i, round_key: __m128i) -> __m128i {
    aesenclast(a, round_key)
}

/// Performs the `InvMixColumns` transformation on `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesimc_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aesimc))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aesimc_si128(a: __m128i) -> __m128i {
    aesimc(a)
}

/// Assist in expanding the AES cipher key.
///
/// Assist in expanding the AES cipher key by computing steps towards
/// generating a round key for encryption cipher using data from `a` and an
/// 8-bit round constant `IMM8`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aeskeygenassist_si128)
#[inline]
#[target_feature(enable = "aes")]
#[cfg_attr(test, assert_instr(aeskeygenassist, IMM8 = 0))]
#[rustc_legacy_const_generics(1)]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_aeskeygenassist_si128<const IMM8: i32>(a: __m128i) -> __m128i {
    static_assert_imm8!(IMM8);
    aeskeygenassist(a, IMM8 as u8)
}

#[cfg(test)]
mod tests {
    // The constants in the tests below are just bit patterns. They should not
    // be interpreted as integers; signedness does not make sense for them, but
    // __m128i happens to be defined in terms of signed integers.
    #![allow(overflowing_literals)]

    use stdarch_test::simd_test;

    use crate::core_arch::x86::*;

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aesdec_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc664949.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
        let e = _mm_set_epi64x(0x044e4f5176fec48f, 0xb57ecfa381da39ee);
        let r = _mm_aesdec_si128(a, k);
        assert_eq_m128i(r, e);
    }

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aesdeclast_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714178.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
        let e = _mm_set_epi64x(0x36cad57d9072bf9e, 0xf210dd981fa4a493);
        let r = _mm_aesdeclast_si128(a, k);
        assert_eq_m128i(r, e);
    }

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aesenc_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc664810.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
        let e = _mm_set_epi64x(0x16ab0e57dfc442ed, 0x28e4ee1884504333);
        let r = _mm_aesenc_si128(a, k);
        assert_eq_m128i(r, e);
    }

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aesenclast_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714136.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
        let e = _mm_set_epi64x(0xb6dd7df25d7ab320, 0x4b04f98cf4c860f8);
        let r = _mm_aesenclast_si128(a, k);
        assert_eq_m128i(r, e);
    }

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aesimc_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714195.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let e = _mm_set_epi64x(0xc66c82284ee40aa0, 0x6633441122770055);
        let r = _mm_aesimc_si128(a);
        assert_eq_m128i(r, e);
    }

    #[simd_test(enable = "aes")]
    unsafe fn test_mm_aeskeygenassist_si128() {
        // Constants taken from https://msdn.microsoft.com/en-us/library/cc714138.aspx.
        let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
        let e = _mm_set_epi64x(0x857c266b7c266e85, 0xeac4eea9c4eeacea);
        let r = _mm_aeskeygenassist_si128::<5>(a);
        assert_eq_m128i(r, e);
    }
}
<|endoftext|>