<commit_before>#![feature(plugin, custom_derive, custom_attribute)]
#![plugin(rocket_codegen)]
extern crate rocket;
extern crate serde;
extern crate itertools;

#[macro_use]
extern crate serde_derive;
extern crate rocket_contrib;

#[cfg(test)]
extern crate serde_json;

use rocket_contrib::Json;

mod automata;
use automata::{Nfa, Dfa, Unsanitary};

#[get("/")]
fn index() -> &'static str {
    //Render home page
    "Hello, World!"
}

#[post("/submit", format="application/json", data="<data>")]
fn submit_nfa(data: Json<Nfa<Unsanitary>>) -> Json<Dfa> {
    Json(data.into_inner().check().unwrap().make_deterministic())
}

fn main() {
    rocket::ignite().mount("/", routes![index, submit_nfa]).launch();
}
<commit_msg>adding test for main<commit_after>#![feature(plugin, custom_derive, custom_attribute)]
#![plugin(rocket_codegen)]
extern crate rocket;
extern crate serde;
extern crate itertools;

#[macro_use]
extern crate serde_derive;
extern crate rocket_contrib;

#[cfg(test)]
extern crate serde_json;

use rocket_contrib::Json;

use std::io;
use std::path::{Path, PathBuf};

use rocket::response::NamedFile;

mod automata;
use automata::{Nfa, Dfa, Unsanitary};

#[get("/")]
fn index() -> &'static str {
    //Render home page
    "Hello, World!"
}

#[post("/submit", format="application/json", data="<data>")]
fn submit_nfa(data: Json<Nfa<Unsanitary>>) -> Json<Dfa> {
    Json(data.into_inner().check().unwrap().make_deterministic())
}

fn main() {
    rocket::ignite().mount("/", routes![index, submit_nfa]).launch();
}

#[cfg(test)]
mod test {
    use super::rocket;
    use rocket::local::Client;
    use rocket::http::Status;

    #[test]
    fn test_one() {
        let rocket = rocket::ignite();
        let client = Client::new(rocket).expect("valid rocket instance");
        let mut response = client.get("/").dispatch();

        assert_eq!(response.status(), Status::Ok);
        //assert_eq!(response.content_type(), Some(ContentType::Plain));
        //assert!(response.headers().get_one("X-Special").is_some());
        //assert_eq!(response.body_string(), Some("Expected Body.".into()));
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Exonum Team
//
// 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 std::{borrow::Cow, fmt::Debug, io::Write};

use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use criterion::{black_box, Bencher, Criterion};
use rand::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

use exonum_crypto::{self, CryptoHash, Hash};
use exonum_merkledb::{
    proof_map_index::{BranchNode, ProofPath},
    StorageKey, StorageValue,
};

const CHUNK_SIZE: usize = 64;
const SEED: [u8; 16] = [100; 16];

#[derive(Debug, Clone, Copy, PartialEq)]
struct SimpleData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for SimpleData {
    fn into_bytes(self) -> Vec<u8> {
        let mut buffer = vec![0; 40];
        LittleEndian::write_u16(&mut buffer[0..2], self.id);
        LittleEndian::write_i16(&mut buffer[2..4], self.class);
        LittleEndian::write_i32(&mut buffer[4..8], self.value);
        buffer[8..].copy_from_slice(self.hash.as_ref());
        buffer
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let id = LittleEndian::read_u16(&bytes[0..2]);
        let class = LittleEndian::read_i16(&bytes[2..4]);
        let value = LittleEndian::read_i32(&bytes[4..8]);
        let hash = Hash::from_slice(&bytes[8..40]).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for SimpleData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
struct CursorData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for CursorData {
    fn into_bytes(self) -> Vec<u8> {
        let mut buf = vec![0; 40];
        let mut cursor = buf.as_mut_slice();
        cursor.write_u16::<LittleEndian>(self.id).unwrap();
        cursor.write_i16::<LittleEndian>(self.class).unwrap();
        cursor.write_i32::<LittleEndian>(self.value).unwrap();
        cursor.write_all(self.hash.as_ref()).unwrap();
        buf
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let mut bytes = bytes.as_ref();
        let id = bytes.read_u16::<LittleEndian>().unwrap();
        let class = bytes.read_i16::<LittleEndian>().unwrap();
        let value = bytes.read_i32::<LittleEndian>().unwrap();
        let hash = Hash::from_slice(bytes).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for CursorData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

fn gen_bytes_data() -> Vec<u8> {
    let mut rng = XorShiftRng::from_seed(SEED);
    let mut v = vec![0; CHUNK_SIZE];
    rng.fill_bytes(&mut v);
    v
}

fn gen_sample_data() -> SimpleData {
    SimpleData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_cursor_data() -> CursorData {
    CursorData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_branch_node_data() -> BranchNode {
    BranchNode::empty()
}

fn bench_binary_value<F, V>(c: &mut Criterion, name: &str, f: F)
where
    F: Fn() -> V + 'static + Clone + Copy,
    V: StorageValue + Clone + PartialEq + Debug,
{
    // Checks that binary value is correct.
    let val = f();
    let bytes = val.clone().into_bytes();
    let val2 = V::from_bytes(bytes.into());
    assert_eq!(val, val2);
    // Runs benchmarks.
    c.bench_function(
        &format!("encoding/{}/into_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.into_bytes()));
        },
    );
    c.bench_function(
        &format!("encoding/{}/from_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(
                || {
                    let val = f();
                    val.into_bytes()
                },
                |bytes| black_box(V::from_bytes(bytes.into())),
            );
        },
    );
    c.bench_function(
        &format!("encoding/{}/hash", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.hash()));
        },
    );
}

fn bench_storage_key_concat(b: &mut Bencher) {
    b.iter_with_setup(
        || ("prefixed.key", Hash::zero(), ProofPath::new(&Hash::zero())),
        |(prefix, key, path)| {
            let mut v = vec![0; prefix.size() + key.size() + path.size()];
            let mut pos = 0;
            prefix.write(&mut v[pos..pos + prefix.size()]);
            pos += prefix.size();
            key.write(&mut v[pos..pos + key.size()]);
            pos += key.size();
            path.write(&mut v[pos..pos + path.size()]);
            black_box(v);
        },
    );
}

pub fn bench_encoding(c: &mut Criterion) {
    exonum_crypto::init();
    bench_binary_value(c, "bytes", gen_bytes_data);
    bench_binary_value(c, "simple", gen_sample_data);
    bench_binary_value(c, "cursor", gen_cursor_data);
    bench_binary_value(c, "branch_node", gen_branch_node_data);
    c.bench_function("encoding/storage_key/concat", bench_storage_key_concat);
}
<commit_msg>Improve io::Write perfomance<commit_after>// Copyright 2018 The Exonum Team
//
// 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 std::{borrow::Cow, fmt::Debug, io::Write};

use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use criterion::{black_box, Bencher, Criterion};
use rand::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

use exonum_crypto::{self, CryptoHash, Hash};
use exonum_merkledb::{
    proof_map_index::{BranchNode, ProofPath},
    StorageKey, StorageValue,
};

const CHUNK_SIZE: usize = 64;
const SEED: [u8; 16] = [100; 16];

#[derive(Debug, Clone, Copy, PartialEq)]
struct SimpleData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for SimpleData {
    fn into_bytes(self) -> Vec<u8> {
        let mut buffer = vec![0; 40];
        LittleEndian::write_u16(&mut buffer[0..2], self.id);
        LittleEndian::write_i16(&mut buffer[2..4], self.class);
        LittleEndian::write_i32(&mut buffer[4..8], self.value);
        buffer[8..].copy_from_slice(self.hash.as_ref());
        buffer
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let id = LittleEndian::read_u16(&bytes[0..2]);
        let class = LittleEndian::read_i16(&bytes[2..4]);
        let value = LittleEndian::read_i32(&bytes[4..8]);
        let hash = Hash::from_slice(&bytes[8..40]).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for SimpleData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
struct CursorData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl BinaryForm for CursorData {
    fn to_bytes(&self) -> Vec<u8> {
        let mut buf = vec![0; 40];
        let mut cursor = buf.as_mut_slice();
        cursor.write_u16::<LittleEndian>(self.id).unwrap();
        cursor.write_i16::<LittleEndian>(self.class).unwrap();
        cursor.write_i32::<LittleEndian>(self.value).unwrap();
        cursor.write_all(self.hash.as_ref()).unwrap();
        buf
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let mut bytes = bytes.as_ref();
        let id = bytes.read_u16::<LittleEndian>().unwrap();
        let class = bytes.read_i16::<LittleEndian>().unwrap();
        let value = bytes.read_i32::<LittleEndian>().unwrap();
        let hash = Hash::from_slice(bytes).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for CursorData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

fn gen_bytes_data() -> Vec<u8> {
    let mut rng = XorShiftRng::from_seed(SEED);
    let mut v = vec![0; CHUNK_SIZE];
    rng.fill_bytes(&mut v);
    v
}

fn gen_sample_data() -> SimpleData {
    SimpleData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_cursor_data() -> CursorData {
    CursorData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_branch_node_data() -> BranchNode {
    BranchNode::empty()
}

fn bench_binary_value<F, V>(c: &mut Criterion, name: &str, f: F)
where
    F: Fn() -> V + 'static + Clone + Copy,
    V: StorageValue + Clone + PartialEq + Debug,
{
    // Checks that binary value is correct.
    let val = f();
    let bytes = val.clone().into_bytes();
    let val2 = V::from_bytes(bytes.into());
    assert_eq!(val, val2);
    // Runs benchmarks.
    c.bench_function(
        &format!("encoding/{}/into_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.into_bytes()));
        },
    );
    c.bench_function(
        &format!("encoding/{}/from_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(
                || {
                    let val = f();
                    val.into_bytes()
                },
                |bytes| black_box(V::from_bytes(bytes.into())),
            );
        },
    );
    c.bench_function(
        &format!("encoding/{}/hash", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.hash()));
        },
    );
}

fn bench_storage_key_concat(b: &mut Bencher) {
    b.iter_with_setup(
        || ("prefixed.key", Hash::zero(), ProofPath::new(&Hash::zero())),
        |(prefix, key, path)| {
            let mut v = vec![0; prefix.size() + key.size() + path.size()];
            let mut pos = 0;
            prefix.write(&mut v[pos..pos + prefix.size()]);
            pos += prefix.size();
            key.write(&mut v[pos..pos + key.size()]);
            pos += key.size();
            path.write(&mut v[pos..pos + path.size()]);
            black_box(v);
        },
    );
}

pub fn bench_encoding(c: &mut Criterion) {
    exonum_crypto::init();
    bench_binary_value(c, "bytes", gen_bytes_data);
    bench_binary_value(c, "simple", gen_sample_data);
    bench_binary_value(c, "cursor", gen_cursor_data);
    bench_binary_value(c, "branch_node", gen_branch_node_data);
    c.bench_function("encoding/storage_key/concat", bench_storage_key_concat);
}
<|endoftext|>


<commit_before><commit_msg>context: Remove an unused attribute<commit_after><|endoftext|>


<commit_before>//!
//! This module defines a manager for holding multiple instances of mock servers.
//!

use crate::mock_server::MockServer;

use pact_matching::models::{Pact};
use std::collections::BTreeMap;

/// Struct to represent many mock servers running in a background thread
pub struct ServerManager {
    runtime: tokio::runtime::Runtime,
    mock_servers: BTreeMap<String, Box<MockServer>>
}

impl ServerManager {
    /// Construct a new ServerManager for scheduling several instances of mock servers
    /// on one tokio runtime.
    pub fn new() -> ServerManager {
        ServerManager {
            runtime: tokio::runtime::Builder::new()
                .threaded_scheduler()
                .num_threads(1)
                .enable_all()
                .build()
                .unwrap(),
            mock_servers: BTreeMap::new()
        }
    }

    /// Start a new server on the runtime
    pub fn start_mock_server_with_addr(
        &mut self,
        id: String,
        pact: Pact,
        addr: std::net::SocketAddr
    ) -> Result<std::net::SocketAddr, String> {
        let (mock_server, future) = self.runtime.block_on(
            MockServer::new(id.clone(), pact, addr)
        )?;

        self.runtime.spawn(future);
        let addr = mock_server.addr;

        self.mock_servers.insert(id, Box::new(mock_server));
        Ok(addr)
    }

    /// Start a new server on the runtime
    pub fn start_mock_server(&mut self, id: String, pact: Pact, port: u16) -> Result<u16, String> {
        self.start_mock_server_with_addr(id, pact, ([0, 0, 0, 0], port as u16).into()).map(|addr| addr.port())
    }

    /// Shut down a server by its id
    pub fn shutdown_mock_server_by_id(&mut self, id: String) -> bool {
        match self.mock_servers.remove(&id) {
            Some(mut mock_server) => {
                match mock_server.shutdown() {
                    Ok(()) => true,
                    Err(_) => false
                }
            },
            None => false
        }
    }

    /// Shut down a server by its local port number
    pub fn shutdown_mock_server_by_port(&mut self, port: u16) -> bool {
        log::debug!("Shutting down mock server with port {}", port);
        let result = self.mock_servers.iter()
            .find(|ms| ms.1.addr.port() == port)
            .map(|ms| ms.1.id.clone());

        if let Some(id) = result {
            if let Some(mut mock_server) = self.mock_servers.remove(&id) {
                return match mock_server.shutdown() {
                    Ok(()) => true,
                    Err(_) => false
                }
            }
        }

        false
    }

    /// Find mock server by id, and map it using supplied function if found
    pub fn find_mock_server_by_id<R>(&self, id: &String, f: &dyn Fn(&MockServer) -> R) -> Option<R> {
        match self.mock_servers.get(id) {
            Some(mock_server) => Some(f(mock_server)),
            None => None
        }
    }

    /// Find a mock server by port number and apply a mutating operation on it if successful
    pub fn find_mock_server_by_port_mut<R>(&mut self, mock_server_port: u16, f: &dyn Fn(&mut MockServer) -> R) -> Option<R> {
        match self.mock_servers.iter_mut().find(|ms| ms.1.addr.port() == mock_server_port) {
            Some(mock_server) => {
                Some(f(mock_server.1))
            },
            None => None
        }
    }

    /// Map all the running mock servers
    pub fn map_mock_servers<R>(&self, f: &dyn Fn(&MockServer) -> R) -> Vec<R> {
        let mut results = vec![];
        for (_, mock_server) in self.mock_servers.iter() {
            results.push(f(mock_server));
        }
        return results
    }
}

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

    #[test]
    fn manager_should_start_and_shutdown_mock_server() {
        let mut manager = ServerManager::new();
        let start_result = manager.start_mock_server("foobar".into(), Pact::default(), 0);

        assert!(start_result.is_ok());
        let server_port = start_result.unwrap();

        // Server should be up
        assert!(TcpStream::connect(("127.0.0.1", server_port)).is_ok());

        // Should be able to read matches without blocking
        let matches = manager.find_mock_server_by_port_mut(server_port, &|mock_server| {
            mock_server.matches()
        });
        assert_eq!(matches, Some(vec![]));

        let stopped = manager.shutdown_mock_server_by_port(server_port);
        assert!(stopped);

        // The tokio runtime is now out of tasks
        drop(manager);

        // Server should be down
        assert!(TcpStream::connect(("127.0.0.1", server_port)).is_err());
    }
}
<commit_msg>pact_mock_server: Try to fix windows test fail by awaiting the server shutdown<commit_after>//!
//! This module defines a manager for holding multiple instances of mock servers.
//!

use crate::mock_server::MockServer;

use pact_matching::models::Pact;
use std::collections::BTreeMap;

struct ServerEntry {
    mock_server: Box<MockServer>,
    join_handle: tokio::task::JoinHandle<()>,
}

/// Struct to represent many mock servers running in a background thread
pub struct ServerManager {
    runtime: tokio::runtime::Runtime,
    mock_servers: BTreeMap<String, ServerEntry>,
}

impl ServerManager {
    /// Construct a new ServerManager for scheduling several instances of mock servers
    /// on one tokio runtime.
    pub fn new() -> ServerManager {
        ServerManager {
            runtime: tokio::runtime::Builder::new()
                .threaded_scheduler()
                .num_threads(1)
                .enable_all()
                .build()
                .unwrap(),
            mock_servers: BTreeMap::new(),
        }
    }

    /// Start a new server on the runtime
    pub fn start_mock_server_with_addr(
        &mut self,
        id: String,
        pact: Pact,
        addr: std::net::SocketAddr,
    ) -> Result<std::net::SocketAddr, String> {
        let (mock_server, future) =
            self.runtime
                .block_on(MockServer::new(id.clone(), pact, addr))?;

        let addr = mock_server.addr;

        self.mock_servers.insert(
            id,
            ServerEntry {
                mock_server: Box::new(mock_server),
                join_handle: self.runtime.spawn(future),
            },
        );
        Ok(addr)
    }

    /// Start a new server on the runtime
    pub fn start_mock_server(&mut self, id: String, pact: Pact, port: u16) -> Result<u16, String> {
        self.start_mock_server_with_addr(id, pact, ([0, 0, 0, 0], port as u16).into())
            .map(|addr| addr.port())
    }

    /// Shut down a server by its id
    pub fn shutdown_mock_server_by_id(&mut self, id: String) -> bool {
        match self.mock_servers.remove(&id) {
            Some(mut entry) => match entry.mock_server.shutdown() {
                Ok(()) => {
                    self.runtime.block_on(entry.join_handle).unwrap();
                    true
                }
                Err(_) => false,
            },
            None => false,
        }
    }

    /// Shut down a server by its local port number
    pub fn shutdown_mock_server_by_port(&mut self, port: u16) -> bool {
        log::debug!("Shutting down mock server with port {}", port);
        let result = self
            .mock_servers
            .iter()
            .find(|(_id, entry)| entry.mock_server.addr.port() == port)
            .map(|(_id, entry)| entry.mock_server.id.clone());

        if let Some(id) = result {
            if let Some(mut entry) = self.mock_servers.remove(&id) {
                return match entry.mock_server.shutdown() {
                    Ok(()) => {
                        self.runtime.block_on(entry.join_handle).unwrap();
                        true
                    }
                    Err(_) => false,
                };
            }
        }

        false
    }

    /// Find mock server by id, and map it using supplied function if found
    pub fn find_mock_server_by_id<R>(
        &self,
        id: &String,
        f: &dyn Fn(&MockServer) -> R,
    ) -> Option<R> {
        match self.mock_servers.get(id) {
            Some(entry) => Some(f(&entry.mock_server)),
            None => None,
        }
    }

    /// Find a mock server by port number and apply a mutating operation on it if successful
    pub fn find_mock_server_by_port_mut<R>(
        &mut self,
        mock_server_port: u16,
        f: &dyn Fn(&mut MockServer) -> R,
    ) -> Option<R> {
        match self
            .mock_servers
            .iter_mut()
            .find(|(_id, entry)| entry.mock_server.addr.port() == mock_server_port)
        {
            Some((_id, entry)) => Some(f(&mut entry.mock_server)),
            None => None,
        }
    }

    /// Map all the running mock servers
    pub fn map_mock_servers<R>(&self, f: &dyn Fn(&MockServer) -> R) -> Vec<R> {
        let mut results = vec![];
        for (_id_, entry) in self.mock_servers.iter() {
            results.push(f(&entry.mock_server));
        }
        return results;
    }
}

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

    #[test]
    fn manager_should_start_and_shutdown_mock_server() {
        let mut manager = ServerManager::new();
        let start_result = manager.start_mock_server("foobar".into(), Pact::default(), 0);

        assert!(start_result.is_ok());
        let server_port = start_result.unwrap();

        // Server should be up
        assert!(TcpStream::connect(("127.0.0.1", server_port)).is_ok());

        // Should be able to read matches without blocking
        let matches =
            manager.find_mock_server_by_port_mut(server_port, &|mock_server| mock_server.matches());
        assert_eq!(matches, Some(vec![]));

        let stopped = manager.shutdown_mock_server_by_port(server_port);
        assert!(stopped);

        // The tokio runtime is now out of tasks
        drop(manager);

        // Server should be down
        assert!(TcpStream::connect(("127.0.0.1", server_port)).is_err());
    }
}
<|endoftext|>


<commit_before>//! [GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-pushrules-scope-kind-ruleid)

use ruma_api::ruma_api;
use ruma_common::push::AnyPushRule;

use super::RuleKind;

ruma_api! {
    metadata: {
        description: "Retrieve a single specified push rule.",
        method: GET,
        name: "get_pushrule",
        path: "/_matrix/client/r0/pushrules/:scope/:kind/:rule_id",
        rate_limited: false,
        requires_authentication: true,
    }

    request: {
        /// The scope to fetch rules from. 'global' to specify global rules.
        #[ruma_api(path)]
        pub scope: String,

        /// The kind of rule
        #[ruma_api(path)]
        pub kind: RuleKind,

        /// The identifier for the rule.
        #[ruma_api(path)]
        pub rule_id: String,
    }

    response: {
        /// The specific push rule.
        #[ruma_api(body)]
        pub rule: AnyPushRule
    }

    error: crate::Error
}
<commit_msg>Add trailing comma<commit_after>//! [GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-pushrules-scope-kind-ruleid)

use ruma_api::ruma_api;
use ruma_common::push::AnyPushRule;

use super::RuleKind;

ruma_api! {
    metadata: {
        description: "Retrieve a single specified push rule.",
        method: GET,
        name: "get_pushrule",
        path: "/_matrix/client/r0/pushrules/:scope/:kind/:rule_id",
        rate_limited: false,
        requires_authentication: true,
    }

    request: {
        /// The scope to fetch rules from. 'global' to specify global rules.
        #[ruma_api(path)]
        pub scope: String,

        /// The kind of rule
        #[ruma_api(path)]
        pub kind: RuleKind,

        /// The identifier for the rule.
        #[ruma_api(path)]
        pub rule_id: String,
    }

    response: {
        /// The specific push rule.
        #[ruma_api(body)]
        pub rule: AnyPushRule,
    }

    error: crate::Error
}
<|endoftext|>


<commit_before>use kbdgen::{cldr::Keyboard, Load, ProjectBundle};
use log::{debug, log_enabled};
use snafu::{ResultExt, Snafu};
use snafu_cli_debug::SnafuCliDebug;
use std::{fs::File, io::BufWriter, path::PathBuf};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Cli {
    #[structopt(parse(from_os_str))]
    input: PathBuf,

    #[structopt(parse(from_os_str))]
    output: PathBuf,

    #[structopt(flatten)]
    verbose: clap_verbosity_flag::Verbosity,
}

fn main() -> Result<(), Error> {
    let opts = Cli::from_args();
    let _ = opts.verbose.setup_env_logger("kbdgen-to-cldr");

    let bundle = ProjectBundle::load(&opts.input).context(CannotLoad)?;
    if log_enabled!(log::Level::Debug) {
        debug!("Bundle `{}` loaded", opts.input.display());
        let locales = bundle
            .project
            .locales
            .values()
            .map(|l| l.name.as_str())
            .collect::<Vec<_>>();
        debug!("Bundle contains these locales: {:?}", locales);
    }

    bundle
        .layouts
        .iter()
        .map(|(name, layout)| (name, layout_to_cldr(&name, layout)))
        .try_for_each(|(name, keyboards)| {
            use kbdgen::cldr::ToXml;

            for (platform, keyboard) in keyboards? {
                let path = &opts.output.join(name).join(platform).with_extension("xml");
                std::fs::create_dir_all(path.parent().unwrap())
                    .context(CannotCreateFile { path })?;
                let file = File::create(path).context(CannotCreateFile { path })?;
                let mut writer = BufWriter::new(file);
                keyboard
                    .write_xml(&mut writer)
                    .context(CannotSerializeXml)?;
            }
            Ok(())
        })
        .context(CannotBeSaved)?;

    Ok(())
}

fn layout_to_cldr(
    name: &str,
    layout: &kbdgen::models::Layout,
) -> Result<Vec<(String, Keyboard)>, SavingError> {
    log::debug!("to cldr with you, {}!", name);

    use kbdgen::{
        cldr::*,
        models::{IsoKey, MobileModes},
    };
    use std::collections::BTreeMap;
    use strum::IntoEnumIterator;

    let mut res = vec![];

    fn mobile_mode_to_keyboard(
        name: &str,
        mobile: &MobileModes,
        long_presses: Option<&BTreeMap<String, String>>,
    ) -> Keyboard {
        let mut key_maps = vec![];

        for (modifiers, mapping) in mobile {
            let keys = IsoKey::iter()
                .zip(mapping.iter())
                .map(|(iso, value)| {
                    let long_press = long_presses.and_then(|l| l.get(value)).cloned();
                    Map {
                        iso: iso.to_string(),
                        to: value.to_string(),
                        transform: None,
                        long_press,
                    }
                })
                .collect();

            key_maps.push(KeyMap {
                keys,
                modifiers: Some(modifiers.to_string()),
            })
        }

        Keyboard {
            locale: name.to_string(),
            names: vec![Names {
                values: vec![Name {
                    value: name.to_string(),
                }],
            }],
            key_maps,
            ..Keyboard::default()
        }
    }

    if let Some(a) = layout.modes.android.as_ref() {
        log::debug!("android: check");
        res.push((
            String::from("android"),
            mobile_mode_to_keyboard(name, a, layout.longpress.as_ref()),
        ));
    }
    if let Some(a) = layout.modes.ios.as_ref() {
        log::debug!("ios: check");
        res.push((
            String::from("ios"),
            mobile_mode_to_keyboard(name, a, layout.longpress.as_ref()),
        ));
    }
    if let Some(a) = layout.modes.mobile.as_ref() {
        log::debug!("generic mobile: check");
        res.push((
            String::from("mobile"),
            mobile_mode_to_keyboard(name, a, layout.longpress.as_ref()),
        ));
    }

    Ok(res)
}

#[derive(Snafu, SnafuCliDebug)]
pub enum Error {
    #[snafu(display("Could not load kbdgen bundle"))]
    CannotLoad {
        source: kbdgen::LoadError,
        backtrace: snafu::Backtrace,
    },
    #[snafu(display("Could not write CLDR file"))]
    CannotBeSaved {
        source: SavingError,
        backtrace: snafu::Backtrace,
    },
}

#[derive(Snafu, Debug)]
pub enum SavingError {
    #[snafu(display("Could not create file `{}`", path.display()))]
    CannotCreateFile {
        path: PathBuf,
        source: std::io::Error,
        backtrace: snafu::Backtrace,
    },
    #[snafu(display("Could transform to xml"))]
    CannotSerializeXml {
        source: std::io::Error,
        backtrace: snafu::Backtrace,
    },
}
<commit_msg>First step towards Desktop CLDR<commit_after>use kbdgen::{
    cldr::{Keyboard, *},
    models::{DesktopModes, IsoKey, MobileModes},
    Load, ProjectBundle,
};
use log::{debug, log_enabled};
use snafu::{ResultExt, Snafu};
use snafu_cli_debug::SnafuCliDebug;
use std::{collections::BTreeMap, fs::File, io::BufWriter, path::PathBuf};
use structopt::StructOpt;
use strum::IntoEnumIterator;

#[derive(Debug, StructOpt)]
struct Cli {
    #[structopt(parse(from_os_str))]
    input: PathBuf,

    #[structopt(parse(from_os_str))]
    output: PathBuf,

    #[structopt(flatten)]
    verbose: clap_verbosity_flag::Verbosity,
}

fn main() -> Result<(), Error> {
    let opts = Cli::from_args();
    let _ = opts.verbose.setup_env_logger("kbdgen-to-cldr");

    let bundle = ProjectBundle::load(&opts.input).context(CannotLoad)?;
    if log_enabled!(log::Level::Debug) {
        debug!("Bundle `{}` loaded", opts.input.display());
        let locales = bundle
            .project
            .locales
            .values()
            .map(|l| l.name.as_str())
            .collect::<Vec<_>>();
        debug!("Bundle contains these locales: {:?}", locales);
    }

    bundle
        .layouts
        .iter()
        .map(|(name, layout)| (name, layout_to_cldr(&name, layout, &bundle)))
        .try_for_each(|(name, keyboards)| {
            for (platform, keyboard) in keyboards? {
                let path = &opts.output.join(name).join(platform).with_extension("xml");
                std::fs::create_dir_all(path.parent().unwrap())
                    .context(CannotCreateFile { path })?;
                let file = File::create(path).context(CannotCreateFile { path })?;
                let mut writer = BufWriter::new(file);
                keyboard
                    .write_xml(&mut writer)
                    .context(CannotSerializeXml)?;
            }
            Ok(())
        })
        .context(CannotBeSaved)?;

    Ok(())
}

fn layout_to_cldr(
    name: &str,
    layout: &kbdgen::models::Layout,
    _project: &kbdgen::ProjectBundle,
) -> Result<Vec<(String, Keyboard)>, SavingError> {
    log::debug!("to cldr with you, {}!", name);

    let mut res = vec![];

    if let Some(a) = layout.modes.android.as_ref() {
        log::debug!("android: check");
        res.push((
            String::from("android"),
            mobile_mode_to_keyboard(name, "android", a, layout.longpress.as_ref(), layout),
        ));
    }
    if let Some(a) = layout.modes.ios.as_ref() {
        log::debug!("ios: check");
        res.push((
            String::from("ios"),
            mobile_mode_to_keyboard(name, "ios", a, layout.longpress.as_ref(), layout),
        ));
    }
    if let Some(a) = layout.modes.mobile.as_ref() {
        log::debug!("generic mobile: check");
        res.push((
            String::from("mobile"),
            mobile_mode_to_keyboard(name, "mobile", a, layout.longpress.as_ref(), layout),
        ));
    }
    if let Some(a) = layout.modes.win.as_ref() {
        log::debug!("generic win: check");
        res.push((
            String::from("win"),
            desktop_mode_to_keyboard(name, "win", a, layout.longpress.as_ref(), layout),
        ));
    }
    if let Some(a) = layout.modes.mac.as_ref() {
        log::debug!("generic mac: check");
        res.push((
            String::from("mac"),
            desktop_mode_to_keyboard(name, "mac", a, layout.longpress.as_ref(), layout),
        ));
    }
    if let Some(a) = layout.modes.chrome.as_ref() {
        log::debug!("generic chrome: check");
        res.push((
            String::from("chrome"),
            desktop_mode_to_keyboard(name, "chrome", a, layout.longpress.as_ref(), layout),
        ));
    }
    if let Some(a) = layout.modes.x11.as_ref() {
        log::debug!("generic x11: check");
        res.push((
            String::from("x11"),
            desktop_mode_to_keyboard(name, "x11", a, layout.longpress.as_ref(), layout),
        ));
    }
    if let Some(a) = layout.modes.desktop.as_ref() {
        log::debug!("generic desktop: check");
        res.push((
            String::from("desktop"),
            desktop_mode_to_keyboard(name, "desktop", a, layout.longpress.as_ref(), layout),
        ));
    }

    Ok(res)
}

fn desktop_mode_to_keyboard(
    name: &str,
    target: &str,
    desktop: &DesktopModes,
    long_presses: Option<&BTreeMap<String, String>>,
    layout: &kbdgen::models::Layout,
) -> Keyboard {
    let mut key_maps = vec![];

    for (modifiers, mapping) in desktop {
        let keys = mapping
            .iter()
            .filter_map(|(iso, value)| {
                if let Some(value) = value.as_ref() {
                    Some((iso, value))
                } else {
                    None
                }
            })
            .map(|(iso, value)| {
                let long_press = long_presses.and_then(|l| l.get(value.as_str())).cloned();
                Map {
                    iso: iso.to_string(),
                    to: value.to_string(),
                    transform: None,
                    long_press,
                }
            })
            .collect();

        key_maps.push(KeyMap {
            keys,
            modifiers: Some(modifiers.to_string()),
        })
    }

    Keyboard {
        locale: format!("{}-t-k0-{}", name, target),
        names: vec![Names {
            values: vec![Name {
                value: pick_name_from_display_names(&layout.display_names),
            }],
        }],
        key_maps,
        ..Keyboard::default()
    }
}

fn mobile_mode_to_keyboard(
    name: &str,
    target: &str,
    mobile: &MobileModes,
    long_presses: Option<&BTreeMap<String, String>>,
    layout: &kbdgen::models::Layout,
) -> Keyboard {
    let mut key_maps = vec![];

    for (modifiers, mapping) in mobile {
        let keys = IsoKey::iter()
            .zip(mapping.iter())
            .map(|(iso, value)| {
                let long_press = long_presses.and_then(|l| l.get(value)).cloned();
                Map {
                    iso: iso.to_string(),
                    to: value.to_string(),
                    transform: None,
                    long_press,
                }
            })
            .collect();

        key_maps.push(KeyMap {
            keys,
            modifiers: Some(modifiers.to_string()),
        })
    }

    Keyboard {
        locale: format!("{}-t-k0-{}", name, target),
        names: vec![Names {
            values: vec![Name {
                value: pick_name_from_display_names(&layout.display_names),
            }],
        }],
        key_maps,
        ..Keyboard::default()
    }
}

fn pick_name_from_display_names(names: &BTreeMap<String, String>) -> String {
    names
        .get("en")
        .or_else(|| names.values().next())
        .cloned()
        .unwrap_or_default()
}

#[derive(Snafu, SnafuCliDebug)]
pub enum Error {
    #[snafu(display("Could not load kbdgen bundle"))]
    CannotLoad {
        source: kbdgen::LoadError,
        backtrace: snafu::Backtrace,
    },
    #[snafu(display("Could not write CLDR file"))]
    CannotBeSaved {
        source: SavingError,
        backtrace: snafu::Backtrace,
    },
}

#[derive(Snafu, Debug)]
pub enum SavingError {
    #[snafu(display("Could not create file `{}`", path.display()))]
    CannotCreateFile {
        path: PathBuf,
        source: std::io::Error,
        backtrace: snafu::Backtrace,
    },
    #[snafu(display("Could transform to xml"))]
    CannotSerializeXml {
        source: std::io::Error,
        backtrace: snafu::Backtrace,
    },
}
<|endoftext|>


<commit_before>use app_units::Au;
use core_graphics::base::kCGImageAlphaPremultipliedLast;
use core_graphics::color_space::CGColorSpace;
use core_graphics::context::CGContext;
use core_graphics::data_provider::CGDataProvider;
use core_graphics::font::{CGFont, CGGlyph};
use core_graphics::geometry::CGPoint;
use core_text::font::CTFont;
use core_text::font_descriptor::kCTFontDefaultOrientation;
use core_text;
use libc::size_t;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use types::FontKey;

pub type NativeFontHandle = CGFont;

pub struct FontContext {
    cg_fonts: HashMap<FontKey, CGFont>,
    ct_fonts: HashMap<(FontKey, Au), CTFont>,
}

pub struct RasterizedGlyph {
    pub left: i32,
    pub top: i32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

impl RasterizedGlyph {
    pub fn blank() -> RasterizedGlyph {
        RasterizedGlyph {
            left: 0,
            top: 0,
            width: 0,
            height: 0,
            bytes: vec![],
        }
    }
}

impl FontContext {
    pub fn new() -> FontContext {
        FontContext {
            cg_fonts: HashMap::new(),
            ct_fonts: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        let data_provider = CGDataProvider::from_buffer(bytes);
        let cg_font = match CGFont::from_data_provider(data_provider) {
            Err(_) => return,
            Ok(cg_font) => cg_font,
        };
        self.cg_fonts.insert((*font_key).clone(), cg_font);
    }

    pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: CGFont) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        self.cg_fonts.insert((*font_key).clone(), native_font_handle);
    }

    pub fn get_glyph(&mut self,
                     font_key: &FontKey,
                     size: Au,
                     character: u32,
                     device_pixel_ratio: f32)
                     -> Option<RasterizedGlyph> {
        let ct_font = match self.ct_fonts.entry(((*font_key).clone(), size)) {
            Entry::Occupied(entry) => (*entry.get()).clone(),
            Entry::Vacant(entry) => {
                let cg_font = match self.cg_fonts.get(font_key) {
                    None => return Some(RasterizedGlyph::blank()),
                    Some(cg_font) => cg_font,
                };
                let ct_font = core_text::font::new_from_CGFont(
                        cg_font,
                        size.to_f64_px() * (device_pixel_ratio as f64));
                entry.insert(ct_font.clone());
                ct_font
            }
        };

        let glyph = character as CGGlyph;
        let bounds = ct_font.get_bounding_rects_for_glyphs(kCTFontDefaultOrientation, &[glyph]);

        // We add in one extra pixel of width in the horizontal direction to account for
        // antialiasing.
        let rasterized_left = bounds.origin.x.floor() as i32;
        let rasterized_width =
            (bounds.origin.x - (rasterized_left as f64) + bounds.size.width).ceil() as u32 + 1;
        let rasterized_descent = (-bounds.origin.y).ceil() as i32;
        let rasterized_ascent = (bounds.size.height + bounds.origin.y).ceil() as i32;
        let rasterized_height = (rasterized_descent + rasterized_ascent) as u32;
        if rasterized_width == 0 || rasterized_height == 0 {
            return Some(RasterizedGlyph::blank())
        }

        let mut cg_context = CGContext::create_bitmap_context(rasterized_width as size_t,
                                                              rasterized_height as size_t,
                                                              8,
                                                              rasterized_width as size_t * 4,
                                                              &CGColorSpace::create_device_rgb(),
                                                              kCGImageAlphaPremultipliedLast);
        cg_context.set_allows_font_smoothing(true);
        cg_context.set_should_smooth_fonts(true);
        cg_context.set_rgb_fill_color(1.0, 1.0, 1.0, 1.0);

        let rasterization_origin = CGPoint {
            x: bounds.origin.x - (rasterized_left as f64),
            y: rasterized_descent as f64,
        };
        ct_font.draw_glyphs(&[glyph], &[rasterization_origin], cg_context.clone());

        let rasterized_area = (rasterized_width * rasterized_height) as usize;
        let mut rasterized_pixels = cg_context.data().to_vec();
        for i in 0..rasterized_area {
            let alpha = (rasterized_pixels[i * 4 + 3] as f32) / 255.0;
            for j in 0..3 {
                rasterized_pixels[i * 4 + j] =
                    ((rasterized_pixels[i * 4 + j] as f32) / alpha) as u8;
            }
        }

        Some(RasterizedGlyph {
            left: rasterized_left,
            top: (bounds.size.height + bounds.origin.y).ceil() as i32,
            width: rasterized_width,
            height: rasterized_height,
            bytes: rasterized_pixels,
        })
    }
}

<commit_msg>Fix the positioning of Mac glyphs.<commit_after>use app_units::Au;
use core_graphics::base::kCGImageAlphaPremultipliedLast;
use core_graphics::color_space::CGColorSpace;
use core_graphics::context::CGContext;
use core_graphics::data_provider::CGDataProvider;
use core_graphics::font::{CGFont, CGGlyph};
use core_graphics::geometry::CGPoint;
use core_text::font::CTFont;
use core_text::font_descriptor::kCTFontDefaultOrientation;
use core_text;
use libc::size_t;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use types::FontKey;

pub type NativeFontHandle = CGFont;

pub struct FontContext {
    cg_fonts: HashMap<FontKey, CGFont>,
    ct_fonts: HashMap<(FontKey, Au), CTFont>,
}

pub struct RasterizedGlyph {
    pub left: i32,
    pub top: i32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

impl RasterizedGlyph {
    pub fn blank() -> RasterizedGlyph {
        RasterizedGlyph {
            left: 0,
            top: 0,
            width: 0,
            height: 0,
            bytes: vec![],
        }
    }
}

impl FontContext {
    pub fn new() -> FontContext {
        FontContext {
            cg_fonts: HashMap::new(),
            ct_fonts: HashMap::new(),
        }
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8]) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        let data_provider = CGDataProvider::from_buffer(bytes);
        let cg_font = match CGFont::from_data_provider(data_provider) {
            Err(_) => return,
            Ok(cg_font) => cg_font,
        };
        self.cg_fonts.insert((*font_key).clone(), cg_font);
    }

    pub fn add_native_font(&mut self, font_key: &FontKey, native_font_handle: CGFont) {
        if self.cg_fonts.contains_key(font_key) {
            return
        }

        self.cg_fonts.insert((*font_key).clone(), native_font_handle);
    }

    pub fn get_glyph(&mut self,
                     font_key: &FontKey,
                     size: Au,
                     character: u32,
                     device_pixel_ratio: f32)
                     -> Option<RasterizedGlyph> {
        let ct_font = match self.ct_fonts.entry(((*font_key).clone(), size)) {
            Entry::Occupied(entry) => (*entry.get()).clone(),
            Entry::Vacant(entry) => {
                let cg_font = match self.cg_fonts.get(font_key) {
                    None => return Some(RasterizedGlyph::blank()),
                    Some(cg_font) => cg_font,
                };
                let ct_font = core_text::font::new_from_CGFont(
                        cg_font,
                        size.to_f64_px() * (device_pixel_ratio as f64));
                entry.insert(ct_font.clone());
                ct_font
            }
        };

        let glyph = character as CGGlyph;
        let bounds = ct_font.get_bounding_rects_for_glyphs(kCTFontDefaultOrientation, &[glyph]);

        let rasterized_left = bounds.origin.x.floor() as i32;
        let rasterized_width =
            (bounds.origin.x - (rasterized_left as f64) + bounds.size.width).ceil() as u32;
        let rasterized_descent = (-bounds.origin.y).ceil() as i32;
        let rasterized_ascent = (bounds.size.height + bounds.origin.y).ceil() as i32;
        let rasterized_height = (rasterized_descent + rasterized_ascent) as u32;
        if rasterized_width == 0 || rasterized_height == 0 {
            return Some(RasterizedGlyph::blank())
        }

        let mut cg_context = CGContext::create_bitmap_context(rasterized_width as size_t,
                                                              rasterized_height as size_t,
                                                              8,
                                                              rasterized_width as size_t * 4,
                                                              &CGColorSpace::create_device_rgb(),
                                                              kCGImageAlphaPremultipliedLast);
        cg_context.set_allows_font_smoothing(true);
        cg_context.set_should_smooth_fonts(true);
        cg_context.set_rgb_fill_color(1.0, 1.0, 1.0, 1.0);

        let rasterization_origin = CGPoint {
            x: -rasterized_left as f64,
            y: rasterized_descent as f64,
        };
        ct_font.draw_glyphs(&[glyph], &[rasterization_origin], cg_context.clone());

        let rasterized_area = (rasterized_width * rasterized_height) as usize;
        let mut rasterized_pixels = cg_context.data().to_vec();
        for i in 0..rasterized_area {
            let alpha = (rasterized_pixels[i * 4 + 3] as f32) / 255.0;
            for j in 0..3 {
                rasterized_pixels[i * 4 + j] =
                    ((rasterized_pixels[i * 4 + j] as f32) / alpha) as u8;
            }
        }

        Some(RasterizedGlyph {
            left: rasterized_left,
            top: (bounds.size.height + bounds.origin.y).ceil() as i32,
            width: rasterized_width,
            height: rasterized_height,
            bytes: rasterized_pixels,
        })
    }
}

<|endoftext|>


<commit_before>use super::*;
use crate::case_result::compare_result;
use cached_tree_hash::{CachedTreeHash, TreeHashCache};
use serde_derive::Deserialize;
use ssz::{Decode, Encode};
use std::fmt::Debug;
use std::marker::PhantomData;
use tree_hash::TreeHash;
use types::{
    test_utils::{SeedableRng, TestRandom, XorShiftRng},
    Attestation, AttestationData, AttestationDataAndCustodyBit, AttesterSlashing, BeaconBlock,
    BeaconBlockBody, BeaconBlockHeader, BeaconState, Crosslink, Deposit, DepositData, Eth1Data,
    EthSpec, Fork, Hash256, HistoricalBatch, IndexedAttestation, PendingAttestation,
    ProposerSlashing, Transfer, Validator, VoluntaryExit,
};

// Enum variant names are used by Serde when deserializing the test YAML
#[derive(Debug, Clone, Deserialize)]
pub enum SszStatic<E>
where
    E: EthSpec,
{
    Fork(SszStaticInner<Fork, E>),
    Crosslink(SszStaticInner<Crosslink, E>),
    Eth1Data(SszStaticInner<Eth1Data, E>),
    AttestationData(SszStaticInner<AttestationData, E>),
    AttestationDataAndCustodyBit(SszStaticInner<AttestationDataAndCustodyBit, E>),
    IndexedAttestation(SszStaticInner<IndexedAttestation, E>),
    DepositData(SszStaticInner<DepositData, E>),
    BeaconBlockHeader(SszStaticInner<BeaconBlockHeader, E>),
    Validator(SszStaticInner<Validator, E>),
    PendingAttestation(SszStaticInner<PendingAttestation, E>),
    HistoricalBatch(SszStaticInner<HistoricalBatch<E>, E>),
    ProposerSlashing(SszStaticInner<ProposerSlashing, E>),
    AttesterSlashing(SszStaticInner<AttesterSlashing, E>),
    Attestation(SszStaticInner<Attestation, E>),
    Deposit(SszStaticInner<Deposit, E>),
    VoluntaryExit(SszStaticInner<VoluntaryExit, E>),
    Transfer(SszStaticInner<Transfer, E>),
    BeaconBlockBody(SszStaticInner<BeaconBlockBody, E>),
    BeaconBlock(SszStaticInner<BeaconBlock, E>),
    BeaconState(SszStaticInner<BeaconState<E>, E>),
}

#[derive(Debug, Clone, Deserialize)]
pub struct SszStaticInner<T, E>
where
    E: EthSpec,
{
    pub value: T,
    pub serialized: String,
    pub root: String,
    #[serde(skip, default)]
    _phantom: PhantomData<E>,
}

impl<E: EthSpec + serde::de::DeserializeOwned> YamlDecode for SszStatic<E> {
    fn yaml_decode(yaml: &str) -> Result<Self, Error> {
        serde_yaml::from_str(yaml).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))
    }
}

impl<E: EthSpec> Case for SszStatic<E> {
    fn result(&self, _case_index: usize) -> Result<(), Error> {
        use self::SszStatic::*;

        match *self {
            Fork(ref val) => ssz_static_test(val),
            Crosslink(ref val) => ssz_static_test(val),
            Eth1Data(ref val) => ssz_static_test(val),
            AttestationData(ref val) => ssz_static_test(val),
            AttestationDataAndCustodyBit(ref val) => ssz_static_test(val),
            IndexedAttestation(ref val) => ssz_static_test(val),
            DepositData(ref val) => ssz_static_test(val),
            BeaconBlockHeader(ref val) => ssz_static_test(val),
            Validator(ref val) => ssz_static_test(val),
            PendingAttestation(ref val) => ssz_static_test(val),
            HistoricalBatch(ref val) => ssz_static_test(val),
            ProposerSlashing(ref val) => ssz_static_test(val),
            AttesterSlashing(ref val) => ssz_static_test(val),
            Attestation(ref val) => ssz_static_test(val),
            Deposit(ref val) => ssz_static_test(val),
            VoluntaryExit(ref val) => ssz_static_test(val),
            Transfer(ref val) => ssz_static_test(val),
            BeaconBlockBody(ref val) => ssz_static_test(val),
            BeaconBlock(ref val) => ssz_static_test(val),
            BeaconState(ref val) => ssz_static_test(val),
        }
    }
}

fn ssz_static_test<T, E: EthSpec>(tc: &SszStaticInner<T, E>) -> Result<(), Error>
where
    T: Clone
        + Decode
        + Debug
        + Encode
        + PartialEq<T>
        + serde::de::DeserializeOwned
        + TreeHash
        + CachedTreeHash
        + TestRandom,
{
    // Verify we can decode SSZ in the same way we can decode YAML.
    let ssz = hex::decode(&tc.serialized[2..])
        .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
    let expected = tc.value.clone();
    let decode_result = T::from_ssz_bytes(&ssz);
    compare_result(&decode_result, &Some(expected))?;

    // Verify we can encode the result back into original ssz bytes
    let decoded = decode_result.unwrap();
    let encoded_result = decoded.as_ssz_bytes();
    compare_result::<Vec<u8>, Error>(&Ok(encoded_result), &Some(ssz))?;

    // Verify the TreeHash root of the decoded struct matches the test.
    let expected_root =
        &hex::decode(&tc.root[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
    let expected_root = Hash256::from_slice(&expected_root);
    let tree_hash_root = Hash256::from_slice(&decoded.tree_hash_root());
    compare_result::<Hash256, Error>(&Ok(tree_hash_root), &Some(expected_root))?;

    // Verify a _new_ CachedTreeHash root of the decoded struct matches the test.
    let cache = TreeHashCache::new(&decoded).unwrap();
    let cached_tree_hash_root = Hash256::from_slice(cache.tree_hash_root().unwrap());
    compare_result::<Hash256, Error>(&Ok(cached_tree_hash_root), &Some(expected_root))?;

    // Verify the root after an update from a random CachedTreeHash to the decoded struct.
    let mut rng = XorShiftRng::from_seed([42; 16]);
    let random_instance = T::random_for_test(&mut rng);
    let mut cache = TreeHashCache::new(&random_instance).unwrap();
    cache.update(&decoded).unwrap();
    let updated_root = Hash256::from_slice(cache.tree_hash_root().unwrap());
    compare_result::<Hash256, Error>(&Ok(updated_root), &Some(expected_root))?;

    Ok(())
}
<commit_msg>Ignore clippy lint in ef_tests<commit_after>use super::*;
use crate::case_result::compare_result;
use cached_tree_hash::{CachedTreeHash, TreeHashCache};
use serde_derive::Deserialize;
use ssz::{Decode, Encode};
use std::fmt::Debug;
use std::marker::PhantomData;
use tree_hash::TreeHash;
use types::{
    test_utils::{SeedableRng, TestRandom, XorShiftRng},
    Attestation, AttestationData, AttestationDataAndCustodyBit, AttesterSlashing, BeaconBlock,
    BeaconBlockBody, BeaconBlockHeader, BeaconState, Crosslink, Deposit, DepositData, Eth1Data,
    EthSpec, Fork, Hash256, HistoricalBatch, IndexedAttestation, PendingAttestation,
    ProposerSlashing, Transfer, Validator, VoluntaryExit,
};

// Enum variant names are used by Serde when deserializing the test YAML
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, Deserialize)]
pub enum SszStatic<E>
where
    E: EthSpec,
{
    Fork(SszStaticInner<Fork, E>),
    Crosslink(SszStaticInner<Crosslink, E>),
    Eth1Data(SszStaticInner<Eth1Data, E>),
    AttestationData(SszStaticInner<AttestationData, E>),
    AttestationDataAndCustodyBit(SszStaticInner<AttestationDataAndCustodyBit, E>),
    IndexedAttestation(SszStaticInner<IndexedAttestation, E>),
    DepositData(SszStaticInner<DepositData, E>),
    BeaconBlockHeader(SszStaticInner<BeaconBlockHeader, E>),
    Validator(SszStaticInner<Validator, E>),
    PendingAttestation(SszStaticInner<PendingAttestation, E>),
    HistoricalBatch(SszStaticInner<HistoricalBatch<E>, E>),
    ProposerSlashing(SszStaticInner<ProposerSlashing, E>),
    AttesterSlashing(SszStaticInner<AttesterSlashing, E>),
    Attestation(SszStaticInner<Attestation, E>),
    Deposit(SszStaticInner<Deposit, E>),
    VoluntaryExit(SszStaticInner<VoluntaryExit, E>),
    Transfer(SszStaticInner<Transfer, E>),
    BeaconBlockBody(SszStaticInner<BeaconBlockBody, E>),
    BeaconBlock(SszStaticInner<BeaconBlock, E>),
    BeaconState(SszStaticInner<BeaconState<E>, E>),
}

#[derive(Debug, Clone, Deserialize)]
pub struct SszStaticInner<T, E>
where
    E: EthSpec,
{
    pub value: T,
    pub serialized: String,
    pub root: String,
    #[serde(skip, default)]
    _phantom: PhantomData<E>,
}

impl<E: EthSpec + serde::de::DeserializeOwned> YamlDecode for SszStatic<E> {
    fn yaml_decode(yaml: &str) -> Result<Self, Error> {
        serde_yaml::from_str(yaml).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))
    }
}

impl<E: EthSpec> Case for SszStatic<E> {
    fn result(&self, _case_index: usize) -> Result<(), Error> {
        use self::SszStatic::*;

        match *self {
            Fork(ref val) => ssz_static_test(val),
            Crosslink(ref val) => ssz_static_test(val),
            Eth1Data(ref val) => ssz_static_test(val),
            AttestationData(ref val) => ssz_static_test(val),
            AttestationDataAndCustodyBit(ref val) => ssz_static_test(val),
            IndexedAttestation(ref val) => ssz_static_test(val),
            DepositData(ref val) => ssz_static_test(val),
            BeaconBlockHeader(ref val) => ssz_static_test(val),
            Validator(ref val) => ssz_static_test(val),
            PendingAttestation(ref val) => ssz_static_test(val),
            HistoricalBatch(ref val) => ssz_static_test(val),
            ProposerSlashing(ref val) => ssz_static_test(val),
            AttesterSlashing(ref val) => ssz_static_test(val),
            Attestation(ref val) => ssz_static_test(val),
            Deposit(ref val) => ssz_static_test(val),
            VoluntaryExit(ref val) => ssz_static_test(val),
            Transfer(ref val) => ssz_static_test(val),
            BeaconBlockBody(ref val) => ssz_static_test(val),
            BeaconBlock(ref val) => ssz_static_test(val),
            BeaconState(ref val) => ssz_static_test(val),
        }
    }
}

fn ssz_static_test<T, E: EthSpec>(tc: &SszStaticInner<T, E>) -> Result<(), Error>
where
    T: Clone
        + Decode
        + Debug
        + Encode
        + PartialEq<T>
        + serde::de::DeserializeOwned
        + TreeHash
        + CachedTreeHash
        + TestRandom,
{
    // Verify we can decode SSZ in the same way we can decode YAML.
    let ssz = hex::decode(&tc.serialized[2..])
        .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
    let expected = tc.value.clone();
    let decode_result = T::from_ssz_bytes(&ssz);
    compare_result(&decode_result, &Some(expected))?;

    // Verify we can encode the result back into original ssz bytes
    let decoded = decode_result.unwrap();
    let encoded_result = decoded.as_ssz_bytes();
    compare_result::<Vec<u8>, Error>(&Ok(encoded_result), &Some(ssz))?;

    // Verify the TreeHash root of the decoded struct matches the test.
    let expected_root =
        &hex::decode(&tc.root[2..]).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;
    let expected_root = Hash256::from_slice(&expected_root);
    let tree_hash_root = Hash256::from_slice(&decoded.tree_hash_root());
    compare_result::<Hash256, Error>(&Ok(tree_hash_root), &Some(expected_root))?;

    // Verify a _new_ CachedTreeHash root of the decoded struct matches the test.
    let cache = TreeHashCache::new(&decoded).unwrap();
    let cached_tree_hash_root = Hash256::from_slice(cache.tree_hash_root().unwrap());
    compare_result::<Hash256, Error>(&Ok(cached_tree_hash_root), &Some(expected_root))?;

    // Verify the root after an update from a random CachedTreeHash to the decoded struct.
    let mut rng = XorShiftRng::from_seed([42; 16]);
    let random_instance = T::random_for_test(&mut rng);
    let mut cache = TreeHashCache::new(&random_instance).unwrap();
    cache.update(&decoded).unwrap();
    let updated_root = Hash256::from_slice(cache.tree_hash_root().unwrap());
    compare_result::<Hash256, Error>(&Ok(updated_root), &Some(expected_root))?;

    Ok(())
}
<|endoftext|>


<commit_before>#[doc(
    brief = "Attribute parsing",
    desc =
    "The attribute parser provides methods for pulling documentation out of \
     an AST's attributes."
)];

import rustc::syntax::ast;
import rustc::front::attr;
import core::tuple;

export crate_attrs, mod_attrs, fn_attrs, arg_attrs, const_attrs, enum_attrs;
export parse_crate, parse_mod, parse_fn, parse_const, parse_enum;

type crate_attrs = {
    name: option<str>
};

type mod_attrs = {
    brief: option<str>,
    desc: option<str>
};

type fn_attrs = {
    brief: option<str>,
    desc: option<str>,
    args: [arg_attrs],
    return: option<str>,
    failure: option<str>
};

type arg_attrs = {
    name: str,
    desc: str
};

type const_attrs = {
    brief: option<str>,
    desc: option<str>
};

type enum_attrs = {
    brief: option<str>,
    desc: option<str>
};

type variant_attrs = {
    desc: option<str>
};

#[cfg(test)]
mod test {

    fn parse_attributes(source: str) -> [ast::attribute] {
        import rustc::syntax::parse::parser;
        // FIXME: Uncommenting this results in rustc bugs
        //import rustc::syntax::codemap;
        import rustc::driver::diagnostic;

        let cm = rustc::syntax::codemap::new_codemap();
        let handler = diagnostic::mk_handler(none);
        let parse_sess = @{
            cm: cm,
            mutable next_id: 0,
            span_diagnostic: diagnostic::mk_span_handler(handler, cm),
            mutable chpos: 0u,
            mutable byte_pos: 0u
        };
        let parser = parser::new_parser_from_source_str(
            parse_sess, [], "-", @source);

        parser::parse_outer_attributes(parser)
    }
}

fn doc_meta(
    attrs: [ast::attribute]
) -> option<@ast::meta_item> {

    #[doc =
      "Given a vec of attributes, extract the meta_items contained in the \
       doc attribute"];

    let doc_attrs = attr::find_attrs_by_name(attrs, "doc");
    let doc_metas = attr::attr_metas(doc_attrs);
    if vec::is_not_empty(doc_metas) {
        if vec::len(doc_metas) != 1u {
            #warn("ignoring %u doc attributes", vec::len(doc_metas) - 1u);
        }
        some(doc_metas[0])
    } else {
        none
    }
}

fn parse_crate(attrs: [ast::attribute]) -> crate_attrs {
    let link_metas = attr::find_linkage_metas(attrs);

    {
        name: attr::meta_item_value_from_list(link_metas, "name")
    }
}

#[test]
fn should_extract_crate_name_from_link_attribute() {
    let source = "#[link(name = \"snuggles\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == some("snuggles");
}

#[test]
fn should_not_extract_crate_name_if_no_link_attribute() {
    let source = "";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == none;
}

#[test]
fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() {
    let source = "#[link(whatever)]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == none;
}

fn parse_mod(attrs: [ast::attribute]) -> mod_attrs {
    parse_short_doc_or(
        attrs,
        {|desc|
            {
                brief: none,
                desc: desc
            }
        },
        parse_mod_long_doc
    )
}

fn parse_mod_long_doc(
    _items: [@ast::meta_item],
    brief: option<str>,
    desc: option<str>
) -> mod_attrs {
    {
        brief: brief,
        desc: desc
    }
}

#[test]
fn parse_mod_should_handle_undocumented_mods() {
    let source = "";
    let attrs = test::parse_attributes(source);
    let attrs = parse_mod(attrs);
    assert attrs.brief == none;
    assert attrs.desc == none;
}

#[test]
fn parse_mod_should_parse_simple_doc_attributes() {
    let source = "#[doc = \"basic\"]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_mod(attrs);
    assert attrs.desc == some("basic");
}

#[test]
fn parse_mod_should_parse_the_brief_description() {
    let source = "#[doc(brief = \"short\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_mod(attrs);
    assert attrs.brief == some("short");
}

#[test]
fn parse_mod_should_parse_the_long_description() {
    let source = "#[doc(desc = \"description\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_mod(attrs);
    assert attrs.desc == some("description");
}

fn parse_short_doc_or<T>(
    attrs: [ast::attribute],
    handle_short: fn&(
        short_desc: option<str>
    ) -> T,
    parse_long: fn&(
        doc_items: [@ast::meta_item],
        brief: option<str>,
        desc: option<str>
    ) -> T
) -> T {
    alt doc_meta(attrs) {
      some(meta) {
        alt attr::get_meta_item_value_str(meta) {
          some(desc) { handle_short(some(desc)) }
          none {
            alt attr::get_meta_item_list(meta) {
              some(list) {
                let brief = attr::meta_item_value_from_list(list, "brief");
                let desc = attr::meta_item_value_from_list(list, "desc");
                parse_long(list, brief, desc)
              }
              none {
                handle_short(none)
              }
            }
          }
        }
      }
      none {
        handle_short(none)
      }
    }
}

fn parse_fn(
    attrs: [ast::attribute]
) -> fn_attrs {

    parse_short_doc_or(
        attrs,
        {|desc|
            {
                brief: none,
                desc: desc,
                args: [],
                return: none,
                failure: none
            }
        },
        parse_fn_long_doc
    )
}

fn parse_fn_long_doc(
    items: [@ast::meta_item],
    brief: option<str>,
    desc: option<str>
) -> fn_attrs {
    let return = attr::meta_item_value_from_list(items, "return");
    let failure = attr::meta_item_value_from_list(items, "failure");
    let args = alt attr::meta_item_list_from_list(items, "args") {
      some(items) {
        vec::filter_map(items) {|item|
            option::map(attr::name_value_str_pair(item)) { |pair|
                {
                    name: tuple::first(pair),
                    desc: tuple::second(pair)
                }
            }
        }
      }
      none { [] }
    };

    {
        brief: brief,
        desc: desc,
        args: args,
        return: return,
        failure: failure
    }
}

#[test]
fn parse_fn_should_handle_undocumented_functions() {
    let source = "";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.brief == none;
    assert attrs.desc == none;
    assert attrs.return == none;
    assert vec::len(attrs.args) == 0u;
}

#[test]
fn parse_fn_should_parse_simple_doc_attributes() {
    let source = "#[doc = \"basic\"]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.desc == some("basic");
}

#[test]
fn parse_fn_should_parse_the_brief_description() {
    let source = "#[doc(brief = \"short\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.brief == some("short");
}

#[test]
fn parse_fn_should_parse_the_long_description() {
    let source = "#[doc(desc = \"description\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.desc == some("description");
}

#[test]
fn parse_fn_should_parse_the_return_value_description() {
    let source = "#[doc(return = \"return value\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.return == some("return value");
}

#[test]
fn parse_fn_should_parse_the_argument_descriptions() {
    let source = "#[doc(args(a = \"arg a\", b = \"arg b\"))]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.args[0] == {name: "a", desc: "arg a"};
    assert attrs.args[1] == {name: "b", desc: "arg b"};
}

#[test]
fn parse_fn_should_parse_failure_conditions() {
    let source = "#[doc(failure = \"it's the fail\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.failure == some("it's the fail");
}

fn parse_const(attrs: [ast::attribute]) -> const_attrs {
    parse_short_doc_or(
        attrs,
        {|desc|
            {
                brief: none,
                desc: desc
            }
        },
        parse_const_long_doc
    )
}

fn parse_const_long_doc(
    _items: [@ast::meta_item],
    brief: option<str>,
    desc: option<str>
) -> const_attrs {
    {
        brief: brief,
        desc: desc
    }
}

#[test]
fn should_parse_const_short_doc() {
    let source = "#[doc = \"description\"]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_const(attrs);
    assert attrs.desc == some("description");
}

#[test]
fn should_parse_const_long_doc() {
    let source = "#[doc(brief = \"a\", desc = \"b\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_const(attrs);
    assert attrs.brief == some("a");
    assert attrs.desc == some("b");
}

fn parse_enum(attrs: [ast::attribute]) -> enum_attrs {
    parse_short_doc_or(
        attrs,
        {|desc|
            {
                brief: none,
                desc: desc
            }
        },
        parse_enum_long_doc
    )
}

fn parse_enum_long_doc(
    _items: [@ast::meta_item],
    brief: option<str>,
    desc: option<str>
) -> enum_attrs {
    {
        brief: brief,
        desc: desc
    }
}

#[test]
fn should_parse_enum_short_doc() {
    let source = "#[doc = \"description\"]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_enum(attrs);
    assert attrs.desc == some("description");
}

#[test]
fn should_parse_enum_long_doc() {
    let source = "#[doc(brief = \"a\", desc = \"b\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_enum(attrs);
    assert attrs.brief == some("a");
    assert attrs.desc == some("b");
}
<commit_msg>rustdoc: Extract some common functions from attr_parser<commit_after>#[doc(
    brief = "Attribute parsing",
    desc =
    "The attribute parser provides methods for pulling documentation out of \
     an AST's attributes."
)];

import rustc::syntax::ast;
import rustc::front::attr;
import core::tuple;

export crate_attrs, mod_attrs, fn_attrs, arg_attrs, const_attrs, enum_attrs;
export parse_crate, parse_mod, parse_fn, parse_const, parse_enum;

type crate_attrs = {
    name: option<str>
};

type mod_attrs = {
    brief: option<str>,
    desc: option<str>
};

type fn_attrs = {
    brief: option<str>,
    desc: option<str>,
    args: [arg_attrs],
    return: option<str>,
    failure: option<str>
};

type arg_attrs = {
    name: str,
    desc: str
};

type const_attrs = {
    brief: option<str>,
    desc: option<str>
};

type enum_attrs = {
    brief: option<str>,
    desc: option<str>
};

type variant_attrs = {
    desc: option<str>
};

#[cfg(test)]
mod test {

    fn parse_attributes(source: str) -> [ast::attribute] {
        import rustc::syntax::parse::parser;
        // FIXME: Uncommenting this results in rustc bugs
        //import rustc::syntax::codemap;
        import rustc::driver::diagnostic;

        let cm = rustc::syntax::codemap::new_codemap();
        let handler = diagnostic::mk_handler(none);
        let parse_sess = @{
            cm: cm,
            mutable next_id: 0,
            span_diagnostic: diagnostic::mk_span_handler(handler, cm),
            mutable chpos: 0u,
            mutable byte_pos: 0u
        };
        let parser = parser::new_parser_from_source_str(
            parse_sess, [], "-", @source);

        parser::parse_outer_attributes(parser)
    }
}

fn doc_meta(
    attrs: [ast::attribute]
) -> option<@ast::meta_item> {

    #[doc =
      "Given a vec of attributes, extract the meta_items contained in the \
       doc attribute"];

    let doc_attrs = attr::find_attrs_by_name(attrs, "doc");
    let doc_metas = attr::attr_metas(doc_attrs);
    if vec::is_not_empty(doc_metas) {
        if vec::len(doc_metas) != 1u {
            #warn("ignoring %u doc attributes", vec::len(doc_metas) - 1u);
        }
        some(doc_metas[0])
    } else {
        none
    }
}

fn parse_crate(attrs: [ast::attribute]) -> crate_attrs {
    let link_metas = attr::find_linkage_metas(attrs);

    {
        name: attr::meta_item_value_from_list(link_metas, "name")
    }
}

#[test]
fn should_extract_crate_name_from_link_attribute() {
    let source = "#[link(name = \"snuggles\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == some("snuggles");
}

#[test]
fn should_not_extract_crate_name_if_no_link_attribute() {
    let source = "";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == none;
}

#[test]
fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() {
    let source = "#[link(whatever)]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == none;
}

fn parse_basic(
    attrs: [ast::attribute]
) -> {
    brief: option<str>,
    desc: option<str>
} {
    parse_short_doc_or(
        attrs,
        {|desc|
            {
                brief: none,
                desc: desc
            }
        },
        {|_items, brief, desc|
            {
                brief: brief,
                desc: desc
            }
        }
    )
}

fn parse_mod(attrs: [ast::attribute]) -> mod_attrs {
    parse_basic(attrs)
}

#[test]
fn parse_mod_should_handle_undocumented_mods() {
    let source = "";
    let attrs = test::parse_attributes(source);
    let attrs = parse_mod(attrs);
    assert attrs.brief == none;
    assert attrs.desc == none;
}

#[test]
fn parse_mod_should_parse_simple_doc_attributes() {
    let source = "#[doc = \"basic\"]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_mod(attrs);
    assert attrs.desc == some("basic");
}

#[test]
fn parse_mod_should_parse_the_brief_description() {
    let source = "#[doc(brief = \"short\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_mod(attrs);
    assert attrs.brief == some("short");
}

#[test]
fn parse_mod_should_parse_the_long_description() {
    let source = "#[doc(desc = \"description\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_mod(attrs);
    assert attrs.desc == some("description");
}

fn parse_short_doc_or<T>(
    attrs: [ast::attribute],
    handle_short: fn&(
        short_desc: option<str>
    ) -> T,
    parse_long: fn&(
        doc_items: [@ast::meta_item],
        brief: option<str>,
        desc: option<str>
    ) -> T
) -> T {
    alt doc_meta(attrs) {
      some(meta) {
        alt attr::get_meta_item_value_str(meta) {
          some(desc) { handle_short(some(desc)) }
          none {
            alt attr::get_meta_item_list(meta) {
              some(list) {
                let brief = attr::meta_item_value_from_list(list, "brief");
                let desc = attr::meta_item_value_from_list(list, "desc");
                parse_long(list, brief, desc)
              }
              none {
                handle_short(none)
              }
            }
          }
        }
      }
      none {
        handle_short(none)
      }
    }
}

fn parse_fn(
    attrs: [ast::attribute]
) -> fn_attrs {

    parse_short_doc_or(
        attrs,
        {|desc|
            {
                brief: none,
                desc: desc,
                args: [],
                return: none,
                failure: none
            }
        },
        parse_fn_long_doc
    )
}

fn parse_fn_long_doc(
    items: [@ast::meta_item],
    brief: option<str>,
    desc: option<str>
) -> fn_attrs {
    let return = attr::meta_item_value_from_list(items, "return");
    let failure = attr::meta_item_value_from_list(items, "failure");
    let args = alt attr::meta_item_list_from_list(items, "args") {
      some(items) {
        vec::filter_map(items) {|item|
            option::map(attr::name_value_str_pair(item)) { |pair|
                {
                    name: tuple::first(pair),
                    desc: tuple::second(pair)
                }
            }
        }
      }
      none { [] }
    };

    {
        brief: brief,
        desc: desc,
        args: args,
        return: return,
        failure: failure
    }
}

#[test]
fn parse_fn_should_handle_undocumented_functions() {
    let source = "";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.brief == none;
    assert attrs.desc == none;
    assert attrs.return == none;
    assert vec::len(attrs.args) == 0u;
}

#[test]
fn parse_fn_should_parse_simple_doc_attributes() {
    let source = "#[doc = \"basic\"]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.desc == some("basic");
}

#[test]
fn parse_fn_should_parse_the_brief_description() {
    let source = "#[doc(brief = \"short\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.brief == some("short");
}

#[test]
fn parse_fn_should_parse_the_long_description() {
    let source = "#[doc(desc = \"description\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.desc == some("description");
}

#[test]
fn parse_fn_should_parse_the_return_value_description() {
    let source = "#[doc(return = \"return value\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.return == some("return value");
}

#[test]
fn parse_fn_should_parse_the_argument_descriptions() {
    let source = "#[doc(args(a = \"arg a\", b = \"arg b\"))]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.args[0] == {name: "a", desc: "arg a"};
    assert attrs.args[1] == {name: "b", desc: "arg b"};
}

#[test]
fn parse_fn_should_parse_failure_conditions() {
    let source = "#[doc(failure = \"it's the fail\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_fn(attrs);
    assert attrs.failure == some("it's the fail");
}

fn parse_const(attrs: [ast::attribute]) -> const_attrs {
    parse_basic(attrs)
}

#[test]
fn should_parse_const_short_doc() {
    let source = "#[doc = \"description\"]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_const(attrs);
    assert attrs.desc == some("description");
}

#[test]
fn should_parse_const_long_doc() {
    let source = "#[doc(brief = \"a\", desc = \"b\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_const(attrs);
    assert attrs.brief == some("a");
    assert attrs.desc == some("b");
}

fn parse_enum(attrs: [ast::attribute]) -> enum_attrs {
    parse_basic(attrs)
}

#[test]
fn should_parse_enum_short_doc() {
    let source = "#[doc = \"description\"]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_enum(attrs);
    assert attrs.desc == some("description");
}

#[test]
fn should_parse_enum_long_doc() {
    let source = "#[doc(brief = \"a\", desc = \"b\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_enum(attrs);
    assert attrs.brief == some("a");
    assert attrs.desc == some("b");
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 crate::ir::attrs::BaseAttrsNode;
use crate::ir::PrimExpr;
use crate::runtime::array::Array;
use crate::runtime::DataType;
use crate::runtime::String as TString;
use tvm_macros::Object;

type IndexExpr = PrimExpr;

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "Conv2DAttrs"]
#[type_key = "relay.attrs.Conv2DAttrs"]
pub struct Conv2DAttrsNode {
    pub base: BaseAttrsNode,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    // TODO(@gussmith23) groups is "int", what should it be here?
    pub groups: i32,
    pub channels: IndexExpr,
    pub kernel_size: Array<IndexExpr>,
    pub data_layout: TString,
    pub kernel_layout: TString,
    pub out_layout: TString,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "BiasAddAttrs"]
#[type_key = "relay.attrs.BiasAddAttrs"]
pub struct BiasAddAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "MatmulAttrs"]
#[type_key = "relay.attrs.MatmulAttrs"]
pub struct MatmulAttrsNode {
    pub base: BaseAttrsNode,
    pub units: IndexExpr,
    pub out_dtype: DataType,
    pub transpose_a: bool,
    pub transpose_b: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "DenseAttrs"]
#[type_key = "relay.attrs.DenseAttrs"]
pub struct DenseAttrsNode {
    pub base: BaseAttrsNode,
    pub units: IndexExpr,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "GlobalPool2DAttrs"]
#[type_key = "relay.attrs.GlobalPool2DAttrs"]
pub struct GlobalPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub layout: TString,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "MaxPool2DAttrs"]
#[type_key = "relay.attrs.MaxPool2DAttrs"]
pub struct MaxPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub pool_size: Array<IndexExpr>,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub layout: TString,
    pub ceil_mode: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "SoftmaxAttrs"]
#[type_key = "relay.attrs.SoftmaxAttrs"]
pub struct SoftmaxAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "BatchNormAttrs"]
#[type_key = "relay.attrs.BatchNormAttrs"]
pub struct BatchNormAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
    pub epsilon: f64,
    pub center: bool,
    pub scale: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "LeakyReluAttrs"]
#[type_key = "relay.attrs.LeakyReluAttrs"]
pub struct LeakyReluAttrsNode {
    pub base: BaseAttrsNode,
    pub alpha: f64,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "AvgPool2DAttrs"]
#[type_key = "relay.attrs.AvgPool2DAttrs"]
pub struct AvgPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub pool_size: Array<IndexExpr>,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub layout: TString,
    pub ceil_mode: bool,
    pub count_include_pad: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "UpSamplingAttrs"]
#[type_key = "relay.attrs.UpSamplingAttrs"]
pub struct UpSamplingAttrsNode {
    pub base: BaseAttrsNode,
    pub scale_h: f64,
    pub scale_w: f64,
    pub layout: TString,
    pub method: TString,
    pub align_corners: bool,
}
<commit_msg>Add dilation to MaxPool2DAttrs Rust bindings (#9215)<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 crate::ir::attrs::BaseAttrsNode;
use crate::ir::PrimExpr;
use crate::runtime::array::Array;
use crate::runtime::DataType;
use crate::runtime::String as TString;
use tvm_macros::Object;

type IndexExpr = PrimExpr;

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "Conv2DAttrs"]
#[type_key = "relay.attrs.Conv2DAttrs"]
pub struct Conv2DAttrsNode {
    pub base: BaseAttrsNode,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    // TODO(@gussmith23) groups is "int", what should it be here?
    pub groups: i32,
    pub channels: IndexExpr,
    pub kernel_size: Array<IndexExpr>,
    pub data_layout: TString,
    pub kernel_layout: TString,
    pub out_layout: TString,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "BiasAddAttrs"]
#[type_key = "relay.attrs.BiasAddAttrs"]
pub struct BiasAddAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "MatmulAttrs"]
#[type_key = "relay.attrs.MatmulAttrs"]
pub struct MatmulAttrsNode {
    pub base: BaseAttrsNode,
    pub units: IndexExpr,
    pub out_dtype: DataType,
    pub transpose_a: bool,
    pub transpose_b: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "DenseAttrs"]
#[type_key = "relay.attrs.DenseAttrs"]
pub struct DenseAttrsNode {
    pub base: BaseAttrsNode,
    pub units: IndexExpr,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "GlobalPool2DAttrs"]
#[type_key = "relay.attrs.GlobalPool2DAttrs"]
pub struct GlobalPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub layout: TString,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "MaxPool2DAttrs"]
#[type_key = "relay.attrs.MaxPool2DAttrs"]
pub struct MaxPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub pool_size: Array<IndexExpr>,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    pub layout: TString,
    pub ceil_mode: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "SoftmaxAttrs"]
#[type_key = "relay.attrs.SoftmaxAttrs"]
pub struct SoftmaxAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "BatchNormAttrs"]
#[type_key = "relay.attrs.BatchNormAttrs"]
pub struct BatchNormAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
    pub epsilon: f64,
    pub center: bool,
    pub scale: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "LeakyReluAttrs"]
#[type_key = "relay.attrs.LeakyReluAttrs"]
pub struct LeakyReluAttrsNode {
    pub base: BaseAttrsNode,
    pub alpha: f64,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "AvgPool2DAttrs"]
#[type_key = "relay.attrs.AvgPool2DAttrs"]
pub struct AvgPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub pool_size: Array<IndexExpr>,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub layout: TString,
    pub ceil_mode: bool,
    pub count_include_pad: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "UpSamplingAttrs"]
#[type_key = "relay.attrs.UpSamplingAttrs"]
pub struct UpSamplingAttrsNode {
    pub base: BaseAttrsNode,
    pub scale_h: f64,
    pub scale_w: f64,
    pub layout: TString,
    pub method: TString,
    pub align_corners: bool,
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 crate::ir::attrs::BaseAttrsNode;
use crate::ir::PrimExpr;
use crate::runtime::array::Array;
use crate::runtime::DataType;
use crate::runtime::String as TString;
use tvm_macros::Object;

type IndexExpr = PrimExpr;

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "PadAttrs"]
#[type_key = "relay.attrs.PadAttrs"]
pub struct PadAttrsNode {
    pub base: BaseAttrsNode,
    pub pad_width: Array<Array<IndexExpr>>,
    pub pad_mode: TString,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "Conv1DAttrs"]
#[type_key = "relay.attrs.Conv1DAttrs"]
pub struct Conv1DAttrsNode {
    pub base: BaseAttrsNode,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    // TODO(@gussmith23) groups is "int", what should it be here?
    pub groups: i32,
    pub channels: IndexExpr,
    pub kernel_size: Array<IndexExpr>,
    pub data_layout: TString,
    pub kernel_layout: TString,
    pub out_layout: TString,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "Conv2DAttrs"]
#[type_key = "relay.attrs.Conv2DAttrs"]
pub struct Conv2DAttrsNode {
    pub base: BaseAttrsNode,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    // TODO(@gussmith23) groups is "int", what should it be here?
    pub groups: i32,
    pub channels: IndexExpr,
    pub kernel_size: Array<IndexExpr>,
    pub data_layout: TString,
    pub kernel_layout: TString,
    pub out_layout: TString,
    pub auto_scheduler_rewritten_layout: TString,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "BiasAddAttrs"]
#[type_key = "relay.attrs.BiasAddAttrs"]
pub struct BiasAddAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "MatmulAttrs"]
#[type_key = "relay.attrs.MatmulAttrs"]
pub struct MatmulAttrsNode {
    pub base: BaseAttrsNode,
    pub units: IndexExpr,
    pub out_dtype: DataType,
    pub transpose_a: bool,
    pub transpose_b: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "DenseAttrs"]
#[type_key = "relay.attrs.DenseAttrs"]
pub struct DenseAttrsNode {
    pub base: BaseAttrsNode,
    pub units: IndexExpr,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "GlobalPool2DAttrs"]
#[type_key = "relay.attrs.GlobalPool2DAttrs"]
pub struct GlobalPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub layout: TString,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "MaxPool2DAttrs"]
#[type_key = "relay.attrs.MaxPool2DAttrs"]
pub struct MaxPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub pool_size: Array<IndexExpr>,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    pub layout: TString,
    pub ceil_mode: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "SoftmaxAttrs"]
#[type_key = "relay.attrs.SoftmaxAttrs"]
pub struct SoftmaxAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "BatchNormAttrs"]
#[type_key = "relay.attrs.BatchNormAttrs"]
pub struct BatchNormAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
    pub epsilon: f64,
    pub center: bool,
    pub scale: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "LeakyReluAttrs"]
#[type_key = "relay.attrs.LeakyReluAttrs"]
pub struct LeakyReluAttrsNode {
    pub base: BaseAttrsNode,
    pub alpha: f64,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "AvgPool2DAttrs"]
#[type_key = "relay.attrs.AvgPool2DAttrs"]
pub struct AvgPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub pool_size: Array<IndexExpr>,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    pub layout: TString,
    pub ceil_mode: bool,
    pub count_include_pad: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "UpSamplingAttrs"]
#[type_key = "relay.attrs.UpSamplingAttrs"]
pub struct UpSamplingAttrsNode {
    pub base: BaseAttrsNode,
    pub scale_h: f64,
    pub scale_w: f64,
    pub layout: TString,
    pub method: TString,
    pub align_corners: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "DropoutAttrs"]
#[type_key = "relay.attrs.DropoutAttrs"]
pub struct DropoutAttrsNode {
    pub base: BaseAttrsNode,
    pub rate: f64,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "BatchMatmulAttrs"]
#[type_key = "relay.attrs.BatchMatmulAttrs"]
pub struct BatchMatmulAttrsNode {
    pub base: BaseAttrsNode,
    pub auto_scheduler_rewritten_layout: TString,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "LayerNormAttrs"]
#[type_key = "relay.attrs.LayerNormAttrs"]
pub struct LayerNormAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
    pub epsilon: f64,
    pub center: bool,
    pub scale: bool,
}
<commit_msg>Update nn.rs (#10063)<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 crate::ir::attrs::BaseAttrsNode;
use crate::ir::PrimExpr;
use crate::runtime::array::Array;
use crate::runtime::DataType;
use crate::runtime::String as TString;
use tvm_macros::Object;

type IndexExpr = PrimExpr;

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "PadAttrs"]
#[type_key = "relay.attrs.PadAttrs"]
pub struct PadAttrsNode {
    pub base: BaseAttrsNode,
    pub pad_width: Array<Array<IndexExpr>>,
    pub pad_mode: TString,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "Conv1DAttrs"]
#[type_key = "relay.attrs.Conv1DAttrs"]
pub struct Conv1DAttrsNode {
    pub base: BaseAttrsNode,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    // TODO(@gussmith23) groups is "int", what should it be here?
    pub groups: i32,
    pub channels: IndexExpr,
    pub kernel_size: Array<IndexExpr>,
    pub data_layout: TString,
    pub kernel_layout: TString,
    pub out_layout: TString,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "Conv2DAttrs"]
#[type_key = "relay.attrs.Conv2DAttrs"]
pub struct Conv2DAttrsNode {
    pub base: BaseAttrsNode,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    // TODO(@gussmith23) groups is "int", what should it be here?
    pub groups: i32,
    pub channels: IndexExpr,
    pub kernel_size: Array<IndexExpr>,
    pub data_layout: TString,
    pub kernel_layout: TString,
    pub out_layout: TString,
    pub auto_scheduler_rewritten_layout: TString,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "BiasAddAttrs"]
#[type_key = "relay.attrs.BiasAddAttrs"]
pub struct BiasAddAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "MatmulAttrs"]
#[type_key = "relay.attrs.MatmulAttrs"]
pub struct MatmulAttrsNode {
    pub base: BaseAttrsNode,
    pub units: IndexExpr,
    pub out_dtype: DataType,
    pub transpose_a: bool,
    pub transpose_b: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "DenseAttrs"]
#[type_key = "relay.attrs.DenseAttrs"]
pub struct DenseAttrsNode {
    pub base: BaseAttrsNode,
    pub units: IndexExpr,
    pub auto_scheduler_rewritten_layout: TString,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "GlobalPool2DAttrs"]
#[type_key = "relay.attrs.GlobalPool2DAttrs"]
pub struct GlobalPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub layout: TString,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "MaxPool2DAttrs"]
#[type_key = "relay.attrs.MaxPool2DAttrs"]
pub struct MaxPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub pool_size: Array<IndexExpr>,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    pub layout: TString,
    pub ceil_mode: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "SoftmaxAttrs"]
#[type_key = "relay.attrs.SoftmaxAttrs"]
pub struct SoftmaxAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "BatchNormAttrs"]
#[type_key = "relay.attrs.BatchNormAttrs"]
pub struct BatchNormAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
    pub epsilon: f64,
    pub center: bool,
    pub scale: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "LeakyReluAttrs"]
#[type_key = "relay.attrs.LeakyReluAttrs"]
pub struct LeakyReluAttrsNode {
    pub base: BaseAttrsNode,
    pub alpha: f64,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "AvgPool2DAttrs"]
#[type_key = "relay.attrs.AvgPool2DAttrs"]
pub struct AvgPool2DAttrsNode {
    pub base: BaseAttrsNode,
    pub pool_size: Array<IndexExpr>,
    pub strides: Array<IndexExpr>,
    pub padding: Array<IndexExpr>,
    pub dilation: Array<IndexExpr>,
    pub layout: TString,
    pub ceil_mode: bool,
    pub count_include_pad: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "UpSamplingAttrs"]
#[type_key = "relay.attrs.UpSamplingAttrs"]
pub struct UpSamplingAttrsNode {
    pub base: BaseAttrsNode,
    pub scale_h: f64,
    pub scale_w: f64,
    pub layout: TString,
    pub method: TString,
    pub align_corners: bool,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "DropoutAttrs"]
#[type_key = "relay.attrs.DropoutAttrs"]
pub struct DropoutAttrsNode {
    pub base: BaseAttrsNode,
    pub rate: f64,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "BatchMatmulAttrs"]
#[type_key = "relay.attrs.BatchMatmulAttrs"]
pub struct BatchMatmulAttrsNode {
    pub base: BaseAttrsNode,
    pub auto_scheduler_rewritten_layout: TString,
    pub out_dtype: DataType,
}

#[repr(C)]
#[derive(Object, Debug)]
#[ref_name = "LayerNormAttrs"]
#[type_key = "relay.attrs.LayerNormAttrs"]
pub struct LayerNormAttrsNode {
    pub base: BaseAttrsNode,
    pub axis: i32,
    pub epsilon: f64,
    pub center: bool,
    pub scale: bool,
}
<|endoftext|>