<commit_before>use petgraph::Direction;
use petgraph::graph::{Graph, NodeIndex};
use petgraph::visit::EdgeRef;
use std::cell::Cell;
use std::collections::HashMap;

use parser::ast::Identifier;

pub mod errors {
    use super::Symbol;

    error_chain! {
        errors {
            CannotExitGlobalScope {
                description("cannot exit global scope")
            }
            ScopeAlreadyExists(scope: String) {
                description("scope already exists")
                display("scope already exists: `{}`", scope)
            }
            ScopeDoesNotExist(scope: String) {
                description("scope does not exist")
                display("scope does not exist: `{}`", scope)
            }
            SymbolAlreadyExists(symbol: Symbol) {
                description("symbol already exists")
                display("symbol already exists: `{:?}`", symbol)
            }
        }
    }
}

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Symbol {
    pub name: Identifier,
    pub type_: SymbolType,
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum SymbolType {
    Argument,
    Callback,
    CallbackInterface,
    Const,
    Enum,
    ExtendedAttributeArgumentList,
    Iterable,
    Maplike,
    NonPartialDictionary,
    NonPartialInterface,
    NonPartialNamespace,
    PartialDictionary,
    PartialNamespace,
    PartialInterface,
    RegularAttribute,
    RegularOperation,
    Setlike,
    SpecialOperation,
    StaticAttribute,
    StaticOperation,
    StringifierAttribute,
    StringifierOperation,
    Typedef,
}

type SymbolNode = HashMap<Identifier, Symbol>;

#[derive(Clone, Debug)]
pub struct SymbolTable {
    current_scope: Cell<NodeIndex>,
    scope_tree: Graph<SymbolNode, Identifier>,
}

impl SymbolTable {
    pub fn new() -> Self {
        let mut scope_tree = Graph::<SymbolNode, Identifier>::new();
        let current_scope = Cell::new(scope_tree.add_node(HashMap::new()));

        SymbolTable {
            current_scope,
            scope_tree,
        }
    }

    pub fn create_scope(&mut self, name: Identifier) -> errors::Result<()> {
        if !self.does_child_scope_exist(&*name) {
            return Err(errors::ErrorKind::ScopeAlreadyExists(name).into());
        }

        let new_scope = self.scope_tree.add_node(HashMap::new());
        self.scope_tree.add_edge(
            self.current_scope.get(),
            new_scope,
            name,
        );
        Ok(())
    }

    pub fn does_child_scope_exist(&self, name: &str) -> bool {
        self.find_child_scope(name, self.current_scope.get())
            .is_some()
    }

    pub fn enter_scope(&self, name: &str) -> errors::Result<()> {
        match self.find_child_scope(name, self.current_scope.get()) {
            Some(child_scope) => {
                self.current_scope.set(child_scope);
                Ok(())
            }
            None => Err(
                errors::ErrorKind::ScopeDoesNotExist(name.to_string()).into(),
            ),
        }
    }

    pub fn exit_scope(&self) -> errors::Result<()> {
        match self.get_parent_scope(self.current_scope.get()) {
            Some(parent_scope) => {
                self.current_scope.set(parent_scope);
                Ok(())
            }
            None => Err(errors::ErrorKind::CannotExitGlobalScope.into()),
        }
    }

    pub fn insert_symbol(&mut self, name: Identifier, symbol: Symbol) -> errors::Result<()> {
        let current_scope = self.current_scope.get();
        let symbol_node = self.get_symbol_node_mut(current_scope);
        symbol_node.insert(name, symbol).map(|symbol| ()).ok_or(
            errors::ErrorKind::SymbolAlreadyExists(symbol).into(),
        )
    }

    pub fn lookup_local_symbol(&self, name: &str) -> Option<&Symbol> {
        self.get_symbol_node(self.current_scope.get()).get(name)
    }

    pub fn lookup_symbol(&self, name: &str) -> Option<&Symbol> {
        let mut current_scope = self.current_scope.get();

        loop {
            let symbol_node = self.get_symbol_node(current_scope);

            if let Some(symbol) = symbol_node.get(name) {
                return Some(symbol);
            }

            match self.get_parent_scope(current_scope) {
                Some(parent_scope) => current_scope = parent_scope,
                None => return None,
            }
        }
    }

    fn find_child_scope(&self, name: &str, scope: NodeIndex) -> Option<NodeIndex> {
        let edge = self.scope_tree
            .edges_directed(scope, Direction::Outgoing)
            .find(|edge| edge.weight() == name);

        edge.map(|edge| edge.target())
    }

    fn get_parent_scope(&self, scope: NodeIndex) -> Option<NodeIndex> {
        let edge = self.scope_tree
            .edges_directed(scope, Direction::Incoming)
            .nth(0);

        edge.map(|edge| edge.target())
    }

    fn get_symbol_node(&self, scope: NodeIndex) -> &SymbolNode {
        self.scope_tree.node_weight(scope).expect(
            "\"scope\" must reference an existing symbol node",
        )
    }

    fn get_symbol_node_mut(&mut self, scope: NodeIndex) -> &mut SymbolNode {
        self.scope_tree.node_weight_mut(scope).expect(
            "\"scope\" must reference an existing symbol node",
        )
    }
}
<commit_msg>fix symbol table insertion<commit_after>use petgraph::Direction;
use petgraph::graph::{Graph, NodeIndex};
use petgraph::visit::EdgeRef;
use std::cell::Cell;
use std::collections::HashMap;

use parser::ast::Identifier;

pub mod errors {
    use super::Symbol;

    error_chain! {
        errors {
            CannotExitGlobalScope {
                description("cannot exit global scope")
            }
            ScopeAlreadyExists(scope: String) {
                description("scope already exists")
                display("scope already exists: `{}`", scope)
            }
            ScopeDoesNotExist(scope: String) {
                description("scope does not exist")
                display("scope does not exist: `{}`", scope)
            }
            SymbolAlreadyExists(symbol: Symbol) {
                description("symbol already exists")
                display("symbol already exists: `{:?}`", symbol)
            }
        }
    }
}

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Symbol {
    pub name: Identifier,
    pub type_: SymbolType,
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum SymbolType {
    Argument,
    Callback,
    CallbackInterface,
    Const,
    Enum,
    ExtendedAttributeArgumentList,
    Iterable,
    Maplike,
    NonPartialDictionary,
    NonPartialInterface,
    NonPartialNamespace,
    PartialDictionary,
    PartialNamespace,
    PartialInterface,
    RegularAttribute,
    RegularOperation,
    Setlike,
    SpecialOperation,
    StaticAttribute,
    StaticOperation,
    StringifierAttribute,
    StringifierOperation,
    Typedef,
}

type SymbolNode = HashMap<Identifier, Symbol>;

#[derive(Clone, Debug)]
pub struct SymbolTable {
    current_scope: Cell<NodeIndex>,
    scope_tree: Graph<SymbolNode, Identifier>,
}

impl SymbolTable {
    pub fn new() -> Self {
        let mut scope_tree = Graph::<SymbolNode, Identifier>::new();
        let current_scope = Cell::new(scope_tree.add_node(HashMap::new()));

        SymbolTable {
            current_scope,
            scope_tree,
        }
    }

    pub fn create_scope(&mut self, name: Identifier) -> errors::Result<()> {
        if !self.does_child_scope_exist(&*name) {
            return Err(errors::ErrorKind::ScopeAlreadyExists(name).into());
        }

        let new_scope = self.scope_tree.add_node(HashMap::new());
        self.scope_tree.add_edge(
            self.current_scope.get(),
            new_scope,
            name,
        );
        Ok(())
    }

    pub fn does_child_scope_exist(&self, name: &str) -> bool {
        self.find_child_scope(name, self.current_scope.get())
            .is_some()
    }

    pub fn enter_scope(&self, name: &str) -> errors::Result<()> {
        match self.find_child_scope(name, self.current_scope.get()) {
            Some(child_scope) => {
                self.current_scope.set(child_scope);
                Ok(())
            }
            None => Err(
                errors::ErrorKind::ScopeDoesNotExist(name.to_string()).into(),
            ),
        }
    }

    pub fn exit_scope(&self) -> errors::Result<()> {
        match self.get_parent_scope(self.current_scope.get()) {
            Some(parent_scope) => {
                self.current_scope.set(parent_scope);
                Ok(())
            }
            None => Err(errors::ErrorKind::CannotExitGlobalScope.into()),
        }
    }

    pub fn insert_symbol(&mut self, name: Identifier, symbol: Symbol) -> errors::Result<()> {
        let current_scope = self.current_scope.get();
        let symbol_node = self.get_symbol_node_mut(current_scope);

        match symbol_node.insert(name, symbol) {
            Some(old_symbol) => Err(errors::ErrorKind::SymbolAlreadyExists(old_symbol).into()),
            None => Ok(()),
        }
    }

    pub fn lookup_local_symbol(&self, name: &str) -> Option<&Symbol> {
        self.get_symbol_node(self.current_scope.get()).get(name)
    }

    pub fn lookup_symbol(&self, name: &str) -> Option<&Symbol> {
        let mut current_scope = self.current_scope.get();

        loop {
            let symbol_node = self.get_symbol_node(current_scope);

            if let Some(symbol) = symbol_node.get(name) {
                return Some(symbol);
            }

            match self.get_parent_scope(current_scope) {
                Some(parent_scope) => current_scope = parent_scope,
                None => return None,
            }
        }
    }

    fn find_child_scope(&self, name: &str, scope: NodeIndex) -> Option<NodeIndex> {
        let edge = self.scope_tree
            .edges_directed(scope, Direction::Outgoing)
            .find(|edge| edge.weight() == name);

        edge.map(|edge| edge.target())
    }

    fn get_parent_scope(&self, scope: NodeIndex) -> Option<NodeIndex> {
        let edge = self.scope_tree
            .edges_directed(scope, Direction::Incoming)
            .nth(0);

        edge.map(|edge| edge.target())
    }

    fn get_symbol_node(&self, scope: NodeIndex) -> &SymbolNode {
        self.scope_tree.node_weight(scope).expect(
            "\"scope\" must reference an existing symbol node",
        )
    }

    fn get_symbol_node_mut(&mut self, scope: NodeIndex) -> &mut SymbolNode {
        self.scope_tree.node_weight_mut(scope).expect(
            "\"scope\" must reference an existing symbol node",
        )
    }
}
<|endoftext|>


<commit_before>#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate inf_4301a;

use std::str;

fuzz_target!(|data: &[u8]| {

    if let Ok(ref s) = str::from_utf8(data) {
        if let Ok(exprs) = inf_4301a::parse_expressions(&s) {
            if let Err(err) = inf_4301a::do_the_thing(exprs, &mut inf_4301a::env::Environment::new()) {
                inf_4301a::error::print_error("<fuzzer>", &s, err);
            }
        }
    }

});
<commit_msg>Update fuzzer script to previous commit's changes<commit_after>#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate inf_4301a;

use std::str;

fuzz_target!(|data: &[u8]| {

    if let Ok(ref s) = str::from_utf8(data) {
        if let Ok(exprs) = inf_4301a::parse_expressions(&s) {
            if let Err(err) = inf_4301a::do_the_thing(exprs, &mut inf_4301a::env::Environment::new()) {
                inf_4301a::error::print_error("<fuzzer>", &s, &err);
            }
        }
    }

});
<|endoftext|>


<commit_before>extern crate para_bm;

use std::time::Duration;
use std::thread::Thread;

use para_bm::{sleep_ns};

fn fast () {
    sleep_ns(1000);
}

fn slow () {
    sleep_ns(1000000);
}

fn my_bench<F> (f: F) where F: Fn() {

    // first "throw away" run
    let mut d = Duration::span(|| {
        f();
    });
    let ns = d.num_nanoseconds().unwrap();
    println!("num nano seconds first run {}", ns);

    let mut sum = 0;
    // iterate to get more cache hits, etc...
    for _ in 0 .. 10 {
        d = Duration::span(|| {
            f();
        });
        let ns = d.num_nanoseconds().unwrap();
        sum = sum + ns;
    }

    let avg = (sum as f64) / 10.0;
    println!("average after first run {}", avg);
}

fn main () {

    println!("Running Threaded slow");
    my_bench(||{
        Thread::scoped(move || {
            slow();
        });
    });

    println!("Running Non-Threaded fast");
    my_bench(||{
        fast()
    });

}
<commit_msg>multi-threaded<commit_after>extern crate para_bm;

use std::time::Duration;
use std::thread::Thread;

use para_bm::{sleep_ns};

fn fast () {
    sleep_ns(1000);
}

fn slow () {
    sleep_ns(1000000000);
}

fn my_bench<F> (f: F) where F: Fn() {

    // first "throw away" run
    let mut d = Duration::span(|| {
        f();
    });
    let ns = d.num_nanoseconds().unwrap();
    println!("num nano seconds first run {}", ns);

    let mut sum = 0;
    // iterate to get more cache hits, etc...
    for _ in 0 .. 10 {
        d = Duration::span(|| {
            f();
        });
        let ns = d.num_nanoseconds().unwrap();
        sum = sum + ns;
    }

    let avg = (sum as f64) / 10.0;
    println!("average after first run {}", avg);
}

fn main () {

    println!("Running Threaded slow");
    my_bench(||{
        let threads_holder = (0 .. 3).map(|ii| {
            Thread::scoped(move || {
                slow();
                println!("Done slow thread {}", ii);
            })
        }).collect::<Vec<_>>();
        println!("done spawning");
    });

    /*
    println!("Running Non-Threaded fast");
    my_bench(||{
        fast();
    });
    */

}
<|endoftext|>


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

// ignore-aarch64
#![feature(libc)]

extern crate libc;

use std::mem;
use std::thread;

#[link(name = "rust_test_helpers")]
extern {
    fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t),
                     data: libc::uintptr_t) -> libc::uintptr_t;
}

pub fn main() {
    unsafe {
        thread::spawn(move|| {
            let i = 100;
            rust_dbg_call(callback, mem::transmute(&i));
        }).join();
    }
}

extern fn callback(data: libc::uintptr_t) {
    unsafe {
        let data: *const isize = mem::transmute(data);
        assert_eq!(*data, 100);
    }
}
<commit_msg>Auto merge of #27914 - pnkfelix:fix-fcnr-for-valgrind, r=alexcrichton<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-aarch64
#![feature(libc)]

extern crate libc;

use std::mem;
use std::thread;

#[link(name = "rust_test_helpers")]
extern {
    fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t),
                     data: libc::uintptr_t) -> libc::uintptr_t;
}

pub fn main() {
    unsafe {
        thread::spawn(move|| {
            let i: isize = 100;
            rust_dbg_call(callback_isize, mem::transmute(&i));
        }).join().unwrap();

        thread::spawn(move|| {
            let i: i32 = 100;
            rust_dbg_call(callback_i32, mem::transmute(&i));
        }).join().unwrap();

        thread::spawn(move|| {
            let i: i64 = 100;
            rust_dbg_call(callback_i64, mem::transmute(&i));
        }).join().unwrap();
    }
}

extern fn callback_isize(data: libc::uintptr_t) {
    unsafe {
        let data: *const isize = mem::transmute(data);
        assert_eq!(*data, 100);
    }
}

extern fn callback_i64(data: libc::uintptr_t) {
    unsafe {
        let data: *const i64 = mem::transmute(data);
        assert_eq!(*data, 100);
    }
}

extern fn callback_i32(data: libc::uintptr_t) {
    unsafe {
        let data: *const i32 = mem::transmute(data);
        assert_eq!(*data, 100);
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 The Tink-Rust Authors
//
// 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::sync::Arc;
use tink::{
    keyset::{insecure, Handle},
    proto::{key_data::KeyMaterialType, KeyData},
    TinkError,
};

#[test]
fn test_new_handle() {
    tink_mac::init();
    let kt = tink_mac::hmac_sha256_tag128_key_template();
    let kh = Handle::new(&kt).unwrap();
    let ks = insecure::keyset_material(&kh);
    assert_eq!(1, ks.key.len(), "incorrect number of keys in the keyset");
    let key = ks.key[0].clone();
    assert_eq!(ks.primary_key_id, key.key_id, "incorrect primary key id");
    assert_eq!(
        key.key_data.unwrap().type_url,
        kt.type_url,
        "incorrect type url"
    );
    assert!(
        tink_mac::new(&kh).is_ok(),
        "cannot get primitive from generated keyset handle"
    );
}

#[test]
fn test_new_handle_with_invalid_input() {
    tink_mac::init();
    // template unregistered type_url
    let mut template = tink_mac::hmac_sha256_tag128_key_template();
    template.type_url = "some unknown type_url".to_string();
    assert!(
        Handle::new(&template).is_err(),
        "expect an error when type_url is not registered"
    );
}

#[test]
fn test_read() {
    let master_key = Box::new(tink_aead::subtle::AesGcm::new(&[b'A'; 32]).unwrap());

    // Create a keyset
    let key_data = tink_testutil::new_key_data(
        "some type url",
        &[42, 42, 0x42, 0x42, 0o42, 0o42], // 42 in all possible formats
        KeyMaterialType::Symmetric,
    );
    let key = tink_testutil::new_key(
        &key_data,
        tink::proto::KeyStatusType::Enabled,
        1,
        tink::proto::OutputPrefixType::Tink,
    );
    let ks = tink_testutil::new_keyset(1, vec![key]);
    let h = insecure::new_handle(ks).unwrap();

    // Also check that debug output of handle doesn't include key material.
    let debug_output = format!("{:?}", h);
    assert!(!debug_output.contains("42"));

    let mem_keyset = &mut tink::keyset::MemReaderWriter::default();
    assert!(h.write(mem_keyset, master_key.clone()).is_ok());
    let h2 = Handle::read(mem_keyset, master_key).unwrap();
    assert_eq!(
        insecure::keyset_material(&h),
        insecure::keyset_material(&h2),
        "Decrypt failed: got {:?}, want {:?}",
        h2,
        h
    );
}

#[test]
fn test_read_with_no_secrets() {
    // Create a keyset containing public key material
    let key_data =
        tink_testutil::new_key_data("some type url", &[0], KeyMaterialType::AsymmetricPublic);
    let key = tink_testutil::new_key(
        &key_data,
        tink::proto::KeyStatusType::Enabled,
        1,
        tink::proto::OutputPrefixType::Tink,
    );
    let ks = tink_testutil::new_keyset(1, vec![key]);
    let h = insecure::new_handle(ks).unwrap();

    let mem_keyset = &mut tink::keyset::MemReaderWriter::default();
    assert!(h.write_with_no_secrets(mem_keyset).is_ok());
    let h2 = Handle::read_with_no_secrets(mem_keyset).unwrap();

    assert_eq!(
        insecure::keyset_material(&h),
        insecure::keyset_material(&h2),
        "Decrypt failed: got {:?}, want {:?}",
        h2,
        h
    );
}

#[test]
fn test_with_no_secrets_functions_fail_when_handling_secret_key_material() {
    // Create a keyset containing secret key material (symmetric)
    let key_data = tink_testutil::new_key_data("some type url", &[0], KeyMaterialType::Symmetric);
    let key = tink_testutil::new_key(
        &key_data,
        tink::proto::KeyStatusType::Enabled,
        1,
        tink::proto::OutputPrefixType::Tink,
    );
    let ks = tink_testutil::new_keyset(1, vec![key]);
    let h = insecure::new_handle(ks).unwrap();

    assert!(
        h.write_with_no_secrets(&mut tink::keyset::MemReaderWriter::default())
            .is_err(),
        "handle.write_with_no_secrets() should fail when exporting secret key material"
    );

    assert!(
        Handle::read_with_no_secrets(&mut tink::keyset::MemReaderWriter {
            keyset: Some(insecure::keyset_material(&h)),
            ..Default::default()
        })
        .is_err(),
        "keyset.read_with_no_secrets should fail when importing secret key material"
    );
}

#[test]
fn test_with_no_secrets_functions_fail_when_unknown_key_material() {
    // Create a keyset containing secret key material (symmetric)
    let key_data =
        tink_testutil::new_key_data("some type url", &[0], KeyMaterialType::UnknownKeymaterial);
    let key = tink_testutil::new_key(
        &key_data,
        tink::proto::KeyStatusType::Enabled,
        1,
        tink::proto::OutputPrefixType::Tink,
    );
    let ks = tink_testutil::new_keyset(1, vec![key]);
    let h = insecure::new_handle(ks).unwrap();

    assert!(
        h.write_with_no_secrets(&mut tink::keyset::MemReaderWriter::default())
            .is_err(),
        "handle.write_with_no_secrets() should fail when exporting secret key material"
    );

    assert!(
        Handle::read_with_no_secrets(&mut tink::keyset::MemReaderWriter {
            keyset: Some(insecure::keyset_material(&h)),
            ..Default::default()
        })
        .is_err(),
        "keyset.read_with_no_secrets should fail when importing secret key material"
    );
}

#[test]
fn test_with_no_secrets_functions_fail_with_asymmetric_private_key_material() {
    // Create a keyset containing secret key material (asymmetric)
    let key_data =
        tink_testutil::new_key_data("some type url", &[0], KeyMaterialType::AsymmetricPrivate);
    let key = tink_testutil::new_key(
        &key_data,
        tink::proto::KeyStatusType::Enabled,
        1,
        tink::proto::OutputPrefixType::Tink,
    );
    let ks = tink_testutil::new_keyset(1, vec![key]);
    let h = insecure::new_handle(ks).unwrap();

    assert!(
        h.write_with_no_secrets(&mut tink::keyset::MemReaderWriter::default())
            .is_err(),
        "handle.write_with_no_secrets() should fail when exporting secret key material"
    );

    assert!(
        Handle::read_with_no_secrets(&mut tink::keyset::MemReaderWriter {
            keyset: Some(insecure::keyset_material(&h)),
            ..Default::default()
        })
        .is_err(),
        "keyset.read_with_no_secrets should fail when importing secret key material"
    );
}

#[test]
fn test_keyset_info() {
    tink_mac::init();
    let kt = tink_mac::hmac_sha256_tag128_key_template();
    let kh = tink::keyset::Handle::new(&kt).unwrap();
    let info = kh.keyset_info();
    assert_eq!(info.primary_key_id, info.key_info[0].key_id);
}

#[test]
fn test_invalid_keyset() {
    tink_mac::init();
    let kt = tink_mac::hmac_sha256_tag128_key_template();
    let kh = Handle::new(&kt).unwrap();

    let mut invalid_ks = insecure::keyset_material(&kh);
    invalid_ks.key[0].key_data = None;
    assert!(insecure::new_handle(invalid_ks).is_err());

    let mut invalid_ks = insecure::keyset_material(&kh);
    invalid_ks.key.clear();
    assert!(insecure::new_handle(invalid_ks).is_err());
}

#[test]
fn test_invalid_keyset_from_manager() {
    // Use a key manager that generates invalid `KeyData`.
    pub struct InvalidKeyManager {}

    impl tink::registry::KeyManager for InvalidKeyManager {
        fn primitive(&self, _serialized_key: &[u8]) -> Result<tink::Primitive, TinkError> {
            Err("not implemented".into())
        }

        fn new_key(&self, _serialized_key_format: &[u8]) -> Result<Vec<u8>, TinkError> {
            Err("not implemented".into())
        }

        fn type_url(&self) -> &'static str {
            "InvalidKeyGenerator"
        }

        fn key_material_type(&self) -> KeyMaterialType {
            KeyMaterialType::Symmetric
        }

        fn new_key_data(&self, _serialized_key_format: &[u8]) -> Result<KeyData, TinkError> {
            Ok(KeyData {
                key_material_type: 9999,
                type_url: self.type_url().to_string(),
                value: vec![],
            })
        }
    }
    tink::registry::register_key_manager(Arc::new(InvalidKeyManager {})).unwrap();
    let kt = tink::proto::KeyTemplate {
        output_prefix_type: tink::proto::OutputPrefixType::Tink as i32,
        type_url: "InvalidKeyGenerator".to_string(),
        value: vec![],
    };

    assert!(tink::keyset::Handle::new(&kt).is_err());
}

#[test]
fn test_destroyed_key_keyset() {
    tink_mac::init();
    let kt = tink_mac::hmac_sha256_tag128_key_template();
    let kh = Handle::new(&kt).unwrap();

    let mut ks = insecure::keyset_material(&kh);
    ks.key[0].key_data = None;
    ks.key[0].status = tink::proto::KeyStatusType::Destroyed as i32;
    let kh = insecure::new_handle(ks).unwrap();
    let info = kh.keyset_info();
    assert_eq!(info.primary_key_id, info.key_info[0].key_id);
    // The type_url for a destroyed key is not available.
    assert_eq!(info.key_info[0].type_url, "");
}

#[test]
fn test_handle_public() {
    tink_signature::init();
    let kh = Handle::new(&tink_signature::ecdsa_p256_key_template()).unwrap();

    let kh_public = kh.public().unwrap();

    let ks = insecure::keyset_material(&kh_public);
    assert_eq!(
        ks.key[0].key_data.as_ref().unwrap().key_material_type,
        KeyMaterialType::AsymmetricPublic as i32
    );

    // handle.public() only works for asymmetric private keys.
    let result = kh_public.public();
    tink_testutil::expect_err(result, "contains a non-private key");
}

#[test]
fn test_handle_public_destroyed_key() {
    tink_signature::init();

    let mut ksm = tink::keyset::Manager::new();
    ksm.rotate(&tink_signature::ecdsa_p256_key_template())
        .unwrap();
    let key_id = ksm
        .add(
            &tink_signature::ecdsa_p256_key_template(),
            /* primary= */ false,
        )
        .unwrap();
    ksm.destroy(key_id).unwrap();
    let kh = ksm.handle().unwrap();

    let result = kh.public();
    tink_testutil::expect_err(result, "invalid keyset");
}

#[test]
fn test_handle_public_wrong_keymanager() {
    tink_mac::init();
    tink_signature::init();
    let kh = Handle::new(&tink_signature::ecdsa_p256_key_template()).unwrap();

    // Manually corrupt the keyset to refer to the wrong key manager.
    let mut ks = insecure::keyset_material(&kh);
    ks.key[0].key_data.as_mut().unwrap().type_url = tink_testutil::HMAC_TYPE_URL.to_string();
    let invalid_kh = insecure::new_handle(ks).unwrap();

    let result = invalid_kh.public();
    tink_testutil::expect_err(result, "handles private keys");
}
<commit_msg>tink::keyset: more MemReaderWriter tests<commit_after>// Copyright 2020 The Tink-Rust Authors
//
// 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::sync::Arc;
use tink::{
    keyset::{insecure, Handle},
    proto::{key_data::KeyMaterialType, KeyData},
    TinkError,
};

#[test]
fn test_new_handle() {
    tink_mac::init();
    let kt = tink_mac::hmac_sha256_tag128_key_template();
    let kh = Handle::new(&kt).unwrap();
    let ks = insecure::keyset_material(&kh);
    assert_eq!(1, ks.key.len(), "incorrect number of keys in the keyset");
    let key = ks.key[0].clone();
    assert_eq!(ks.primary_key_id, key.key_id, "incorrect primary key id");
    assert_eq!(
        key.key_data.unwrap().type_url,
        kt.type_url,
        "incorrect type url"
    );
    assert!(
        tink_mac::new(&kh).is_ok(),
        "cannot get primitive from generated keyset handle"
    );
}

#[test]
fn test_new_handle_with_invalid_input() {
    tink_mac::init();
    // template unregistered type_url
    let mut template = tink_mac::hmac_sha256_tag128_key_template();
    template.type_url = "some unknown type_url".to_string();
    assert!(
        Handle::new(&template).is_err(),
        "expect an error when type_url is not registered"
    );
}

#[test]
fn test_read() {
    let main_key = Box::new(tink_aead::subtle::AesGcm::new(&[b'A'; 32]).unwrap());

    // Create a keyset
    let key_data = tink_testutil::new_key_data(
        "some type url",
        &[42, 42, 0x42, 0x42, 0o42, 0o42], // 42 in all possible formats
        KeyMaterialType::Symmetric,
    );
    let key = tink_testutil::new_key(
        &key_data,
        tink::proto::KeyStatusType::Enabled,
        1,
        tink::proto::OutputPrefixType::Tink,
    );
    let ks = tink_testutil::new_keyset(1, vec![key]);
    let h = insecure::new_handle(ks).unwrap();

    // Also check that debug output of handle doesn't include key material.
    let debug_output = format!("{:?}", h);
    assert!(!debug_output.contains("42"));

    let mem_keyset = &mut tink::keyset::MemReaderWriter::default();
    assert!(h.write(mem_keyset, main_key.clone()).is_ok());
    let h2 = Handle::read(mem_keyset, main_key).unwrap();
    assert_eq!(
        insecure::keyset_material(&h),
        insecure::keyset_material(&h2),
        "Decrypt failed: got {:?}, want {:?}",
        h2,
        h
    );
}

#[test]
fn test_read_with_no_secrets() {
    // Create a keyset containing public key material
    let key_data =
        tink_testutil::new_key_data("some type url", &[0], KeyMaterialType::AsymmetricPublic);
    let key = tink_testutil::new_key(
        &key_data,
        tink::proto::KeyStatusType::Enabled,
        1,
        tink::proto::OutputPrefixType::Tink,
    );
    let ks = tink_testutil::new_keyset(1, vec![key]);
    let h = insecure::new_handle(ks).unwrap();

    let mem_keyset = &mut tink::keyset::MemReaderWriter::default();
    assert!(h.write_with_no_secrets(mem_keyset).is_ok());
    let h2 = Handle::read_with_no_secrets(mem_keyset).unwrap();

    assert_eq!(
        insecure::keyset_material(&h),
        insecure::keyset_material(&h2),
        "Decrypt failed: got {:?}, want {:?}",
        h2,
        h
    );
}

#[test]
fn test_with_no_secrets_functions_fail_when_handling_secret_key_material() {
    // Create a keyset containing secret key material (symmetric)
    let key_data = tink_testutil::new_key_data("some type url", &[0], KeyMaterialType::Symmetric);
    let key = tink_testutil::new_key(
        &key_data,
        tink::proto::KeyStatusType::Enabled,
        1,
        tink::proto::OutputPrefixType::Tink,
    );
    let ks = tink_testutil::new_keyset(1, vec![key]);
    let h = insecure::new_handle(ks).unwrap();

    assert!(
        h.write_with_no_secrets(&mut tink::keyset::MemReaderWriter::default())
            .is_err(),
        "handle.write_with_no_secrets() should fail when exporting secret key material"
    );

    assert!(
        Handle::read_with_no_secrets(&mut tink::keyset::MemReaderWriter {
            keyset: Some(insecure::keyset_material(&h)),
            ..Default::default()
        })
        .is_err(),
        "keyset.read_with_no_secrets should fail when importing secret key material"
    );
}

#[test]
fn test_with_no_secrets_functions_fail_when_unknown_key_material() {
    // Create a keyset containing secret key material (symmetric)
    let key_data =
        tink_testutil::new_key_data("some type url", &[0], KeyMaterialType::UnknownKeymaterial);
    let key = tink_testutil::new_key(
        &key_data,
        tink::proto::KeyStatusType::Enabled,
        1,
        tink::proto::OutputPrefixType::Tink,
    );
    let ks = tink_testutil::new_keyset(1, vec![key]);
    let h = insecure::new_handle(ks).unwrap();

    assert!(
        h.write_with_no_secrets(&mut tink::keyset::MemReaderWriter::default())
            .is_err(),
        "handle.write_with_no_secrets() should fail when exporting secret key material"
    );

    assert!(
        Handle::read_with_no_secrets(&mut tink::keyset::MemReaderWriter {
            keyset: Some(insecure::keyset_material(&h)),
            ..Default::default()
        })
        .is_err(),
        "keyset.read_with_no_secrets should fail when importing secret key material"
    );
}

#[test]
fn test_with_no_secrets_functions_fail_with_asymmetric_private_key_material() {
    // Create a keyset containing secret key material (asymmetric)
    let key_data =
        tink_testutil::new_key_data("some type url", &[0], KeyMaterialType::AsymmetricPrivate);
    let key = tink_testutil::new_key(
        &key_data,
        tink::proto::KeyStatusType::Enabled,
        1,
        tink::proto::OutputPrefixType::Tink,
    );
    let ks = tink_testutil::new_keyset(1, vec![key]);
    let h = insecure::new_handle(ks).unwrap();

    assert!(
        h.write_with_no_secrets(&mut tink::keyset::MemReaderWriter::default())
            .is_err(),
        "handle.write_with_no_secrets() should fail when exporting secret key material"
    );

    assert!(
        Handle::read_with_no_secrets(&mut tink::keyset::MemReaderWriter {
            keyset: Some(insecure::keyset_material(&h)),
            ..Default::default()
        })
        .is_err(),
        "keyset.read_with_no_secrets should fail when importing secret key material"
    );
}

#[test]
fn test_keyset_info() {
    tink_mac::init();
    let kt = tink_mac::hmac_sha256_tag128_key_template();
    let kh = tink::keyset::Handle::new(&kt).unwrap();
    let info = kh.keyset_info();
    assert_eq!(info.primary_key_id, info.key_info[0].key_id);
}

#[test]
fn test_invalid_keyset() {
    tink_mac::init();
    let kt = tink_mac::hmac_sha256_tag128_key_template();
    let kh = Handle::new(&kt).unwrap();

    let mut invalid_ks = insecure::keyset_material(&kh);
    invalid_ks.key[0].key_data = None;
    assert!(insecure::new_handle(invalid_ks).is_err());

    let mut invalid_ks = insecure::keyset_material(&kh);
    invalid_ks.key.clear();
    assert!(insecure::new_handle(invalid_ks).is_err());
}

#[test]
fn test_invalid_keyset_from_manager() {
    // Use a key manager that generates invalid `KeyData`.
    pub struct InvalidKeyManager {}

    impl tink::registry::KeyManager for InvalidKeyManager {
        fn primitive(&self, _serialized_key: &[u8]) -> Result<tink::Primitive, TinkError> {
            Err("not implemented".into())
        }

        fn new_key(&self, _serialized_key_format: &[u8]) -> Result<Vec<u8>, TinkError> {
            Err("not implemented".into())
        }

        fn type_url(&self) -> &'static str {
            "InvalidKeyGenerator"
        }

        fn key_material_type(&self) -> KeyMaterialType {
            KeyMaterialType::Symmetric
        }

        fn new_key_data(&self, _serialized_key_format: &[u8]) -> Result<KeyData, TinkError> {
            Ok(KeyData {
                key_material_type: 9999,
                type_url: self.type_url().to_string(),
                value: vec![],
            })
        }
    }
    tink::registry::register_key_manager(Arc::new(InvalidKeyManager {})).unwrap();
    let kt = tink::proto::KeyTemplate {
        output_prefix_type: tink::proto::OutputPrefixType::Tink as i32,
        type_url: "InvalidKeyGenerator".to_string(),
        value: vec![],
    };

    assert!(tink::keyset::Handle::new(&kt).is_err());
}

#[test]
fn test_destroyed_key_keyset() {
    tink_mac::init();
    let kt = tink_mac::hmac_sha256_tag128_key_template();
    let kh = Handle::new(&kt).unwrap();

    let mut ks = insecure::keyset_material(&kh);
    ks.key[0].key_data = None;
    ks.key[0].status = tink::proto::KeyStatusType::Destroyed as i32;
    let kh = insecure::new_handle(ks).unwrap();
    let info = kh.keyset_info();
    assert_eq!(info.primary_key_id, info.key_info[0].key_id);
    // The type_url for a destroyed key is not available.
    assert_eq!(info.key_info[0].type_url, "");
}

#[test]
fn test_handle_public() {
    tink_signature::init();
    let kh = Handle::new(&tink_signature::ecdsa_p256_key_template()).unwrap();

    let kh_public = kh.public().unwrap();

    let ks = insecure::keyset_material(&kh_public);
    assert_eq!(
        ks.key[0].key_data.as_ref().unwrap().key_material_type,
        KeyMaterialType::AsymmetricPublic as i32
    );

    // handle.public() only works for asymmetric private keys.
    let result = kh_public.public();
    tink_testutil::expect_err(result, "contains a non-private key");
}

#[test]
fn test_handle_public_destroyed_key() {
    tink_signature::init();

    let mut ksm = tink::keyset::Manager::new();
    ksm.rotate(&tink_signature::ecdsa_p256_key_template())
        .unwrap();
    let key_id = ksm
        .add(
            &tink_signature::ecdsa_p256_key_template(),
            /* primary= */ false,
        )
        .unwrap();
    ksm.destroy(key_id).unwrap();
    let kh = ksm.handle().unwrap();

    let result = kh.public();
    tink_testutil::expect_err(result, "invalid keyset");
}

#[test]
fn test_handle_public_wrong_keymanager() {
    tink_mac::init();
    tink_signature::init();
    let kh = Handle::new(&tink_signature::ecdsa_p256_key_template()).unwrap();

    // Manually corrupt the keyset to refer to the wrong key manager.
    let mut ks = insecure::keyset_material(&kh);
    ks.key[0].key_data.as_mut().unwrap().type_url = tink_testutil::HMAC_TYPE_URL.to_string();
    let invalid_kh = insecure::new_handle(ks).unwrap();

    let result = invalid_kh.public();
    tink_testutil::expect_err(result, "handles private keys");
}

#[test]
fn test_mem_read_with_no_secrets_empty() {
    let result = Handle::read_with_no_secrets(&mut tink::keyset::MemReaderWriter::default());
    tink_testutil::expect_err(result, "no keyset available");
}

#[test]
fn test_mem_read_empty() {
    let main_key = Box::new(tink_aead::subtle::AesGcm::new(&[b'A'; 32]).unwrap());
    let result = Handle::read(&mut tink::keyset::MemReaderWriter::default(), main_key);
    tink_testutil::expect_err(result, "no keyset available");
}
<|endoftext|>


<commit_before>use super::{GbaMemory, ROM_MAX_MASK};
use arm::{AccessType, Waitstates};
use byteorder::{ByteOrder, LittleEndian as LE};

impl GbaMemory {
    pub(super) fn load32_gamepak(
        &self,
        address: u32,
        waitstate: u8,
        access: AccessType,
    ) -> (u32, Waitstates) {
        let masked = (address & ROM_MAX_MASK) as usize;
        let value = if masked < self.rom.len() {
            LE::read_u32(&self.rom[masked..])
        } else {
            0
        };

        let wait = self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1];

        (value, wait)
    }

    pub(super) fn load16_gamepak(
        &self,
        address: u32,
        waitstate: u8,
        access: AccessType,
    ) -> (u16, Waitstates) {
        let masked = (address & ROM_MAX_MASK) as usize;
        let value = if masked < self.rom.len() {
            LE::read_u16(&self.rom[masked..])
        } else {
            0
        };

        let wait = self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1];

        (value, wait)
    }

    pub(super) fn load8_gamepak(
        &self,
        address: u32,
        waitstate: u8,
        access: AccessType,
    ) -> (u8, Waitstates) {
        let masked = (address & ROM_MAX_MASK) as usize;
        let value = if masked < self.rom.len() {
            self.rom[masked]
        } else {
            0
        };

        let wait = self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1];

        (value, wait)
    }

    pub(super) fn store32_gamepak(
        &self,
        _address: u32,
        _value: u32,
        waitstate: u8,
        access: AccessType,
    ) -> Waitstates {
        self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1]
    }

    pub(super) fn store16_gamepak(
        &self,
        _address: u32,
        _value: u16,
        waitstate: u8,
        access: AccessType,
    ) -> Waitstates {
        self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1]
    }

    pub(super) fn store8_gamepak(
        &self,
        _address: u32,
        _value: u8,
        waitstate: u8,
        access: AccessType,
    ) -> Waitstates {
        self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1]
    }
}
<commit_msg>Fix gamepak access timings. (still not fully accurate probably).<commit_after>use super::{GbaMemory, ROM_MAX_MASK};
use arm::{AccessType, Waitstates};
use byteorder::{ByteOrder, LittleEndian as LE};

impl GbaMemory {
    pub(super) fn load32_gamepak(
        &self,
        address: u32,
        waitstate: u8,
        mut access: AccessType,
    ) -> (u32, Waitstates) {
        let masked = (address & ROM_MAX_MASK) as usize;
        let value = if masked < self.rom.len() {
            LE::read_u32(&self.rom[masked..])
        } else {
            0
        };

        gamepak_access_fix(address, &mut access);
        let wait = self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1];

        (value, wait)
    }

    pub(super) fn load16_gamepak(
        &self,
        address: u32,
        waitstate: u8,
        mut access: AccessType,
    ) -> (u16, Waitstates) {
        let masked = (address & ROM_MAX_MASK) as usize;
        let value = if masked < self.rom.len() {
            LE::read_u16(&self.rom[masked..])
        } else {
            0
        };

        gamepak_access_fix(address, &mut access);
        let wait = self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1];

        (value, wait)
    }

    pub(super) fn load8_gamepak(
        &self,
        address: u32,
        waitstate: u8,
        mut access: AccessType,
    ) -> (u8, Waitstates) {
        let masked = (address & ROM_MAX_MASK) as usize;
        let value = if masked < self.rom.len() {
            self.rom[masked]
        } else {
            0
        };

        gamepak_access_fix(address, &mut access);
        let wait = self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1];

        (value, wait)
    }

    pub(super) fn store32_gamepak(
        &self,
        address: u32,
        _value: u32,
        waitstate: u8,
        mut access: AccessType,
    ) -> Waitstates {
        gamepak_access_fix(address, &mut access);
        self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1]
    }

    pub(super) fn store16_gamepak(
        &self,
        address: u32,
        _value: u16,
        waitstate: u8,
        mut access: AccessType,
    ) -> Waitstates {
        gamepak_access_fix(address, &mut access);
        self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1]
    }

    pub(super) fn store8_gamepak(
        &self,
        address: u32,
        _value: u8,
        waitstate: u8,
        mut access: AccessType,
    ) -> Waitstates {
        gamepak_access_fix(address, &mut access);
        self.gamepak_waitstates[((waitstate as usize) << 1) + (access as usize)]
            + self.gamepak_waitstates[((waitstate as usize) << 1) + 1]
    }
}

/// Changes the given access type to nonsequential if the address is the start of
/// a 128K block.
#[inline(always)]
fn gamepak_access_fix(address: u32, access: &mut AccessType) {
    if (address & 0x1FFFF) == 0 {
        *access = AccessType::NonSeq;
    }
}
<|endoftext|>


<commit_before>use ::quote::Tokens;
use ::syn::Ident;
use ::yaml_rust::Yaml;

use infer::datatype;
use infer::TokensResult;

const UNSPECIFIED_CODE: u16 = 999;

fn parse_response_key(key: &Yaml) -> (u16, Ident) {
    match key.as_i64() {
        Some(code) => (code as u16, Ident::new(format!("Status{}", code))),
        None => (UNSPECIFIED_CODE, Ident::new("UnspecifiedCode")),
    }
}

pub(super) fn infer_v3(schema: &Yaml) -> TokensResult {
    let mut err_codes: Vec<u16> = Vec::new();
    let mut err_variants: Vec<Ident> = Vec::new();
    let mut err_models: Vec<Tokens> = Vec::new();

    let mut ok_codes: Vec<u16> = Vec::new();
    let mut ok_variants: Vec<Ident> = Vec::new();
    let mut ok_models: Vec<Tokens> = Vec::new();

    let mut additional_types: Vec<Tokens> = Vec::new();
    let mut unspecified_err = quote!(UnspecifiedCode(String),);
    let mut unspecified_err_deser = quote! {
        let mut buf = String::new();
        response.read_to_string(&mut buf).ok();
        ErrBody::UnspecifiedCode(buf)
    };

    for (code, schema) in schema.as_hash().expect("Responses must be a map.") {
        let (status_code, variant_ident) = parse_response_key(&code);

        let inferred_type: Tokens;
        let additional_type: Option<Tokens>;

        let schema = &schema["content"]["application/json"]["schema"];
        if let None = schema.as_hash() {
            inferred_type = quote!{ () };
            additional_type = None;
        } else {
            let (ty, at) = datatype::infer_v3(&schema)?;
            inferred_type = ty;
            additional_type = at;
        }

        if let Some(t) = additional_type {
            additional_types.push(t);
        }

        if status_code < 400 {
            ok_codes.push(status_code);
            ok_variants.push(variant_ident);
            ok_models.push(inferred_type.clone());
        } else {
            err_codes.push(status_code);
            err_variants.push(variant_ident);
            err_models.push(inferred_type.clone());
        }

        if code == &Yaml::from_str("default") {
            // In this case we don't add a Bytes variant; instead use the given model.
            unspecified_err = quote!();
            unspecified_err_deser = quote! {
                match response.json::<#inferred_type>() {
                    Ok(body) => ErrBody::UnspecifiedCode(body),
                    Err(_) => {
                        let mut buf = String::new();
                        response.read_to_string(&mut buf).ok();
                        ErrBody::MalformedJSON(buf)
                    }
                }
            };
        }
    }

    let ok_models2 = ok_models.clone();
    let err_models2 = err_models.clone();
    let ok_variants2 = ok_variants.clone();
    let err_variants2 = err_variants.clone();
    Ok(quote! {
        use std::io::Read;
        use ::tapioca::response::ClientResponse;
        use ::tapioca::response::Response;
        use ::tapioca::response::ResponseBody;
        use ::tapioca::response::ResponseResult as _ResponseResult;
        use ::tapioca::response::Status;
        use ::tapioca::response::StatusCode;

        #(#additional_types)*

        pub type ResponseResult = _ResponseResult<OkResult, ErrResult>;

        #[derive(Clone, Debug)]
        #[allow(dead_code)]
        pub enum OkBody {
            #(#ok_variants(#ok_models),)*
            MalformedJSON(String),
            UnspecifiedCode(String),
        }

        #[derive(Clone, Debug)]
        #[allow(dead_code)]
        pub enum ErrBody {
            #(#err_variants(#err_models),)*
            #unspecified_err
            MalformedJSON(String),
            NetworkFailure(),
        }

        #[derive(Debug)]
        pub struct OkResult {
            body: OkBody,
            status_code: StatusCode,
        }

        #[derive(Debug)]
        pub struct ErrResult {
            body: ErrBody,
            status_code: StatusCode,
        }

        impl Response for OkResult {
            type BodyType = OkBody;

            fn from(maybe_response: &mut Option<&mut ClientResponse>) -> Self {
                let status_code = match *maybe_response {
                    Some(ref response) => StatusCode::of(&Some(response)),
                    None => panic!("OkResponse requires Some response."),
                };

                assert!(status_code.is_ok());

                Self {
                    body: <OkBody as ResponseBody>::from(maybe_response),
                    status_code,
                }
            }

            fn body(&self) -> Self::BodyType {
                self.body.clone()
            }

            fn status_code(&self) -> StatusCode {
                self.status_code
            }
        }

        impl Response for ErrResult {
            type BodyType = ErrBody;

            fn from(maybe_response: &mut Option<&mut ClientResponse>) -> Self {
                let status_code = match *maybe_response {
                    Some(ref response) => StatusCode::of(&Some(response)),
                    None => StatusCode::of(&None),
                };
                assert!(status_code.is_err());

                Self {
                    body: <ErrBody as ResponseBody>::from(maybe_response),
                    status_code,
                }
            }

            fn body(&self) -> Self::BodyType {
                self.body.clone()
            }

            fn status_code(&self) -> StatusCode {
                self.status_code
            }
        }

        impl ResponseBody for OkBody {
            fn from(maybe_response: &mut Option<&mut ClientResponse>) -> Self {
                let status_code = match *maybe_response {
                    Some(ref response) => StatusCode::of(&Some(response)),
                    None => panic!("OkResponse requires Some response"),
                }.to_u16();

                match (maybe_response, status_code) {
                    #(
                    (&mut Some(ref mut response), #ok_codes) =>
                        match response.json::<#ok_models2>() {
                            Ok(body) => OkBody::#ok_variants2(body),
                            Err(_) => {
                                let mut buf = String::new();
                                response.read_to_string(&mut buf).ok();
                                OkBody::MalformedJSON(buf)
                            },
                        },
                    )*
                    (&mut Some(ref mut response), _) => {
                        let mut buf = String::new();
                        response.read_to_string(&mut buf).ok();
                        OkBody::UnspecifiedCode(buf)
                    },
                    (&mut None, _) => panic!("OkResponse requires Some response"),
                }
            }
        }

        impl ResponseBody for ErrBody {
            fn from(maybe_response: &mut Option<&mut ClientResponse>) -> Self {
                let status_code = match *maybe_response {
                    Some(ref response) => StatusCode::of(&Some(response)),
                    None => StatusCode::of(&None),
                };
                assert!(status_code.is_err());

                match (maybe_response, status_code.to_u16()) {
                    #(
                    (&mut Some(ref mut response), #err_codes) =>
                        match response.json::<#err_models2>() {
                            Ok(body) => ErrBody::#err_variants2(body),
                            Err(_) => {
                                let mut buf = String::new();
                                response.read_to_string(&mut buf).ok();
                                ErrBody::MalformedJSON(buf)
                            },
                        },
                    )*
                    (&mut Some(ref mut response), _) => { #unspecified_err_deser },
                    (&mut None, _) => ErrBody::NetworkFailure(),
                }
            }
        }
    })
}
<commit_msg>Handle empty response deserialisation correctly<commit_after>use ::quote::Tokens;
use ::syn::Ident;
use ::yaml_rust::Yaml;

use infer::datatype;
use infer::TokensResult;

const UNSPECIFIED_CODE: u16 = 999;

fn parse_response_key(key: &Yaml) -> (u16, Ident) {
    match key.as_i64() {
        Some(code) => (code as u16, Ident::new(format!("Status{}", code))),
        None => (UNSPECIFIED_CODE, Ident::new("UnspecifiedCode")),
    }
}

pub(super) fn infer_v3(schema: &Yaml) -> TokensResult {
    let mut err_codes: Vec<u16> = Vec::new();
    let mut err_variants: Vec<Ident> = Vec::new();
    let mut err_models: Vec<Tokens> = Vec::new();

    let mut ok_codes: Vec<u16> = Vec::new();
    let mut ok_variants: Vec<Ident> = Vec::new();
    let mut ok_models: Vec<Tokens> = Vec::new();

    let mut additional_types: Vec<Tokens> = Vec::new();
    let mut unspecified_err = quote!(UnspecifiedCode(String),);
    let mut unspecified_err_deser = quote! {
        let mut buf = String::new();
        response.read_to_string(&mut buf).ok();
        ErrBody::UnspecifiedCode(buf)
    };

    for (code, schema) in schema.as_hash().expect("Responses must be a map.") {
        let (status_code, variant_ident) = parse_response_key(&code);

        let inferred_type: Tokens;
        let additional_type: Option<Tokens>;

        let schema = &schema["content"]["application/json"]["schema"];
        if let None = schema.as_hash() {
            inferred_type = quote!{ () };
            additional_type = None;
        } else {
            let (ty, at) = datatype::infer_v3(&schema)?;
            inferred_type = ty;
            additional_type = at;
        }

        if let Some(t) = additional_type {
            additional_types.push(t);
        }

        if status_code < 400 {
            ok_codes.push(status_code);
            ok_variants.push(variant_ident);
            ok_models.push(inferred_type.clone());
        } else {
            err_codes.push(status_code);
            err_variants.push(variant_ident);
            err_models.push(inferred_type.clone());
        }

        if code == &Yaml::from_str("default") {
            // In this case we don't add a Bytes variant; instead use the given model.
            unspecified_err = quote!();
            unspecified_err_deser = quote! {
                deser_into::<#inferred_type>(response)
                    .map(|b| ErrBody::UnspecifiedCode(b))
                    .unwrap_or_else(|b| ErrBody::MalformedJSON(b))
            };
        }
    }

    let ok_models2 = ok_models.clone();
    let err_models2 = err_models.clone();
    let ok_variants2 = ok_variants.clone();
    let err_variants2 = err_variants.clone();
    Ok(quote! {
        use std::io::Read;
        use ::tapioca::response::ClientResponse;
        use ::tapioca::response::Response;
        use ::tapioca::response::ResponseBody;
        use ::tapioca::response::ResponseResult as _ResponseResult;
        use ::tapioca::response::Status;
        use ::tapioca::response::StatusCode;
        use ::tapioca::serde::de::DeserializeOwned;
        use ::tapioca::serde_json;

        #(#additional_types)*

        pub type ResponseResult = _ResponseResult<OkResult, ErrResult>;

        fn deser_into<T: DeserializeOwned>(response: &mut ClientResponse) -> Result<T, String> {
            let mut buf = String::new();
            match response.json::<T>() {
                Ok(body) => Ok(body),
                Err(_) => match response.read_to_string(&mut buf) {
                    Err(_) | Ok(0) => serde_json::from_str::<T>("null").or(Err(buf)),
                    _ => Err(buf),
                },
            }
        }

        #[derive(Clone, Debug)]
        #[allow(dead_code)]
        pub enum OkBody {
            #(#ok_variants(#ok_models),)*
            MalformedJSON(String),
            UnspecifiedCode(String),
        }

        #[derive(Clone, Debug)]
        #[allow(dead_code)]
        pub enum ErrBody {
            #(#err_variants(#err_models),)*
            #unspecified_err
            MalformedJSON(String),
            NetworkFailure(),
        }

        #[derive(Debug)]
        pub struct OkResult {
            body: OkBody,
            status_code: StatusCode,
        }

        #[derive(Debug)]
        pub struct ErrResult {
            body: ErrBody,
            status_code: StatusCode,
        }

        impl Response for OkResult {
            type BodyType = OkBody;

            fn from(maybe_response: &mut Option<&mut ClientResponse>) -> Self {
                let status_code = match *maybe_response {
                    Some(ref response) => StatusCode::of(&Some(response)),
                    None => panic!("OkResponse requires Some response."),
                };

                assert!(status_code.is_ok());

                Self {
                    body: <OkBody as ResponseBody>::from(maybe_response),
                    status_code,
                }
            }

            fn body(&self) -> Self::BodyType {
                self.body.clone()
            }

            fn status_code(&self) -> StatusCode {
                self.status_code
            }
        }

        impl Response for ErrResult {
            type BodyType = ErrBody;

            fn from(maybe_response: &mut Option<&mut ClientResponse>) -> Self {
                let status_code = match *maybe_response {
                    Some(ref response) => StatusCode::of(&Some(response)),
                    None => StatusCode::of(&None),
                };
                assert!(status_code.is_err());

                Self {
                    body: <ErrBody as ResponseBody>::from(maybe_response),
                    status_code,
                }
            }

            fn body(&self) -> Self::BodyType {
                self.body.clone()
            }

            fn status_code(&self) -> StatusCode {
                self.status_code
            }
        }

        impl ResponseBody for OkBody {
            fn from(maybe_response: &mut Option<&mut ClientResponse>) -> Self {
                let status_code = match *maybe_response {
                    Some(ref response) => StatusCode::of(&Some(response)),
                    None => panic!("OkResponse requires Some response"),
                }.to_u16();

                match (maybe_response, status_code) {
                    #(
                    (&mut Some(ref mut response), #ok_codes) =>
                        deser_into::<#ok_models2>(response)
                            .map(|b| OkBody::#ok_variants2(b))
                            .unwrap_or_else(|b| OkBody::MalformedJSON(b)),
                    )*
                    (&mut Some(ref mut response), _) => {
                        let mut buf = String::new();
                        response.read_to_string(&mut buf).ok();
                        OkBody::UnspecifiedCode(buf)
                    },
                    (&mut None, _) => panic!("OkResponse requires Some response"),
                }
            }
        }

        impl ResponseBody for ErrBody {
            fn from(maybe_response: &mut Option<&mut ClientResponse>) -> Self {
                let status_code = match *maybe_response {
                    Some(ref response) => StatusCode::of(&Some(response)),
                    None => StatusCode::of(&None),
                };
                assert!(status_code.is_err());

                match (maybe_response, status_code.to_u16()) {
                    #(
                    (&mut Some(ref mut response), #err_codes) =>
                        deser_into::<#err_models2>(response)
                            .map(|b| ErrBody::#err_variants2(b))
                            .unwrap_or_else(|b| ErrBody::MalformedJSON(b)),
                    )*
                    (&mut Some(ref mut response), _) => { #unspecified_err_deser },
                    (&mut None, _) => ErrBody::NetworkFailure(),
                }
            }
        }
    })
}
<|endoftext|>


<commit_before>//! The Ref object is a helper over the link functionality, so one is able to create references to
//! files outside of the imag store.

use std::path::PathBuf;
use std::ops::Deref;
use std::ops::DerefMut;

use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId;
use libimagstore::store::Store;

use result::Result;
use flags::RefFlags;

pub struct Ref<'a>(FileLockEntry<'a>);

impl<'a> Ref<'a> {

    /// Try to open `si` as Ref object from the store
    pub fn open(store: &Store, si: StoreId) -> Result<Ref<'a>> {
        unimplemented!()
    }

    /// Create a Ref object which refers to `pb`
    pub fn create(store: &Store, pb: PathBuf, flags: RefFlags) -> Result<Ref<'a>> {
        unimplemented!()
    }

    /// Creates a Hash from a PathBuf by making the PathBuf absolute and then running a hash
    /// algorithm on it
    fn hash_path(pb: &PathBuf) -> String {
        unimplemented!()
    }

    /// check whether the pointer the Ref represents still points to a file which exists
    pub fn fs_link_exists(&self) -> bool {
        unimplemented!()
    }

    /// check whether the pointer the Ref represents is valid
    /// This includes:
    ///     - Hashsum of the file is still the same as stored in the Ref
    ///     - file permissions are still valid
    pub fn fs_link_valid(&self) -> bool {
        unimplemented!()
    }

    /// Check whether the file permissions of the referenced file are equal to the stored
    /// permissions
    pub fn fs_link_valid_permissions(&self) -> bool {
        unimplemented!()
    }

    /// Check whether the Hashsum of the referenced file is equal to the stored hashsum
    pub fn fs_link_valid_hash(&self) -> bool {
        unimplemented!()
    }

    /// Update the Ref by re-checking the file from FS
    /// This errors if the file is not present or cannot be read()
    pub fn update_ref(&mut self) -> Result<()> {
        unimplemented!()
    }

    /// Get the path of the file which is reffered to by this Ref
    pub fn fs_file(&self) -> &PathBuf {
        unimplemented!()
    }

    /// Check whether there is a reference to the file at `pb`
    pub fn exists(store: &Store, pb: PathBuf) -> Result<bool> {
        unimplemented!()
    }

    /// Re-find a referenced file
    ///
    /// This function tries to re-find a ref by searching all directories in `search_roots` recursively
    /// for a file which matches the hash of the Ref `ref`.
    ///
    /// If `search_roots` is `None`, it starts at the filesystem root `/`.
    ///
    /// # Warning
    ///
    /// This option causes heavy I/O as it recursively searches the Filesystem.
    pub fn refind(&self, search_roots: Option<Vec<PathBuf>>) -> Option<PathBuf> {
        unimplemented!()
    }

}

impl<'a> Deref for Ref<'a> {
    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.0
    }

}

impl<'a> DerefMut for Ref<'a> {

    fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
        &mut self.0
    }

}
<commit_msg>Impl Ref::open()<commit_after>//! The Ref object is a helper over the link functionality, so one is able to create references to
//! files outside of the imag store.

use std::path::PathBuf;
use std::ops::Deref;
use std::ops::DerefMut;

use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId;
use libimagstore::store::Store;
use libimagerror::into::IntoError;

use toml::Value;

use error::RefErrorKind as REK;
use flags::RefFlags;
use result::Result;

pub struct Ref<'a>(FileLockEntry<'a>);

impl<'a> Ref<'a> {

    /// Try to get `si` as Ref object from the store
    pub fn get(store: &'a Store, si: StoreId) -> Result<Ref<'a>> {
        match store.get(si) {
            Err(e) => return Err(REK::StoreReadError.into_error_with_cause(Box::new(e))),
            Ok(None) => return Err(REK::RefNotInStore.into_error()),
            Ok(Some(fle)) => Ref::read_reference(&fle).map(|_| Ref(fle)),
        }
    }

    fn read_reference(fle: &FileLockEntry<'a>) -> Result<PathBuf> {
        match fle.get_header().read("ref.reference") {
            Ok(Some(Value::String(s))) => Ok(PathBuf::from(s)),
            Ok(Some(_)) => Err(REK::HeaderTypeError.into_error()),
            Ok(None)    => Err(REK::HeaderFieldMissingError.into_error()),
            Err(e)      => Err(REK::StoreReadError.into_error_with_cause(Box::new(e))),
        }
    }

    /// Create a Ref object which refers to `pb`
    pub fn create(store: &Store, pb: PathBuf, flags: RefFlags) -> Result<Ref<'a>> {
        unimplemented!()
    }

    /// Creates a Hash from a PathBuf by making the PathBuf absolute and then running a hash
    /// algorithm on it
    fn hash_path(pb: &PathBuf) -> String {
        unimplemented!()
    }

    /// check whether the pointer the Ref represents still points to a file which exists
    pub fn fs_link_exists(&self) -> bool {
        unimplemented!()
    }

    /// check whether the pointer the Ref represents is valid
    /// This includes:
    ///     - Hashsum of the file is still the same as stored in the Ref
    ///     - file permissions are still valid
    pub fn fs_link_valid(&self) -> bool {
        unimplemented!()
    }

    /// Check whether the file permissions of the referenced file are equal to the stored
    /// permissions
    pub fn fs_link_valid_permissions(&self) -> bool {
        unimplemented!()
    }

    /// Check whether the Hashsum of the referenced file is equal to the stored hashsum
    pub fn fs_link_valid_hash(&self) -> bool {
        unimplemented!()
    }

    /// Update the Ref by re-checking the file from FS
    /// This errors if the file is not present or cannot be read()
    pub fn update_ref(&mut self) -> Result<()> {
        unimplemented!()
    }

    /// Get the path of the file which is reffered to by this Ref
    pub fn fs_file(&self) -> &PathBuf {
        unimplemented!()
    }

    /// Check whether there is a reference to the file at `pb`
    pub fn exists(store: &Store, pb: PathBuf) -> Result<bool> {
        unimplemented!()
    }

    /// Re-find a referenced file
    ///
    /// This function tries to re-find a ref by searching all directories in `search_roots` recursively
    /// for a file which matches the hash of the Ref `ref`.
    ///
    /// If `search_roots` is `None`, it starts at the filesystem root `/`.
    ///
    /// # Warning
    ///
    /// This option causes heavy I/O as it recursively searches the Filesystem.
    pub fn refind(&self, search_roots: Option<Vec<PathBuf>>) -> Option<PathBuf> {
        unimplemented!()
    }

}

impl<'a> Deref for Ref<'a> {
    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.0
    }

}

impl<'a> DerefMut for Ref<'a> {

    fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
        &mut self.0
    }

}
<|endoftext|>


<commit_before>use crate::ast::{FromInputValue, InputValue, Selection, ToInputValue};
use std::{fmt::Debug, sync::Arc};

use crate::{
    executor::{ExecutionResult, Executor, Registry},
    schema::meta::MetaType,
    types::base::{Arguments, GraphQLType},
    value::ScalarValue,
};

impl<S, T, CtxT> GraphQLType<S> for Box<T>
where
    S: ScalarValue,
    T: GraphQLType<S, Context = CtxT>,
{
    type Context = CtxT;
    type TypeInfo = T::TypeInfo;

    fn name(info: &T::TypeInfo) -> Option<&str> {
        T::name(info)
    }

    fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        T::meta(info, registry)
    }

    fn resolve_into_type(
        &self,
        info: &T::TypeInfo,
        name: &str,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_into_type(info, name, selection_set, executor)
    }

    fn resolve_field(
        &self,
        info: &T::TypeInfo,
        field: &str,
        args: &Arguments<S>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_field(info, field, args, executor)
    }

    fn resolve(
        &self,
        info: &T::TypeInfo,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve(info, selection_set, executor)
    }
}

impl<T, S> FromInputValue<S> for Box<T>
where
    S: ScalarValue,
    T: FromInputValue<S>,
{
    fn from_input_value<'a>(v: &'a InputValue<S>) -> Option<Box<T>> {
        match <T as FromInputValue<S>>::from_input_value(v) {
            Some(v) => Some(Box::new(v)),
            None => None,
        }
    }
}

impl<T, S> ToInputValue<S> for Box<T>
where
    S: Debug,
    T: ToInputValue<S>,
{
    fn to_input_value(&self) -> InputValue<S> {
        (**self).to_input_value()
    }
}

impl<'e, S, T, CtxT> GraphQLType<S> for &'e T
where
    S: ScalarValue,
    T: GraphQLType<S, Context = CtxT>,
{
    type Context = CtxT;
    type TypeInfo = T::TypeInfo;

    fn name(info: &T::TypeInfo) -> Option<&str> {
        T::name(info)
    }

    fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        T::meta(info, registry)
    }

    fn resolve_into_type(
        &self,
        info: &T::TypeInfo,
        name: &str,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_into_type(info, name, selection_set, executor)
    }

    fn resolve_field(
        &self,
        info: &T::TypeInfo,
        field: &str,
        args: &Arguments<S>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_field(info, field, args, executor)
    }

    fn resolve(
        &self,
        info: &T::TypeInfo,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve(info, selection_set, executor)
    }
}

impl<'e, S, T> crate::GraphQLTypeAsync<S> for &'e T
where
    S: ScalarValue + Send + Sync,
    T: crate::GraphQLTypeAsync<S>,
    T::TypeInfo: Send + Sync,
    T::Context: Send + Sync,
{
    fn resolve_field_async<'b>(
        &'b self,
        info: &'b Self::TypeInfo,
        field_name: &'b str,
        arguments: &'b Arguments<S>,
        executor: &'b Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'b, ExecutionResult<S>> {
        crate::GraphQLTypeAsync::resolve_field_async(&**self, info, field_name, arguments, executor)
    }

    fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<S>]>,
        executor: &'a Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'a, ExecutionResult<S>> {
        crate::GraphQLTypeAsync::resolve_async(&**self, info, selection_set, executor)
    }
}

impl<'a, T, S> ToInputValue<S> for &'a T
where
    S: Debug,
    T: ToInputValue<S>,
{
    fn to_input_value(&self) -> InputValue<S> {
        (**self).to_input_value()
    }
}

impl<S, T> GraphQLType<S> for Arc<T>
where
    S: ScalarValue,
    T: GraphQLType<S>,
{
    type Context = T::Context;
    type TypeInfo = T::TypeInfo;

    fn name(info: &T::TypeInfo) -> Option<&str> {
        T::name(info)
    }

    fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        T::meta(info, registry)
    }

    fn resolve_into_type(
        &self,
        info: &T::TypeInfo,
        name: &str,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<T::Context, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_into_type(info, name, selection_set, executor)
    }

    fn resolve_field(
        &self,
        info: &T::TypeInfo,
        field: &str,
        args: &Arguments<S>,
        executor: &Executor<T::Context, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_field(info, field, args, executor)
    }

    fn resolve(
        &self,
        info: &T::TypeInfo,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<T::Context, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve(info, selection_set, executor)
    }
}

impl<'e, S, T> crate::GraphQLTypeAsync<S> for std::sync::Arc<T>
where
    S: ScalarValue + Send + Sync,
    T: crate::GraphQLTypeAsync<S>,
    <T as crate::types::base::GraphQLType<S>>::TypeInfo: Send + Sync,
    <T as crate::types::base::GraphQLType<S>>::Context: Send + Sync,
{
    fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<S>]>,
        executor: &'a Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'a, crate::ExecutionResult<S>> {
        (**self).resolve_async(info, selection_set, executor)
    }
}

impl<T, S> ToInputValue<S> for Arc<T>
where
    S: Debug,
    T: ToInputValue<S>,
{
    fn to_input_value(&self) -> InputValue<S> {
        (**self).to_input_value()
    }
}
<commit_msg>Implement GraphQLTypeAsync for Box (#582)<commit_after>use crate::ast::{FromInputValue, InputValue, Selection, ToInputValue};
use std::{fmt::Debug, sync::Arc};

use crate::{
    executor::{ExecutionResult, Executor, Registry},
    schema::meta::MetaType,
    types::base::{Arguments, GraphQLType},
    value::ScalarValue,
};

impl<S, T, CtxT> GraphQLType<S> for Box<T>
where
    S: ScalarValue,
    T: GraphQLType<S, Context = CtxT>,
{
    type Context = CtxT;
    type TypeInfo = T::TypeInfo;

    fn name(info: &T::TypeInfo) -> Option<&str> {
        T::name(info)
    }

    fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        T::meta(info, registry)
    }

    fn resolve_into_type(
        &self,
        info: &T::TypeInfo,
        name: &str,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_into_type(info, name, selection_set, executor)
    }

    fn resolve_field(
        &self,
        info: &T::TypeInfo,
        field: &str,
        args: &Arguments<S>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_field(info, field, args, executor)
    }

    fn resolve(
        &self,
        info: &T::TypeInfo,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve(info, selection_set, executor)
    }
}

impl<T, S> FromInputValue<S> for Box<T>
where
    S: ScalarValue,
    T: FromInputValue<S>,
{
    fn from_input_value<'a>(v: &'a InputValue<S>) -> Option<Box<T>> {
        match <T as FromInputValue<S>>::from_input_value(v) {
            Some(v) => Some(Box::new(v)),
            None => None,
        }
    }
}

impl<T, S> ToInputValue<S> for Box<T>
where
    S: Debug,
    T: ToInputValue<S>,
{
    fn to_input_value(&self) -> InputValue<S> {
        (**self).to_input_value()
    }
}

impl<'e, S, T, CtxT> GraphQLType<S> for &'e T
where
    S: ScalarValue,
    T: GraphQLType<S, Context = CtxT>,
{
    type Context = CtxT;
    type TypeInfo = T::TypeInfo;

    fn name(info: &T::TypeInfo) -> Option<&str> {
        T::name(info)
    }

    fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        T::meta(info, registry)
    }

    fn resolve_into_type(
        &self,
        info: &T::TypeInfo,
        name: &str,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_into_type(info, name, selection_set, executor)
    }

    fn resolve_field(
        &self,
        info: &T::TypeInfo,
        field: &str,
        args: &Arguments<S>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_field(info, field, args, executor)
    }

    fn resolve(
        &self,
        info: &T::TypeInfo,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<CtxT, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve(info, selection_set, executor)
    }
}

impl<'e, S, T> crate::GraphQLTypeAsync<S> for &'e T
where
    S: ScalarValue + Send + Sync,
    T: crate::GraphQLTypeAsync<S>,
    T::TypeInfo: Send + Sync,
    T::Context: Send + Sync,
{
    fn resolve_field_async<'b>(
        &'b self,
        info: &'b Self::TypeInfo,
        field_name: &'b str,
        arguments: &'b Arguments<S>,
        executor: &'b Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'b, ExecutionResult<S>> {
        crate::GraphQLTypeAsync::resolve_field_async(&**self, info, field_name, arguments, executor)
    }

    fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<S>]>,
        executor: &'a Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'a, ExecutionResult<S>> {
        crate::GraphQLTypeAsync::resolve_async(&**self, info, selection_set, executor)
    }
}

impl<'a, T, S> ToInputValue<S> for &'a T
where
    S: Debug,
    T: ToInputValue<S>,
{
    fn to_input_value(&self) -> InputValue<S> {
        (**self).to_input_value()
    }
}

impl<S, T> GraphQLType<S> for Arc<T>
where
    S: ScalarValue,
    T: GraphQLType<S>,
{
    type Context = T::Context;
    type TypeInfo = T::TypeInfo;

    fn name(info: &T::TypeInfo) -> Option<&str> {
        T::name(info)
    }

    fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        T::meta(info, registry)
    }

    fn resolve_into_type(
        &self,
        info: &T::TypeInfo,
        name: &str,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<T::Context, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_into_type(info, name, selection_set, executor)
    }

    fn resolve_field(
        &self,
        info: &T::TypeInfo,
        field: &str,
        args: &Arguments<S>,
        executor: &Executor<T::Context, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve_field(info, field, args, executor)
    }

    fn resolve(
        &self,
        info: &T::TypeInfo,
        selection_set: Option<&[Selection<S>]>,
        executor: &Executor<T::Context, S>,
    ) -> ExecutionResult<S> {
        (**self).resolve(info, selection_set, executor)
    }
}

impl<S, T, CtxT> crate::GraphQLTypeAsync<S> for Box<T>
where
    T: crate::GraphQLTypeAsync<S, Context = CtxT>,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
{
    fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<S>]>,
        executor: &'a Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'a, crate::ExecutionResult<S>> {
        (**self).resolve_async(info, selection_set, executor)
    }
}

impl<'e, S, T> crate::GraphQLTypeAsync<S> for std::sync::Arc<T>
where
    S: ScalarValue + Send + Sync,
    T: crate::GraphQLTypeAsync<S>,
    <T as crate::types::base::GraphQLType<S>>::TypeInfo: Send + Sync,
    <T as crate::types::base::GraphQLType<S>>::Context: Send + Sync,
{
    fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<S>]>,
        executor: &'a Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'a, crate::ExecutionResult<S>> {
        (**self).resolve_async(info, selection_set, executor)
    }
}

impl<T, S> ToInputValue<S> for Arc<T>
where
    S: Debug,
    T: ToInputValue<S>,
{
    fn to_input_value(&self) -> InputValue<S> {
        (**self).to_input_value()
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::mem;
use std::ptr;

use glib_ffi;
use gobject_ffi;
use gst_base_ffi;
use gst_ffi;

use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gst_base;

use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;

use pad::*;

pub trait AggregatorPadImpl<T: AggregatorPadBase>:
    AnyImpl + ObjectImpl<T> + PadImpl<T> + Send + Sync + 'static
{
    fn flush(&self, aggregator_pad: &T, aggregator: &gst_base::Aggregator) -> gst::FlowReturn {
        aggregator_pad.parent_flush(aggregator)
    }

    fn skip_buffer(
        &self,
        aggregator_pad: &T,
        aggregator: &gst_base::Aggregator,
        buffer: &gst::BufferRef,
    ) -> bool {
        aggregator_pad.parent_skip_buffer(aggregator, buffer)
    }
}

any_impl!(AggregatorPadBase, AggregatorPadImpl);

pub unsafe trait AggregatorPadBase:
    IsA<gst_base::AggregatorPad> + IsA<gst::Pad> + ObjectType
{
    fn parent_flush(&self, aggregator: &gst_base::Aggregator) -> gst::FlowReturn {
        unsafe {
            let klass = self.get_class();
            let parent_klass =
                (*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorPadClass;
            (*parent_klass)
                .flush
                .map(|f| from_glib(f(self.to_glib_none().0, aggregator.to_glib_none().0)))
                .unwrap_or(gst::FlowReturn::Ok)
        }
    }

    fn parent_skip_buffer(
        &self,
        aggregator: &gst_base::Aggregator,
        buffer: &gst::BufferRef,
    ) -> bool {
        unsafe {
            let klass = self.get_class();
            let parent_klass =
                (*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorPadClass;
            (*parent_klass)
                .skip_buffer
                .map(|f| {
                    from_glib(f(
                        self.to_glib_none().0,
                        aggregator.to_glib_none().0,
                        buffer.as_mut_ptr(),
                    ))
                })
                .unwrap_or(false)
        }
    }
}

pub unsafe trait AggregatorPadClassExt<T: AggregatorPadBase>
where
    T::ImplType: AggregatorPadImpl<T>,
{
    fn override_vfuncs(&mut self, _: &ClassInitToken) {
        unsafe {
            let klass = &mut *(self as *const Self as *mut gst_base_ffi::GstAggregatorPadClass);
            klass.flush = Some(aggregator_pad_flush::<T>);
            klass.skip_buffer = Some(aggregator_pad_skip_buffer::<T>);
        }
    }
}

glib_wrapper! {
    pub struct AggregatorPad(Object<InstanceStruct<AggregatorPad>>):
        [gst_base::AggregatorPad => gst_base_ffi::GstAggregatorPad,
         gst::Pad => gst_ffi::GstPad,
         gst::Object => gst_ffi::GstObject];

    match fn {
        get_type => || get_type::<AggregatorPad>(),
    }
}

unsafe impl<T: IsA<gst_base::AggregatorPad> + IsA<gst::Pad> + ObjectType> AggregatorPadBase for T {}
pub type AggregatorPadClass = ClassStruct<AggregatorPad>;

// FIXME: Boilerplate
unsafe impl AggregatorPadClassExt<AggregatorPad> for AggregatorPadClass {}
unsafe impl PadClassExt<AggregatorPad> for AggregatorPadClass {}
unsafe impl ObjectClassExt<AggregatorPad> for AggregatorPadClass {}

unsafe impl Send for AggregatorPad {}
unsafe impl Sync for AggregatorPad {}

#[macro_export]
macro_rules! box_aggregator_pad_impl(
    ($name:ident) => {
        box_pad_impl!($name);

        impl<T: AggregatorPadBase> AggregatorPadImpl<T> for Box<$name<T>>
        {
            fn flush(&self, aggregator_pad: &T, aggregator: &gst_base::Aggregator) -> gst::FlowReturn {
                let imp: &$name<T> = self.as_ref();
                imp.flush(aggregator_pad, aggregator)
            }

            fn skip_buffer(&self, aggregator_pad: &T, aggregator: &gst_base::Aggregator, buffer: &gst::BufferRef) -> bool {
                let imp: &$name<T> = self.as_ref();
                imp.skip_buffer(aggregator_pad, aggregator, buffer)
            }
        }
    };
);
box_aggregator_pad_impl!(AggregatorPadImpl);

impl ObjectType for AggregatorPad {
    const NAME: &'static str = "RsAggregatorPad";
    type ParentType = gst_base::AggregatorPad;
    type ImplType = Box<AggregatorPadImpl<Self>>;
    type InstanceStructType = InstanceStruct<Self>;

    fn class_init(token: &ClassInitToken, klass: &mut AggregatorPadClass) {
        ObjectClassExt::override_vfuncs(klass, token);
        PadClassExt::override_vfuncs(klass, token);
        GhostPadClassExt::override_vfuncs(klass, token);
        AggregatorPadClassExt::override_vfuncs(klass, token);
    }

    object_type_fns!();
}

unsafe extern "C" fn aggregator_pad_flush<T: AggregatorPadBase>(
    ptr: *mut gst_base_ffi::GstAggregatorPad,
    aggregator: *mut gst_base_ffi::GstAggregator,
) -> gst_ffi::GstFlowReturn
where
    T::ImplType: AggregatorPadImpl<T>,
{
    floating_reference_guard!(ptr);
    let aggregator_pad = &*(ptr as *mut T::InstanceStructType);
    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
    let imp = aggregator_pad.get_impl();

    imp.flush(&wrap, &from_glib_borrow(aggregator)).to_glib()
}

unsafe extern "C" fn aggregator_pad_skip_buffer<T: AggregatorPadBase>(
    ptr: *mut gst_base_ffi::GstAggregatorPad,
    aggregator: *mut gst_base_ffi::GstAggregator,
    buffer: *mut gst_ffi::GstBuffer,
) -> glib_ffi::gboolean
where
    T::ImplType: AggregatorPadImpl<T>,
{
    floating_reference_guard!(ptr);
    let aggregator_pad = &*(ptr as *mut T::InstanceStructType);
    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
    let imp = aggregator_pad.get_impl();

    imp.skip_buffer(
        &wrap,
        &from_glib_borrow(aggregator),
        gst::BufferRef::from_ptr(buffer),
    )
    .to_glib()
}
<commit_msg>AggregatorPad is not actually a GhostPad<commit_after>// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::mem;
use std::ptr;

use glib_ffi;
use gobject_ffi;
use gst_base_ffi;
use gst_ffi;

use glib;
use glib::translate::*;
use gst;
use gst::prelude::*;
use gst_base;

use gobject_subclass::anyimpl::*;
use gobject_subclass::object::*;

use pad::*;

pub trait AggregatorPadImpl<T: AggregatorPadBase>:
    AnyImpl + ObjectImpl<T> + PadImpl<T> + Send + Sync + 'static
{
    fn flush(&self, aggregator_pad: &T, aggregator: &gst_base::Aggregator) -> gst::FlowReturn {
        aggregator_pad.parent_flush(aggregator)
    }

    fn skip_buffer(
        &self,
        aggregator_pad: &T,
        aggregator: &gst_base::Aggregator,
        buffer: &gst::BufferRef,
    ) -> bool {
        aggregator_pad.parent_skip_buffer(aggregator, buffer)
    }
}

any_impl!(AggregatorPadBase, AggregatorPadImpl);

pub unsafe trait AggregatorPadBase:
    IsA<gst_base::AggregatorPad> + IsA<gst::Pad> + ObjectType
{
    fn parent_flush(&self, aggregator: &gst_base::Aggregator) -> gst::FlowReturn {
        unsafe {
            let klass = self.get_class();
            let parent_klass =
                (*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorPadClass;
            (*parent_klass)
                .flush
                .map(|f| from_glib(f(self.to_glib_none().0, aggregator.to_glib_none().0)))
                .unwrap_or(gst::FlowReturn::Ok)
        }
    }

    fn parent_skip_buffer(
        &self,
        aggregator: &gst_base::Aggregator,
        buffer: &gst::BufferRef,
    ) -> bool {
        unsafe {
            let klass = self.get_class();
            let parent_klass =
                (*klass).get_parent_class() as *const gst_base_ffi::GstAggregatorPadClass;
            (*parent_klass)
                .skip_buffer
                .map(|f| {
                    from_glib(f(
                        self.to_glib_none().0,
                        aggregator.to_glib_none().0,
                        buffer.as_mut_ptr(),
                    ))
                })
                .unwrap_or(false)
        }
    }
}

pub unsafe trait AggregatorPadClassExt<T: AggregatorPadBase>
where
    T::ImplType: AggregatorPadImpl<T>,
{
    fn override_vfuncs(&mut self, _: &ClassInitToken) {
        unsafe {
            let klass = &mut *(self as *const Self as *mut gst_base_ffi::GstAggregatorPadClass);
            klass.flush = Some(aggregator_pad_flush::<T>);
            klass.skip_buffer = Some(aggregator_pad_skip_buffer::<T>);
        }
    }
}

glib_wrapper! {
    pub struct AggregatorPad(Object<InstanceStruct<AggregatorPad>>):
        [gst_base::AggregatorPad => gst_base_ffi::GstAggregatorPad,
         gst::Pad => gst_ffi::GstPad,
         gst::Object => gst_ffi::GstObject];

    match fn {
        get_type => || get_type::<AggregatorPad>(),
    }
}

unsafe impl<T: IsA<gst_base::AggregatorPad> + IsA<gst::Pad> + ObjectType> AggregatorPadBase for T {}
pub type AggregatorPadClass = ClassStruct<AggregatorPad>;

// FIXME: Boilerplate
unsafe impl AggregatorPadClassExt<AggregatorPad> for AggregatorPadClass {}
unsafe impl PadClassExt<AggregatorPad> for AggregatorPadClass {}
unsafe impl ObjectClassExt<AggregatorPad> for AggregatorPadClass {}

unsafe impl Send for AggregatorPad {}
unsafe impl Sync for AggregatorPad {}

#[macro_export]
macro_rules! box_aggregator_pad_impl(
    ($name:ident) => {
        box_pad_impl!($name);

        impl<T: AggregatorPadBase> AggregatorPadImpl<T> for Box<$name<T>>
        {
            fn flush(&self, aggregator_pad: &T, aggregator: &gst_base::Aggregator) -> gst::FlowReturn {
                let imp: &$name<T> = self.as_ref();
                imp.flush(aggregator_pad, aggregator)
            }

            fn skip_buffer(&self, aggregator_pad: &T, aggregator: &gst_base::Aggregator, buffer: &gst::BufferRef) -> bool {
                let imp: &$name<T> = self.as_ref();
                imp.skip_buffer(aggregator_pad, aggregator, buffer)
            }
        }
    };
);
box_aggregator_pad_impl!(AggregatorPadImpl);

impl ObjectType for AggregatorPad {
    const NAME: &'static str = "RsAggregatorPad";
    type ParentType = gst_base::AggregatorPad;
    type ImplType = Box<AggregatorPadImpl<Self>>;
    type InstanceStructType = InstanceStruct<Self>;

    fn class_init(token: &ClassInitToken, klass: &mut AggregatorPadClass) {
        ObjectClassExt::override_vfuncs(klass, token);
        PadClassExt::override_vfuncs(klass, token);
        AggregatorPadClassExt::override_vfuncs(klass, token);
    }

    object_type_fns!();
}

unsafe extern "C" fn aggregator_pad_flush<T: AggregatorPadBase>(
    ptr: *mut gst_base_ffi::GstAggregatorPad,
    aggregator: *mut gst_base_ffi::GstAggregator,
) -> gst_ffi::GstFlowReturn
where
    T::ImplType: AggregatorPadImpl<T>,
{
    floating_reference_guard!(ptr);
    let aggregator_pad = &*(ptr as *mut T::InstanceStructType);
    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
    let imp = aggregator_pad.get_impl();

    imp.flush(&wrap, &from_glib_borrow(aggregator)).to_glib()
}

unsafe extern "C" fn aggregator_pad_skip_buffer<T: AggregatorPadBase>(
    ptr: *mut gst_base_ffi::GstAggregatorPad,
    aggregator: *mut gst_base_ffi::GstAggregator,
    buffer: *mut gst_ffi::GstBuffer,
) -> glib_ffi::gboolean
where
    T::ImplType: AggregatorPadImpl<T>,
{
    floating_reference_guard!(ptr);
    let aggregator_pad = &*(ptr as *mut T::InstanceStructType);
    let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
    let imp = aggregator_pad.get_impl();

    imp.skip_buffer(
        &wrap,
        &from_glib_borrow(aggregator),
        gst::BufferRef::from_ptr(buffer),
    )
    .to_glib()
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("Hello there");
        tx.send(val).unwrap();
    });

    let received = rx.recv().unwrap();
    println!("Got: {}", received);
}
<commit_msg>Receive multiple sent messages<commit_after>use std::thread;
use std::sync::mpsc;
use std::time::Duration;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let vals = vec![
            String::from("Hello there"),
            String::from("Hello there 2"),
            String::from("Hello there 3"),
            String::from("Hello there 4")
        ];
        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    for received in rx {
        println!("Got: {}", received);
    }
}
<|endoftext|>