<commit_before>/*
 * Copyright (c) 2013-2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#![feature(macro_rules)]
#![feature(globs)]

#![crate_type = "bin"]

extern crate capnp;
extern crate rand;

use capnp::{MessageReader, MessageBuilder};

pub mod common;

pub mod carsales_capnp;
pub mod carsales;

pub mod catrank_capnp;
pub mod catrank;

pub mod eval_capnp;
pub mod eval;

mod Uncompressed {
    use capnp;
    use std;

    pub fn write<T : std::io::Writer, U : capnp::message::MessageBuilder>(
        writer: &mut T,
        message: &U) {
        capnp::serialize::write_message(writer, message).unwrap();
    }

    pub fn write_buffered<T : std::io::Writer, U : capnp::message::MessageBuilder>(
        writer: &mut T,
        message: &U) {
        capnp::serialize::write_message(writer, message).unwrap();
    }

    pub fn new_buffered_reader<R: capnp::io::BufferedInputStream>(
        inputStream : &mut R,
        options : capnp::message::ReaderOptions) -> capnp::serialize::OwnedSpaceMessageReader {
        capnp::serialize::new_reader(inputStream, options).unwrap()
    }
}

mod Packed {
    use capnp;
    use std;
    use capnp::serialize_packed::{write_packed_message, write_packed_message_unbuffered};

    pub fn write<T : std::io::Writer, U : capnp::message::MessageBuilder>(
        writer: &mut T,
        message: &U) {
        write_packed_message_unbuffered(writer, message).unwrap();
    }

    pub fn write_buffered<T : capnp::io::BufferedOutputStream, U : capnp::message::MessageBuilder>(
        writer: &mut T,
        message: &U) {
        write_packed_message(writer, message).unwrap();
    }

    pub fn new_buffered_reader<R:capnp::io::BufferedInputStream>(
        inputStream : &mut R,
        options : capnp::message::ReaderOptions) -> capnp::serialize::OwnedSpaceMessageReader {
        capnp::serialize_packed::new_reader(inputStream, options).unwrap()
    }

}

static SCRATCH_SIZE : uint = 128 * 1024;

pub struct NoScratch;

impl NoScratch {
    fn new_builder(&mut self, _idx : uint) -> capnp::message::MallocMessageBuilder {
        capnp::message::MallocMessageBuilder::new_default()
    }
}

pub struct UseScratch {
    scratch_space : std::vec::Vec<capnp::common::Word>
}

impl UseScratch {
    pub fn new() -> UseScratch {
        UseScratch {
            scratch_space : capnp::common::allocate_zeroed_words(SCRATCH_SIZE * 6)
        }
    }

    fn new_builder<'a>(&mut self, idx : uint) -> capnp::message::ScratchSpaceMallocMessageBuilder<'a> {
        assert!(idx < 6);
        unsafe {
            capnp::message::ScratchSpaceMallocMessageBuilder::new_default(
                std::mem::transmute(
                    std::raw::Slice { data : self.scratch_space.as_slice().unsafe_ref(idx * SCRATCH_SIZE),
                                      len : SCRATCH_SIZE }))
        }
    }
}

macro_rules! pass_by_object(
    ( $testcase:ident, $reuse:ident, $iters:expr ) => ({
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = $reuse.new_builder(0);
                let mut messageRes = $reuse.new_builder(1);

                let request = messageReq.init_root::<$testcase::RequestBuilder>();
                let response = messageRes.init_root::<$testcase::ResponseBuilder>();
                let expected = $testcase::setup_request(&mut rng, request);

                let requestReader = request.as_reader();
                $testcase::handle_request(requestReader, response);

                let responseReader = response.as_reader();
                if !$testcase::check_response(responseReader, expected) {
                    fail!("Incorrect response.");
                }
            }
        });
    )

macro_rules! pass_by_bytes(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr ) => ({
            let mut requestBytes = std::vec::Vec::from_elem(SCRATCH_SIZE * 8, 0u8);
            let mut responseBytes = std::vec::Vec::from_elem(SCRATCH_SIZE * 8, 0u8);
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = $reuse.new_builder(0);
                let mut messageRes = $reuse.new_builder(1);

                let request = messageReq.init_root::<$testcase::RequestBuilder>();
                let response = messageRes.init_root::<$testcase::ResponseBuilder>();
                let expected = $testcase::setup_request(&mut rng, request);

                {
                    let mut writer = capnp::io::ArrayOutputStream::new(requestBytes.as_mut_slice());
                    $compression::write_buffered(&mut writer, &messageReq)
                }

                let messageReader = $compression::new_buffered_reader(
                    &mut capnp::io::ArrayInputStream::new(requestBytes.as_slice()),
                    capnp::message::DefaultReaderOptions);

                let requestReader : $testcase::RequestReader = messageReader.get_root();
                $testcase::handle_request(requestReader, response);

                {
                    let mut writer = capnp::io::ArrayOutputStream::new(responseBytes.as_mut_slice());
                    $compression::write_buffered(&mut writer, &messageRes)
                }

                let messageReader = $compression::new_buffered_reader(
                    &mut capnp::io::ArrayInputStream::new(responseBytes.as_slice()),
                    capnp::message::DefaultReaderOptions);

                let responseReader : $testcase::ResponseReader = messageReader.get_root();
                if !$testcase::check_response(responseReader, expected) {
                    fail!("Incorrect response.");
                }
            }
        });
    )

macro_rules! server(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr, $input:expr, $output:expr) => ({
            let mut outBuffered = capnp::io::BufferedOutputStreamWrapper::new(&mut $output);
            let mut inBuffered = capnp::io::BufferedInputStreamWrapper::new(&mut $input);
            for _ in range(0, $iters) {
                let mut messageRes = $reuse.new_builder(0);

                let response = messageRes.init_root::<$testcase::ResponseBuilder>();
                let messageReader = $compression::new_buffered_reader(
                    &mut inBuffered,
                    capnp::message::DefaultReaderOptions);
                let requestReader : $testcase::RequestReader = messageReader.get_root();
                $testcase::handle_request(requestReader, response);

                $compression::write_buffered(&mut outBuffered, &messageRes);
                outBuffered.flush().unwrap();
            }
        });
    )

macro_rules! sync_client(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr) => ({
            let mut outStream = std::io::stdio::stdout_raw();
            let mut inStream = std::io::stdio::stdin_raw();
            let mut inBuffered = capnp::io::BufferedInputStreamWrapper::new(&mut inStream);
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = $reuse.new_builder(0);

                let request = messageReq.init_root::<$testcase::RequestBuilder>();

                let expected = $testcase::setup_request(&mut rng, request);
                $compression::write(&mut outStream, &messageReq);

                let messageReader = $compression::new_buffered_reader(
                    &mut inBuffered,
                    capnp::message::DefaultReaderOptions);
                let responseReader : $testcase::ResponseReader = messageReader.get_root();
                assert!($testcase::check_response(responseReader, expected));

            }
        });
    )

macro_rules! pass_by_pipe(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr) => ({
            use std::io::process;

            let mut args = std::os::args();
            *args.get_mut(2) = "client".to_owned();

            let config = process::ProcessConfig {
                program: args.get(0).as_slice(),
                args: args.slice(1, args.len()),
                stdin : process::CreatePipe(true, false),
                stdout : process::CreatePipe(false, true),
                stderr : process::Ignored,
                .. process::ProcessConfig::new()
            };
            match process::Process::configure(config) {
                Ok(ref mut p) => {
                    let mut childStdOut = p.stdout.take().unwrap();
                    let mut childStdIn = p.stdin.take().unwrap();

                    server!($testcase, $reuse, $compression, $iters, childStdOut, childStdIn);
                    println!("{}", p.wait());
                }
                Err(e) => {
                    println!("could not start process: {}", e);
                }
            }
        });
    )

macro_rules! do_testcase(
    ( $testcase:ident, $mode:expr, $reuse:ident, $compression:ident, $iters:expr ) => ({
            match $mode.as_slice() {
                "object" => pass_by_object!($testcase, $reuse, $iters),
                "bytes" => pass_by_bytes!($testcase, $reuse, $compression, $iters),
                "client" => sync_client!($testcase, $reuse, $compression, $iters),
                "server" => {
                    let mut input = std::io::stdio::stdin_raw();
                    let mut output = std::io::stdio::stdout_raw();
                    server!($testcase, $reuse, $compression, $iters, input, output)
                }
                "pipe" => pass_by_pipe!($testcase, $reuse, $compression, $iters),
                s => fail!("unrecognized mode: {}", s)
            }
        });
    )

macro_rules! do_testcase1(
    ( $testcase:expr, $mode:expr, $reuse:ident, $compression:ident, $iters:expr) => ({
            match $testcase.as_slice() {
                "carsales" => do_testcase!(carsales, $mode, $reuse, $compression, $iters),
                "catrank" => do_testcase!(catrank, $mode, $reuse, $compression, $iters),
                "eval" => do_testcase!(eval, $mode, $reuse, $compression, $iters),
                s => fail!("unrecognized test case: {}", s)
            }
        });
    )

macro_rules! do_testcase2(
    ( $testcase:expr, $mode:expr, $reuse:expr, $compression:ident, $iters:expr) => ({
            match $reuse.as_slice() {
                "no-reuse" => {
                    let mut scratch = NoScratch;
                    do_testcase1!($testcase, $mode, scratch, $compression, $iters)
                }
                "reuse" => {
                    let mut scratch = UseScratch::new();
                    do_testcase1!($testcase, $mode, scratch, $compression, $iters)
                }
                s => fail!("unrecognized reuse option: {}", s)
            }
        });
    )

pub fn main() {
    let args = std::os::args();

    if args.len() != 6 {
        println!("USAGE: {} CASE MODE REUSE COMPRESSION ITERATION_COUNT", args.get(0));
        std::os::set_exit_status(1);
        return;
    }

    let iters = match from_str::<u64>(*args.get(5)) {
        Some (n) => n,
        None => {
            println!("Could not parse a u64 from: {}", args.get(5));
            std::os::set_exit_status(1);
            return;
        }
    };

    match args.get(4).as_slice() {
        "none" => do_testcase2!(args.get(1), args.get(2),  args.get(3), Uncompressed, iters),
        "packed" => do_testcase2!(args.get(1), args.get(2), args.get(3), Packed, iters),
        s => fail!("unrecognized compression: {}", s)
    }
}
<commit_msg>update for new std::io::Process API<commit_after>/*
 * Copyright (c) 2013-2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#![feature(macro_rules)]
#![feature(globs)]

#![crate_type = "bin"]

extern crate capnp;
extern crate rand;

use capnp::{MessageReader, MessageBuilder};

pub mod common;

pub mod carsales_capnp;
pub mod carsales;

pub mod catrank_capnp;
pub mod catrank;

pub mod eval_capnp;
pub mod eval;

mod Uncompressed {
    use capnp;
    use std;

    pub fn write<T : std::io::Writer, U : capnp::message::MessageBuilder>(
        writer: &mut T,
        message: &U) {
        capnp::serialize::write_message(writer, message).unwrap();
    }

    pub fn write_buffered<T : std::io::Writer, U : capnp::message::MessageBuilder>(
        writer: &mut T,
        message: &U) {
        capnp::serialize::write_message(writer, message).unwrap();
    }

    pub fn new_buffered_reader<R: capnp::io::BufferedInputStream>(
        inputStream : &mut R,
        options : capnp::message::ReaderOptions) -> capnp::serialize::OwnedSpaceMessageReader {
        capnp::serialize::new_reader(inputStream, options).unwrap()
    }
}

mod Packed {
    use capnp;
    use std;
    use capnp::serialize_packed::{write_packed_message, write_packed_message_unbuffered};

    pub fn write<T : std::io::Writer, U : capnp::message::MessageBuilder>(
        writer: &mut T,
        message: &U) {
        write_packed_message_unbuffered(writer, message).unwrap();
    }

    pub fn write_buffered<T : capnp::io::BufferedOutputStream, U : capnp::message::MessageBuilder>(
        writer: &mut T,
        message: &U) {
        write_packed_message(writer, message).unwrap();
    }

    pub fn new_buffered_reader<R:capnp::io::BufferedInputStream>(
        inputStream : &mut R,
        options : capnp::message::ReaderOptions) -> capnp::serialize::OwnedSpaceMessageReader {
        capnp::serialize_packed::new_reader(inputStream, options).unwrap()
    }

}

static SCRATCH_SIZE : uint = 128 * 1024;

pub struct NoScratch;

impl NoScratch {
    fn new_builder(&mut self, _idx : uint) -> capnp::message::MallocMessageBuilder {
        capnp::message::MallocMessageBuilder::new_default()
    }
}

pub struct UseScratch {
    scratch_space : std::vec::Vec<capnp::common::Word>
}

impl UseScratch {
    pub fn new() -> UseScratch {
        UseScratch {
            scratch_space : capnp::common::allocate_zeroed_words(SCRATCH_SIZE * 6)
        }
    }

    fn new_builder<'a>(&mut self, idx : uint) -> capnp::message::ScratchSpaceMallocMessageBuilder<'a> {
        assert!(idx < 6);
        unsafe {
            capnp::message::ScratchSpaceMallocMessageBuilder::new_default(
                std::mem::transmute(
                    std::raw::Slice { data : self.scratch_space.as_slice().unsafe_ref(idx * SCRATCH_SIZE),
                                      len : SCRATCH_SIZE }))
        }
    }
}

macro_rules! pass_by_object(
    ( $testcase:ident, $reuse:ident, $iters:expr ) => ({
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = $reuse.new_builder(0);
                let mut messageRes = $reuse.new_builder(1);

                let request = messageReq.init_root::<$testcase::RequestBuilder>();
                let response = messageRes.init_root::<$testcase::ResponseBuilder>();
                let expected = $testcase::setup_request(&mut rng, request);

                let requestReader = request.as_reader();
                $testcase::handle_request(requestReader, response);

                let responseReader = response.as_reader();
                if !$testcase::check_response(responseReader, expected) {
                    fail!("Incorrect response.");
                }
            }
        });
    )

macro_rules! pass_by_bytes(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr ) => ({
            let mut requestBytes = std::vec::Vec::from_elem(SCRATCH_SIZE * 8, 0u8);
            let mut responseBytes = std::vec::Vec::from_elem(SCRATCH_SIZE * 8, 0u8);
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = $reuse.new_builder(0);
                let mut messageRes = $reuse.new_builder(1);

                let request = messageReq.init_root::<$testcase::RequestBuilder>();
                let response = messageRes.init_root::<$testcase::ResponseBuilder>();
                let expected = $testcase::setup_request(&mut rng, request);

                {
                    let mut writer = capnp::io::ArrayOutputStream::new(requestBytes.as_mut_slice());
                    $compression::write_buffered(&mut writer, &messageReq)
                }

                let messageReader = $compression::new_buffered_reader(
                    &mut capnp::io::ArrayInputStream::new(requestBytes.as_slice()),
                    capnp::message::DefaultReaderOptions);

                let requestReader : $testcase::RequestReader = messageReader.get_root();
                $testcase::handle_request(requestReader, response);

                {
                    let mut writer = capnp::io::ArrayOutputStream::new(responseBytes.as_mut_slice());
                    $compression::write_buffered(&mut writer, &messageRes)
                }

                let messageReader = $compression::new_buffered_reader(
                    &mut capnp::io::ArrayInputStream::new(responseBytes.as_slice()),
                    capnp::message::DefaultReaderOptions);

                let responseReader : $testcase::ResponseReader = messageReader.get_root();
                if !$testcase::check_response(responseReader, expected) {
                    fail!("Incorrect response.");
                }
            }
        });
    )

macro_rules! server(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr, $input:expr, $output:expr) => ({
            let mut outBuffered = capnp::io::BufferedOutputStreamWrapper::new(&mut $output);
            let mut inBuffered = capnp::io::BufferedInputStreamWrapper::new(&mut $input);
            for _ in range(0, $iters) {
                let mut messageRes = $reuse.new_builder(0);

                let response = messageRes.init_root::<$testcase::ResponseBuilder>();
                let messageReader = $compression::new_buffered_reader(
                    &mut inBuffered,
                    capnp::message::DefaultReaderOptions);
                let requestReader : $testcase::RequestReader = messageReader.get_root();
                $testcase::handle_request(requestReader, response);

                $compression::write_buffered(&mut outBuffered, &messageRes);
                outBuffered.flush().unwrap();
            }
        });
    )

macro_rules! sync_client(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr) => ({
            let mut outStream = std::io::stdio::stdout_raw();
            let mut inStream = std::io::stdio::stdin_raw();
            let mut inBuffered = capnp::io::BufferedInputStreamWrapper::new(&mut inStream);
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = $reuse.new_builder(0);

                let request = messageReq.init_root::<$testcase::RequestBuilder>();

                let expected = $testcase::setup_request(&mut rng, request);
                $compression::write(&mut outStream, &messageReq);

                let messageReader = $compression::new_buffered_reader(
                    &mut inBuffered,
                    capnp::message::DefaultReaderOptions);
                let responseReader : $testcase::ResponseReader = messageReader.get_root();
                assert!($testcase::check_response(responseReader, expected));

            }
        });
    )

macro_rules! pass_by_pipe(
    ( $testcase:ident, $reuse:ident, $compression:ident, $iters:expr) => ({
        use std::io::process;

        let mut args = std::os::args();
        *args.get_mut(2) = "client".to_owned();

        let mut command = process::Command::new(args.get(0).as_slice());
        command.args(args.slice(1, args.len()));
        command.stdin(process::CreatePipe(true, false));
        command.stdout(process::CreatePipe(false, true));
        command.stderr(process::Ignored);
        match command.spawn() {
            Ok(ref mut p) => {
                let mut childStdOut = p.stdout.take().unwrap();
                let mut childStdIn = p.stdin.take().unwrap();

                server!($testcase, $reuse, $compression, $iters, childStdOut, childStdIn);
                println!("{}", p.wait());
            }
            Err(e) => {
                println!("could not start process: {}", e);
            }
        }
    });
    )

macro_rules! do_testcase(
    ( $testcase:ident, $mode:expr, $reuse:ident, $compression:ident, $iters:expr ) => ({
            match $mode.as_slice() {
                "object" => pass_by_object!($testcase, $reuse, $iters),
                "bytes" => pass_by_bytes!($testcase, $reuse, $compression, $iters),
                "client" => sync_client!($testcase, $reuse, $compression, $iters),
                "server" => {
                    let mut input = std::io::stdio::stdin_raw();
                    let mut output = std::io::stdio::stdout_raw();
                    server!($testcase, $reuse, $compression, $iters, input, output)
                }
                "pipe" => pass_by_pipe!($testcase, $reuse, $compression, $iters),
                s => fail!("unrecognized mode: {}", s)
            }
        });
    )

macro_rules! do_testcase1(
    ( $testcase:expr, $mode:expr, $reuse:ident, $compression:ident, $iters:expr) => ({
            match $testcase.as_slice() {
                "carsales" => do_testcase!(carsales, $mode, $reuse, $compression, $iters),
                "catrank" => do_testcase!(catrank, $mode, $reuse, $compression, $iters),
                "eval" => do_testcase!(eval, $mode, $reuse, $compression, $iters),
                s => fail!("unrecognized test case: {}", s)
            }
        });
    )

macro_rules! do_testcase2(
    ( $testcase:expr, $mode:expr, $reuse:expr, $compression:ident, $iters:expr) => ({
            match $reuse.as_slice() {
                "no-reuse" => {
                    let mut scratch = NoScratch;
                    do_testcase1!($testcase, $mode, scratch, $compression, $iters)
                }
                "reuse" => {
                    let mut scratch = UseScratch::new();
                    do_testcase1!($testcase, $mode, scratch, $compression, $iters)
                }
                s => fail!("unrecognized reuse option: {}", s)
            }
        });
    )

pub fn main() {
    let args = std::os::args();

    if args.len() != 6 {
        println!("USAGE: {} CASE MODE REUSE COMPRESSION ITERATION_COUNT", args.get(0));
        std::os::set_exit_status(1);
        return;
    }

    let iters = match from_str::<u64>(*args.get(5)) {
        Some (n) => n,
        None => {
            println!("Could not parse a u64 from: {}", args.get(5));
            std::os::set_exit_status(1);
            return;
        }
    };

    match args.get(4).as_slice() {
        "none" => do_testcase2!(args.get(1), args.get(2),  args.get(3), Uncompressed, iters),
        "packed" => do_testcase2!(args.get(1), args.get(2), args.get(3), Packed, iters),
        s => fail!("unrecognized compression: {}", s)
    }
}
<|endoftext|>


<commit_before>extern crate aoc_2018;
#[macro_use]
extern crate bencher;

use bencher::Bencher;

use aoc_2018::get_impl;

const INPUTS: &[&[u8]] = &[
    include_bytes!("../inputs/01.txt"),
    include_bytes!("../inputs/02.txt"),
];

fn test_part1(day: u32, bench: &mut Bencher) {
    bench.iter(|| {
        let input = INPUTS[day as usize - 1];
        let mut instance = get_impl(day);
        instance.part1(&mut input.as_ref())
    })
}

fn test_part2(day: u32, bench: &mut Bencher) {
    bench.iter(|| {
        let input = INPUTS[day as usize - 1];
        let mut instance = get_impl(day);
        instance.part2(&mut input.as_ref())
    })
}

fn day1_part1(bench: &mut Bencher) {
    test_part1(1, bench)
}

fn day1_part2(bench: &mut Bencher) {
    test_part2(1, bench)
}

fn day2_part1(bench: &mut Bencher) {
    test_part1(2, bench)
}

fn day2_part2(bench: &mut Bencher) {
    test_part2(2, bench)
}

benchmark_group!(day1, day1_part1, day1_part2);
benchmark_group!(day2, day2_part1, day2_part2);

benchmark_main!(day1, day2);
<commit_msg>Use a macro for benchmarking.<commit_after>extern crate aoc_2018;
#[macro_use]
extern crate bencher;

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

use bencher::Bencher;

use aoc_2018::get_impl;

fn get_input(day: u32) -> Vec<u8> {
    let filename = format!("inputs/{:02}.txt", day);

    let mut buf = Vec::new();
    let mut file = File::open(&filename).unwrap();

    file.read_to_end(&mut buf).unwrap();

    buf
}

fn test_part1(day: u32, bench: &mut Bencher) {
    let input = get_input(day);
    bench.iter(|| {
        let mut instance = get_impl(day);
        instance.part1(&mut input.as_slice())
    })
}

fn test_part2(day: u32, bench: &mut Bencher) {
    let input = get_input(day);
    bench.iter(|| {
        let mut instance = get_impl(day);
        instance.part2(&mut input.as_slice())
    })
}

macro_rules! day_bench {

    ( $name:ident, $day:expr ) => {
            pub mod $name {
                use super::*;
                pub fn part1(bench: & mut Bencher) {
                test_part1( $day, bench);
                }
                pub fn part2(bench: & mut Bencher) {
                test_part2( $day, bench);
                }
            }
            benchmark_group!( $name, $name::part1, $name::part2);
    };
}

day_bench!(day01, 1);
day_bench!(day02, 2);
day_bench!(day03, 3);
day_bench!(day04, 4);
day_bench!(day05, 5);
day_bench!(day06, 6);
day_bench!(day07, 7);
day_bench!(day08, 8);
day_bench!(day09, 9);
day_bench!(day10, 10);
day_bench!(day11, 11);
day_bench!(day12, 12);
day_bench!(day13, 13);
day_bench!(day14, 14);
day_bench!(day15, 15);
day_bench!(day16, 16);
day_bench!(day17, 17);

benchmark_main!(day01, day02, day03, day04, day05,
                day06, day07, day08, day09, day10,
                day11, day12, day13, day14, day15,
                day16, day17);
<|endoftext|>


<commit_before>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

use aws_config::meta::region::RegionProviderChain;
use aws_sdk_ec2::{Client, Error, Region, PKG_VERSION};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opt {
    /// The AWS Region.
    #[structopt(short, long)]
    region: Option<String>,

    /// Whether to display additional runtime information.
    #[structopt(short, long)]
    verbose: bool,
}

/// Shows the scheduled events for the Amazon Elastic Compute Cloud (Amazon EC2) instances in the Region.
async fn show_events(reg: &'static str) {
    /*
        let region = Region::new(reg.clone());
        let config = aws_sdk_ec2::Config::builder().region(region).build();
        let client = Client::from_conf(config);
    */

    //let reg_slice: &str = Box::leak(reg.into_boxed_str());

    let region_provider = RegionProviderChain::default_provider().or_else(reg);
    let config = aws_config::from_env().region(region_provider).load().await;
    let client = Client::new(&config);

    let resp = client.describe_instance_status().send().await;

    println!("Instances in region {}:", reg);
    println!();

    for status in resp.unwrap().instance_statuses.unwrap_or_default() {
        println!(
            "  Events scheduled for instance ID: {}",
            status.instance_id.as_deref().unwrap_or_default()
        );
        for event in status.events.unwrap_or_default() {
            println!("    Event ID:     {}", event.instance_event_id.unwrap());
            println!("    Description:  {}", event.description.unwrap());
            /* Event codes:
               InstanceReboot
               InstanceRetirement
               InstanceStop
               SystemMaintenance
               SystemReboot
               Unknown
            */
            println!("    Event code:   {}", event.code.unwrap().as_ref());
            println!();
        }
    }
}

/// Lists the events of your EC2 instances in all available regions.
/// # Arguments
///
/// * `[-r REGION]` - The Region in which the client is created.
///    If not supplied, uses the value of the **AWS_REGION** environment variable.
///    If the environment variable is not set, defaults to **us-west-2**.
/// * `[-v]` - Whether to display additional information.
#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt::init();
    let Opt { region, verbose } = Opt::from_args();

    let region_provider = RegionProviderChain::first_try(region.map(Region::new))
        .or_default_provider()
        .or_else(Region::new("us-west-2"));
    println!();

    if verbose {
        println!("EC2 client version: {}", PKG_VERSION);
        println!(
            "Region:             {}",
            region_provider.region().await.unwrap().as_ref()
        );
        println!();
    }

    let shared_config = aws_config::from_env().region(region_provider).load().await;
    let client = Client::new(&shared_config);

    // Get list of available regions.
    let resp = client.describe_regions().send().await;

    // Show the events for that EC2 instances in that Region.
    for region in resp.unwrap().regions.unwrap_or_default() {
        let reg: &'static str = Box::leak(region.region_name.unwrap().into_boxed_str());
        show_events(reg).await;
    }

    Ok(())
}
<commit_msg>Update list-all-instance-events.rs<commit_after>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

use aws_config::meta::region::RegionProviderChain;
use aws_sdk_ec2::{Client, Error, Region, PKG_VERSION};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opt {
    /// The AWS Region.
    #[structopt(short, long)]
    region: Option<String>,

    /// Whether to display additional runtime information.
    #[structopt(short, long)]
    verbose: bool,
}

/// Shows the scheduled events for the Amazon Elastic Compute Cloud (Amazon EC2) instances in the Region.
async fn show_events(reg: &'static str) {
    let region_provider = RegionProviderChain::default_provider().or_else(reg);
    let config = aws_config::from_env().region(region_provider).load().await;
    let client = Client::new(&config);

    let resp = client.describe_instance_status().send().await;

    println!("Instances in region {}:", reg);
    println!();

    for status in resp.unwrap().instance_statuses.unwrap_or_default() {
        println!(
            "  Events scheduled for instance ID: {}",
            status.instance_id.as_deref().unwrap_or_default()
        );
        for event in status.events.unwrap_or_default() {
            println!("    Event ID:     {}", event.instance_event_id.unwrap());
            println!("    Description:  {}", event.description.unwrap());
            /* Event codes:
               InstanceReboot
               InstanceRetirement
               InstanceStop
               SystemMaintenance
               SystemReboot
               Unknown
            */
            println!("    Event code:   {}", event.code.unwrap().as_ref());
            println!();
        }
    }
}

/// Lists the events of your EC2 instances in all available regions.
/// # Arguments
///
/// * `[-r REGION]` - The Region in which the client is created.
///    If not supplied, uses the value of the **AWS_REGION** environment variable.
///    If the environment variable is not set, defaults to **us-west-2**.
/// * `[-v]` - Whether to display additional information.
#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt::init();
    let Opt { region, verbose } = Opt::from_args();

    let region_provider = RegionProviderChain::first_try(region.map(Region::new))
        .or_default_provider()
        .or_else(Region::new("us-west-2"));
    println!();

    if verbose {
        println!("EC2 client version: {}", PKG_VERSION);
        println!(
            "Region:             {}",
            region_provider.region().await.unwrap().as_ref()
        );
        println!();
    }

    let shared_config = aws_config::from_env().region(region_provider).load().await;
    let client = Client::new(&shared_config);

    // Get list of available regions.
    let resp = client.describe_regions().send().await;

    // Show the events for that EC2 instances in that Region.
    for region in resp.unwrap().regions.unwrap_or_default() {
        let reg: &'static str = Box::leak(region.region_name.unwrap().into_boxed_str());
        show_events(reg).await;
    }

    Ok(())
}
<|endoftext|>


<commit_before>/// Defines a one-to-one association for the child table. This macro should be
/// called with the name of the parent struct, followed by any options, followed
/// by the entire struct body. The struct *must* be annotated with
/// `#[table_name = "something"]`. Both the parent and child structs must
/// implement [`Identifiable`][identifiable].
///
/// [identifiable]: associations/trait.Identifiable.html
///
/// # Options
///
/// ## `foreign_key`
///
/// Required. The name of the foreign key column for this association.
///
/// # Examples
///
/// ```no_run
/// # #[macro_use] extern crate diesel;
/// # table! { users { id -> Integer, } }
/// # table! { posts { id -> Integer, user_id -> Integer, } }
/// pub struct User {
///     id: i32,
/// }
/// # impl_Identifiable! { #[table_name(users)] struct User { id: i32, } }
///
/// pub struct Post {
///     id: i32,
///     user_id: i32,
/// }
/// # impl_Identifiable! { #[table_name(posts)] struct Post { id: i32, user_id: i32, } }
///
/// BelongsTo! {
///     (User, foreign_key = user_id)
///     #[table_name(posts)]
///     struct Post {
///         id: i32,
///         user_id: i32,
///     }
/// }
/// # fn main() {}
/// ```
/// This macro cannot be used with tuple structs.
#[macro_export]
macro_rules! BelongsTo {
    // Format arguments
    (
        ($parent_struct:ident, foreign_key = $foreign_key_name:ident)
        $($rest:tt)*
    ) => {
        BelongsTo! {
            (
                parent_struct = $parent_struct,
                foreign_key_name = $foreign_key_name,
            )
            $($rest)*
        }
    };

    // Extract table name from struct
    (
        ($($args:tt)*)
        #[table_name($table_name:ident)]
        $($rest:tt)*
    ) => {
        BelongsTo! {
            (
                $($args)*
                child_table_name = $table_name,
            )
            $($rest)*
        }
    };

    // Strip meta items, pub (if present) and struct from definition
    (
        $args:tt
        $(#[$ignore:meta])*
        $(pub)* struct $($body:tt)*
    ) => {
        BelongsTo! {
            $args
            $($body)*
        }
    };

    // Receive parsed fields of normal struct from `__diesel_parse_struct_body`
    // Next we need to get the foreign key field in order to determine if it's optional.
    // These patterns must appear above those which start with an ident to compile
    (
        (
            struct_name = $struct_name:ident,
            parent_struct = $parent_struct:ident,
            foreign_key_name = $foreign_key_name:ident,
            $($remaining_arguments:tt)*
        ),
        fields = $fields:tt,
    ) => {
        __diesel_field_with_column_name! {
            (
                fields = $fields,
                struct_name = $struct_name,
                parent_struct = $parent_struct,
                foreign_key_name = $foreign_key_name,
                $($remaining_arguments)*
            ),
            callback = BelongsTo,
            target = $foreign_key_name,
            fields = $fields,
        }
    };

    // Receive the foreign key field from __diesel_field_with_column_name!
    (
        (
            fields = $fields:tt,
            $($remaining_args:tt)*
        ),
        found_field_with_column_name = $ignore:ident,
        field = {
            field_name: $ignore2:ident,
            column_name: $ignore3:ident,
            field_ty: $ignore4:ty,
            field_kind: $foreign_key_kind:ident,
            inner_field_ty: $foreign_key_ty:ty,
            $($rest:tt)*
        },
    ) => {
        BelongsTo! {
            (
                foreign_key_ty = $foreign_key_ty,
                foreign_key_kind = $foreign_key_kind,
                $($remaining_args)*
            ),
            fields = $fields,
        }
    };

    // Generate code when FK is not optional
    (
        (
            foreign_key_ty = $foreign_key_ty:ty,
            foreign_key_kind = regular,
            struct_name = $struct_name:ident,
            parent_struct = $parent_struct:ident,
            foreign_key_name = $foreign_key_name:ident,
            child_table_name = $child_table_name:ident,
        ),
        $($rest:tt)*
    ) => {
        impl $crate::associations::BelongsTo<$parent_struct> for $struct_name {
            type ForeignKey = $foreign_key_ty;
            type ForeignKeyColumn = $child_table_name::$foreign_key_name;

            fn foreign_key(&self) -> Option<&$foreign_key_ty> {
                Some(&self.$foreign_key_name)
            }

            fn foreign_key_column() -> Self::ForeignKeyColumn {
                $child_table_name::$foreign_key_name
            }
        }
    };

    // Generate code when FK is optional
    (
        (
            foreign_key_ty = $foreign_key_ty:ty,
            foreign_key_kind = option,
            struct_name = $struct_name:ident,
            parent_struct = $parent_struct:ident,
            foreign_key_name = $foreign_key_name:ident,
            child_table_name = $child_table_name:ident,
        ),
        $($rest:tt)*
    ) => {
        impl $crate::associations::BelongsTo<$parent_struct> for $struct_name {
            type ForeignKey = $foreign_key_ty;
            type ForeignKeyColumn = $child_table_name::$foreign_key_name;

            fn foreign_key(&self) -> Option<&$foreign_key_ty> {
                self.$foreign_key_name.as_ref()
            }

            fn foreign_key_column() -> Self::ForeignKeyColumn {
                $child_table_name::$foreign_key_name
            }
        }
    };

    // Handle struct with no generics
    (
        ($($args:tt)*)
        $struct_name:ident
        $body:tt $(;)*
    ) => {
        __diesel_parse_struct_body! {
            (
                struct_name = $struct_name,
                $($args)*
            ),
            callback = BelongsTo,
            body = $body,
        }
    };
}
<commit_msg>Hide macro that isn't public API<commit_after>#[macro_export]
#[doc(hidden)]
macro_rules! BelongsTo {
    // Format arguments
    (
        ($parent_struct:ident, foreign_key = $foreign_key_name:ident)
        $($rest:tt)*
    ) => {
        BelongsTo! {
            (
                parent_struct = $parent_struct,
                foreign_key_name = $foreign_key_name,
            )
            $($rest)*
        }
    };

    // Extract table name from struct
    (
        ($($args:tt)*)
        #[table_name($table_name:ident)]
        $($rest:tt)*
    ) => {
        BelongsTo! {
            (
                $($args)*
                child_table_name = $table_name,
            )
            $($rest)*
        }
    };

    // Strip meta items, pub (if present) and struct from definition
    (
        $args:tt
        $(#[$ignore:meta])*
        $(pub)* struct $($body:tt)*
    ) => {
        BelongsTo! {
            $args
            $($body)*
        }
    };

    // Receive parsed fields of normal struct from `__diesel_parse_struct_body`
    // Next we need to get the foreign key field in order to determine if it's optional.
    // These patterns must appear above those which start with an ident to compile
    (
        (
            struct_name = $struct_name:ident,
            parent_struct = $parent_struct:ident,
            foreign_key_name = $foreign_key_name:ident,
            $($remaining_arguments:tt)*
        ),
        fields = $fields:tt,
    ) => {
        __diesel_field_with_column_name! {
            (
                fields = $fields,
                struct_name = $struct_name,
                parent_struct = $parent_struct,
                foreign_key_name = $foreign_key_name,
                $($remaining_arguments)*
            ),
            callback = BelongsTo,
            target = $foreign_key_name,
            fields = $fields,
        }
    };

    // Receive the foreign key field from __diesel_field_with_column_name!
    (
        (
            fields = $fields:tt,
            $($remaining_args:tt)*
        ),
        found_field_with_column_name = $ignore:ident,
        field = {
            field_name: $ignore2:ident,
            column_name: $ignore3:ident,
            field_ty: $ignore4:ty,
            field_kind: $foreign_key_kind:ident,
            inner_field_ty: $foreign_key_ty:ty,
            $($rest:tt)*
        },
    ) => {
        BelongsTo! {
            (
                foreign_key_ty = $foreign_key_ty,
                foreign_key_kind = $foreign_key_kind,
                $($remaining_args)*
            ),
            fields = $fields,
        }
    };

    // Generate code when FK is not optional
    (
        (
            foreign_key_ty = $foreign_key_ty:ty,
            foreign_key_kind = regular,
            struct_name = $struct_name:ident,
            parent_struct = $parent_struct:ident,
            foreign_key_name = $foreign_key_name:ident,
            child_table_name = $child_table_name:ident,
        ),
        $($rest:tt)*
    ) => {
        impl $crate::associations::BelongsTo<$parent_struct> for $struct_name {
            type ForeignKey = $foreign_key_ty;
            type ForeignKeyColumn = $child_table_name::$foreign_key_name;

            fn foreign_key(&self) -> Option<&$foreign_key_ty> {
                Some(&self.$foreign_key_name)
            }

            fn foreign_key_column() -> Self::ForeignKeyColumn {
                $child_table_name::$foreign_key_name
            }
        }
    };

    // Generate code when FK is optional
    (
        (
            foreign_key_ty = $foreign_key_ty:ty,
            foreign_key_kind = option,
            struct_name = $struct_name:ident,
            parent_struct = $parent_struct:ident,
            foreign_key_name = $foreign_key_name:ident,
            child_table_name = $child_table_name:ident,
        ),
        $($rest:tt)*
    ) => {
        impl $crate::associations::BelongsTo<$parent_struct> for $struct_name {
            type ForeignKey = $foreign_key_ty;
            type ForeignKeyColumn = $child_table_name::$foreign_key_name;

            fn foreign_key(&self) -> Option<&$foreign_key_ty> {
                self.$foreign_key_name.as_ref()
            }

            fn foreign_key_column() -> Self::ForeignKeyColumn {
                $child_table_name::$foreign_key_name
            }
        }
    };

    // Handle struct with no generics
    (
        ($($args:tt)*)
        $struct_name:ident
        $body:tt $(;)*
    ) => {
        __diesel_parse_struct_body! {
            (
                struct_name = $struct_name,
                $($args)*
            ),
            callback = BelongsTo,
            body = $body,
        }
    };
}
<|endoftext|>


<commit_before>use analysis::rust_type::Result;
use env::Env;
use gobjects::GStatus;
use library;
use library::*;
use nameutil::crate_name;
use traits::*;

// FIXME: This module needs redundant allocations audit
// TODO: ffi_type computations should be cached

pub fn ffi_type(env: &Env, tid: library::TypeId, c_type: &str) -> Result {
    let (ptr, inner) = rustify_pointers(c_type);
    let res = if ptr.is_empty() {
        if let Some(c_tid) = env.library.find_type(0, c_type) {
            // Fast track plain fundamental types avoiding some checks
            if env.library.type_(c_tid).maybe_ref_as::<Fundamental>().is_some() {
                if let &library::Type::ArraySized(_, size) = env.library.type_(tid) {
                    ffi_inner(env, c_tid, c_type.into())
                        .map_any(|s| format!("[{}; {}]", s, size))
                }
                else {
                    ffi_inner(env, c_tid, c_type.into())
                }
            }
            else { // c_type isn't fundamental
                ffi_inner(env, tid, inner)
            }
        }
        else { // c_type doesn't match any type in the library by name
            ffi_inner(env, tid, inner)
        }
    }
    else { // ptr not empty
        ffi_inner(env, tid, inner)
            .map_any(|s| format!("{} {}", ptr, s))
    };
    trace!("ffi_type({:?}, {}) -> {:?}", tid, c_type, res);
    res
}

fn ffi_inner(env: &Env, tid: library::TypeId, inner: String) -> Result {
    match *env.library.type_(tid) {
        Type::Fundamental(fund) => {
            use library::Fundamental::*;
            let inner = match fund {
                None => "c_void",
                Boolean => "gboolean",
                Int8 => "i8",
                UInt8 => "u8",
                Int16 => "i16",
                UInt16 => "u16",
                Int32 => "i32",
                UInt32 => "u32",
                Int64 => "i64",
                UInt64 => "u64",
                Char => "c_char",
                UChar => "c_char",
                Short => "c_short",
                UShort => "c_ushort",
                Int => "c_int",
                UInt => "c_uint",
                Long => "c_long",
                ULong => "c_ulong",
                Size => "size_t",
                SSize => "ssize_t",
                Float => "c_float",
                Double => "c_double",
                UniChar => "u32",
                Utf8 => "c_char",
                Filename => "c_char",
                Type => "GType",
                Pointer => return Ok(inner),
                Unsupported => return Err(format!("[Unsupported type {}]", inner)),
                VarArgs => panic!("Should not reach here"),
            };
            Ok(inner.into())
        }
        Type::Record(..) | Type::Alias(..) | Type::Function(..) => {
            fix_name(env, tid, &inner)
        }
        Type::Array(inner_tid) => ffi_inner(env, inner_tid, inner),
        Type::ArraySized(inner_tid, size) => {
            match ffi_inner(env, inner_tid, inner) {
                Ok(s) => Ok(format!("[{}; {}]", s, size)),
                Err(s) => Err(format!("[{}; {}]", s, size)),
            }
        }
        Type::List(..) | Type::SList(..) => Ok(inner),
        _ => {
            if let Some(glib_name) = env.library.type_(tid).get_glib_name() {
                if inner != glib_name {
                    let msg = format!("[c:type mismatch {} != {} of {}]", inner, glib_name,
                      env.library.type_(tid).get_name());
                    warn!("{}", msg);
                    Err(msg)
                }
                else {
                    fix_name(env, tid, &inner)
                }
            }
            else {
                let msg = format!("[Missing glib_name of {}, can't match != {}]",
                                  env.library.type_(tid).get_name(), inner);
                warn!("{}", msg);
                Err(msg)
            }
        }
    }
}

fn fix_name(env: &Env, type_id: library::TypeId, name: &str) -> Result {
    if type_id.ns_id == library::INTERNAL_NAMESPACE {
        Ok(name.into())
    } else {
        let name_with_prefix = if type_id.ns_id == library::MAIN_NAMESPACE {
            name.into()
        } else {
            format!("{}_ffi::{}", fix_namespace(env, type_id), name)
        };
        if env.type_status_sys(&type_id.full_name(&env.library)) == GStatus::Ignore {
            Err(name_with_prefix)
        } else {
            Ok(name_with_prefix)
        }
    }
}

//TODO: check if need to use in non sys codegen
fn fix_namespace(env: &Env, type_id: library::TypeId) -> String {
    crate_name(&env.library.namespace(type_id.ns_id).name)
}

fn rustify_pointers(c_type: &str) -> (String, String) {
    let mut input = c_type.trim();
    let leading_const = input.starts_with("const ");
    if leading_const {
        input = &input[6..];
    }
    let end = [
        input.find(" const"),
        input.find("*const"),
        input.find("*"),
        Some(input.len()),
    ].iter().filter_map(|&x| x).min().unwrap();
    let inner = input[..end].trim().into();

    let mut ptrs: Vec<_> = input[end..].rsplit('*').skip(1)
        .map(|s| if s.contains("const") { "*const" } else { "*mut" }).collect();
    if let (true, Some(p)) = (leading_const, ptrs.last_mut()) {
        *p = "*const";
    }

    let res = (ptrs.connect(" "), inner);
    trace!("rustify `{}` -> `{}` `{}`", c_type, res.0, res.1);
    res
}

#[cfg(test)]
mod tests {
    use super::rustify_pointers as rustify_ptr;

    fn s(x: &str, y: &str) -> (String, String) {
        (x.into(), y.into())
    }

    #[test]
    fn rustify_pointers() {
        assert_eq!(rustify_ptr("char"), s("", "char"));
        assert_eq!(rustify_ptr("char*"), s("*mut", "char"));
        assert_eq!(rustify_ptr("const char*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const *"), s("*const", "char"));
        assert_eq!(rustify_ptr(" char * * "), s("*mut *mut", "char"));
        assert_eq!(rustify_ptr("const char**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("char const**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("const char* const*"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char const * const *"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char* const*"), s("*const *mut", "char"));
    }
}
<commit_msg>Fix void* parameters<commit_after>use analysis::rust_type::Result;
use env::Env;
use gobjects::GStatus;
use library;
use library::*;
use nameutil::crate_name;
use traits::*;

// FIXME: This module needs redundant allocations audit
// TODO: ffi_type computations should be cached

pub fn ffi_type(env: &Env, tid: library::TypeId, c_type: &str) -> Result {
    let (ptr, inner) = rustify_pointers(c_type);
    let res = if ptr.is_empty() {
        if let Some(c_tid) = env.library.find_type(0, c_type) {
            // Fast track plain fundamental types avoiding some checks
            if env.library.type_(c_tid).maybe_ref_as::<Fundamental>().is_some() {
                if let &library::Type::ArraySized(_, size) = env.library.type_(tid) {
                    ffi_inner(env, c_tid, c_type.into())
                        .map_any(|s| format!("[{}; {}]", s, size))
                }
                else {
                    ffi_inner(env, c_tid, c_type.into())
                }
            }
            else { // c_type isn't fundamental
                ffi_inner(env, tid, inner)
            }
        }
        else { // c_type doesn't match any type in the library by name
            ffi_inner(env, tid, inner)
        }
    }
    else { // ptr not empty
        ffi_inner(env, tid, inner)
            .map_any(|s| format!("{} {}", ptr, s))
    };
    trace!("ffi_type({:?}, {}) -> {:?}", tid, c_type, res);
    res
}

fn ffi_inner(env: &Env, tid: library::TypeId, inner: String) -> Result {
    match *env.library.type_(tid) {
        Type::Fundamental(fund) => {
            use library::Fundamental::*;
            let inner = match fund {
                None => "c_void",
                Boolean => "gboolean",
                Int8 => "i8",
                UInt8 => "u8",
                Int16 => "i16",
                UInt16 => "u16",
                Int32 => "i32",
                UInt32 => "u32",
                Int64 => "i64",
                UInt64 => "u64",
                Char => "c_char",
                UChar => "c_char",
                Short => "c_short",
                UShort => "c_ushort",
                Int => "c_int",
                UInt => "c_uint",
                Long => "c_long",
                ULong => "c_ulong",
                Size => "size_t",
                SSize => "ssize_t",
                Float => "c_float",
                Double => "c_double",
                UniChar => "u32",
                Utf8 => "c_char",
                Filename => "c_char",
                Type => "GType",
                Pointer => match &inner[..]  {
                    "void" => "c_void",
                    _ => return Ok(inner),
                },
                Unsupported => return Err(format!("[Unsupported type {}]", inner)),
                VarArgs => panic!("Should not reach here"),
            };
            Ok(inner.into())
        }
        Type::Record(..) | Type::Alias(..) | Type::Function(..) => {
            fix_name(env, tid, &inner)
        }
        Type::Array(inner_tid) => ffi_inner(env, inner_tid, inner),
        Type::ArraySized(inner_tid, size) => {
            match ffi_inner(env, inner_tid, inner) {
                Ok(s) => Ok(format!("[{}; {}]", s, size)),
                Err(s) => Err(format!("[{}; {}]", s, size)),
            }
        }
        Type::List(..) | Type::SList(..) => Ok(inner),
        _ => {
            if let Some(glib_name) = env.library.type_(tid).get_glib_name() {
                if inner != glib_name {
                    let msg = format!("[c:type mismatch {} != {} of {}]", inner, glib_name,
                      env.library.type_(tid).get_name());
                    warn!("{}", msg);
                    Err(msg)
                }
                else {
                    fix_name(env, tid, &inner)
                }
            }
            else {
                let msg = format!("[Missing glib_name of {}, can't match != {}]",
                                  env.library.type_(tid).get_name(), inner);
                warn!("{}", msg);
                Err(msg)
            }
        }
    }
}

fn fix_name(env: &Env, type_id: library::TypeId, name: &str) -> Result {
    if type_id.ns_id == library::INTERNAL_NAMESPACE {
        Ok(name.into())
    } else {
        let name_with_prefix = if type_id.ns_id == library::MAIN_NAMESPACE {
            name.into()
        } else {
            format!("{}_ffi::{}", fix_namespace(env, type_id), name)
        };
        if env.type_status_sys(&type_id.full_name(&env.library)) == GStatus::Ignore {
            Err(name_with_prefix)
        } else {
            Ok(name_with_prefix)
        }
    }
}

//TODO: check if need to use in non sys codegen
fn fix_namespace(env: &Env, type_id: library::TypeId) -> String {
    crate_name(&env.library.namespace(type_id.ns_id).name)
}

fn rustify_pointers(c_type: &str) -> (String, String) {
    let mut input = c_type.trim();
    let leading_const = input.starts_with("const ");
    if leading_const {
        input = &input[6..];
    }
    let end = [
        input.find(" const"),
        input.find("*const"),
        input.find("*"),
        Some(input.len()),
    ].iter().filter_map(|&x| x).min().unwrap();
    let inner = input[..end].trim().into();

    let mut ptrs: Vec<_> = input[end..].rsplit('*').skip(1)
        .map(|s| if s.contains("const") { "*const" } else { "*mut" }).collect();
    if let (true, Some(p)) = (leading_const, ptrs.last_mut()) {
        *p = "*const";
    }

    let res = (ptrs.connect(" "), inner);
    trace!("rustify `{}` -> `{}` `{}`", c_type, res.0, res.1);
    res
}

#[cfg(test)]
mod tests {
    use super::rustify_pointers as rustify_ptr;

    fn s(x: &str, y: &str) -> (String, String) {
        (x.into(), y.into())
    }

    #[test]
    fn rustify_pointers() {
        assert_eq!(rustify_ptr("char"), s("", "char"));
        assert_eq!(rustify_ptr("char*"), s("*mut", "char"));
        assert_eq!(rustify_ptr("const char*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const *"), s("*const", "char"));
        assert_eq!(rustify_ptr(" char * * "), s("*mut *mut", "char"));
        assert_eq!(rustify_ptr("const char**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("char const**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("const char* const*"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char const * const *"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char* const*"), s("*const *mut", "char"));
    }
}
<|endoftext|>


<commit_before>mod batch;
use self::batch::generate_batch_payload;
pub use self::batch::BatchItem;
use azure_sdk_core::errors::{check_status_extract_body, check_status_extract_headers_and_body, extract_status_and_body, AzureError, UnexpectedHTTPResult};
use azure_sdk_storage_core::client::Client;
use azure_sdk_storage_core::{get_default_json_mime, get_json_mime_nometadata, get_json_mime_fullmetadata, ServiceType};
use futures::future::*;
use hyper::{
    client::ResponseFuture,
    header::{self, HeaderValue},
    Method, StatusCode,
};
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json;
use futures::Stream;
use futures::stream;
use http::HeaderMap;

const TABLE_TABLES: &str = "TABLES";

pub struct TableService {
    client: Client,
}

impl TableService {
    pub fn new(client: Client) -> Self {
        TableService { client }
    }

    pub fn list_tables(&self) -> impl Future<Item = Vec<String>, Error = AzureError> {
        self.query_entities(TABLE_TABLES, None).and_then(|entities| {
            let e: Vec<String> = entities.into_iter().map(|x: TableEntity| x.TableName).collect();
            ok(e)
        })
    }

    // Create table if not exists.
    pub fn create_table<T: Into<String>>(&self, table_name: T) -> impl Future<Item = (), Error = AzureError> {
        let body = &serde_json::to_string(&TableEntity {
            TableName: table_name.into(),
        })
        .unwrap();
        debug!("body == {}", body);
        let req = self.request_with_default_header(TABLE_TABLES, &Method::POST, Some(body), false);

        done(req)
            .from_err()
            .and_then(move |future_response| check_status_extract_body(future_response, StatusCode::CREATED).and_then(move |_| ok(())))
    }

    pub fn get_entity<T: DeserializeOwned>(
        &self,
        table_name: &str,
        partition_key: &str,
        row_key: &str,
    ) -> impl Future<Item = Option<T>, Error = AzureError> {
        let path = &entity_path(table_name, partition_key, row_key);
        let req = self.request_with_default_header(path, &Method::GET, None, false);
        done(req).from_err().and_then(move |future_response| {
            extract_status_and_body(future_response).and_then(move |(status, body)| {
                if status == StatusCode::NOT_FOUND {
                    ok(None)
                } else if status != StatusCode::OK {
                    err(AzureError::UnexpectedHTTPResult(UnexpectedHTTPResult::new(
                        StatusCode::OK,
                        status,
                        &body,
                    )))
                } else {
                    match serde_json::from_str(&body) {
                        Ok(item) => ok(Some(item)),
                        Err(error) => err(error.into()),
                    }
                }
            })
        })
    }

    pub fn query_entities<T: DeserializeOwned>(
        &self,
        table_name: &str,
        query: Option<&str>,
    ) -> impl Future<Item = Vec<T>, Error = AzureError> {
        let mut path = table_name.to_owned();
        if let Some(clause) = query {
            path.push_str("?");
            path.push_str(clause);
        }

        let req = self.request_with_default_header(path.as_str(), &Method::GET, None, false);

        done(req).from_err().and_then(move |future_response| {
            check_status_extract_body(future_response, StatusCode::OK).and_then(move |body| {
                done(serde_json::from_str::<EntityCollection<T>>(&body))
                    .from_err()
                    .and_then(|ec| ok(ec.value))
            })
        })
    }

    fn query_entity_collection<T: DeserializeOwned>(
        &self,
        table_name: &str,
        query: Option<&str>,
        continuation: Option<&Continuation>,
        fullmetadata: bool,
    ) -> impl Future<Item = EntityCollection<T>, Error = AzureError> {
        let mut path = table_name.to_owned();
        path.push_str("?");
        if let Some(clause) = query {
            path.push_str(clause);
        }
        if let Some(cont) = continuation {
            path.push_str("&NextPartitionKey=");
            path.push_str(&cont.next_partition_key);
            path.push_str("&NextRowKey=");
            path.push_str(&cont.next_row_key);
        }

        let req = self.request_with_default_header(path.as_str(), &Method::GET, None, fullmetadata);

        done(req)
            .from_err()
            .and_then(move |future_response| check_status_extract_headers_and_body(future_response, StatusCode::OK))
            .and_then(move |(headers, body)| done({
                serde_json::from_slice::<EntityCollection<T>>(&body)
                .map(|mut ec| {
                    ec.continuation = continuation_from_headers(&headers);
                    ec
                })
             }).from_err())
    }

    fn stream_query_entities_metadata<'a, T: DeserializeOwned + 'a>(
        &'a self,
        table_name: &'a str,
        query: Option<&'a str>,
        fullmetadata: bool,
    ) ->  impl Stream<Item = T, Error = AzureError> + 'a {

        stream::unfold(ContinuationState::Start, move |cont_state| {
            let cont = match cont_state {
                ContinuationState::Start => None,
                ContinuationState::Next(Some(cont)) => Some(cont),
                ContinuationState::Next(None) => return None,
            };

            let mut path = table_name.to_owned();
            if let Some(clause) = query {
                path.push_str("?");
                path.push_str(clause);
            }

            let req = self.query_entity_collection(table_name, query, cont.as_ref(), fullmetadata);

            Some(req.map(move |ec| {
                (stream::iter_ok(ec.value), ContinuationState::Next(ec.continuation))
            }))
        })
        .flatten()
    }

    pub fn stream_query_entities<'a, T: DeserializeOwned + 'a>(
        &'a self,
        table_name: &'a str,
        query: Option<&'a str>,
    ) ->  impl Stream<Item = T, Error = AzureError> + 'a {
        self.stream_query_entities_metadata(table_name, query, false)
    }

    pub fn stream_query_entities_fullmetadata<'a, T: DeserializeOwned + 'a>(
        &'a self,
        table_name: &'a str,
        query: Option<&'a str>,
    ) ->  impl Stream<Item = T, Error = AzureError> + 'a {
        self.stream_query_entities_metadata(table_name, query, true)
    }

    fn _prepare_insert_entity<T>(&self, table_name: &str, entity: &T) -> Result<ResponseFuture, AzureError>
    where
        T: Serialize,
    {
        let obj_ser = serde_json::to_string(entity)?;
        self.request_with_default_header(table_name, &Method::POST, Some(&obj_ser), false)
    }

    pub fn insert_entity<T: Serialize>(&self, table_name: &str, entity: &T) -> impl Future<Item = (), Error = AzureError> {
        let req = self._prepare_insert_entity(table_name, entity);

        done(req)
            .from_err()
            .and_then(move |future_response| check_status_extract_body(future_response, StatusCode::CREATED).and_then(move |_| ok(())))
    }

    fn _prepare_update_entity<T>(
        &self,
        table_name: &str,
        partition_key: &str,
        row_key: &str,
        entity: &T,
    ) -> Result<ResponseFuture, AzureError>
    where
        T: Serialize,
    {
        let body = &serde_json::to_string(entity)?;
        let path = &entity_path(table_name, partition_key, row_key);
        self.request_with_default_header(path, &Method::PUT, Some(body), false)
    }

    pub fn update_entity<T: Serialize>(
        &self,
        table_name: &str,
        partition_key: &str,
        row_key: &str,
        entity: &T,
    ) -> impl Future<Item = (), Error = AzureError> {
        let req = self._prepare_update_entity(table_name, partition_key, row_key, entity);
        done(req)
            .from_err()
            .and_then(move |future_response| check_status_extract_body(future_response, StatusCode::NO_CONTENT).and_then(move |_| ok(())))
    }

    pub fn delete_entity(&self, table_name: &str, partition_key: &str, row_key: &str) -> impl Future<Item = (), Error = AzureError> {
        let path = &entity_path(table_name, partition_key, row_key);

        let req = self.request(path, &Method::DELETE, None, |ref mut request| {
            request.header(header::ACCEPT, HeaderValue::from_static(get_json_mime_nometadata()));
            request.header(header::IF_MATCH, header::HeaderValue::from_static("*"));
        });
        done(req)
            .from_err()
            .and_then(move |future_response| check_status_extract_body(future_response, StatusCode::NO_CONTENT).and_then(move |_| ok(())))
    }

    pub fn batch<T: Serialize>(
        &self,
        table_name: &str,
        partition_key: &str,
        batch_items: &[BatchItem<T>],
    ) -> impl Future<Item = (), Error = AzureError> {
        let payload = &generate_batch_payload(
            self.client.get_uri_prefix(ServiceType::Table).as_str(),
            table_name,
            partition_key,
            batch_items,
        );

        let req = self.request("$batch", &Method::POST, Some(payload), |ref mut request| {
            request.header(header::CONTENT_TYPE, header::HeaderValue::from_static(get_batch_mime()));
        });
        done(req).from_err().and_then(move |future_response| {
            check_status_extract_body(future_response, StatusCode::ACCEPTED).and_then(move |_| {
                // TODO deal with body response, handle batch failure.
                // let ref body = get_response_body(&mut response)?;
                // info!("{}", body);
                ok(())
            })
        })
    }

    fn request_with_default_header(&self, segment: &str, method: &Method, request_str: Option<&str>, fullmetadata: bool) -> Result<ResponseFuture, AzureError> {
        self.request(segment, method, request_str, |ref mut request| {
            if fullmetadata {
                request.header(header::ACCEPT, HeaderValue::from_static(get_json_mime_fullmetadata()));
            } else {
                request.header(header::ACCEPT, HeaderValue::from_static(get_json_mime_nometadata()));
            }
            request.header(header::ACCEPT, HeaderValue::from_static(get_json_mime_nometadata()));
            if request_str.is_some() {
                request.header(header::CONTENT_TYPE, HeaderValue::from_static(get_default_json_mime()));
            }
        })
    }

    fn request<F>(&self, segment: &str, method: &Method, request_str: Option<&str>, headers_func: F) -> Result<ResponseFuture, AzureError>
    where
        F: FnOnce(&mut ::http::request::Builder),
    {
        trace!("{:?} {}", method, segment);
        if let Some(body) = request_str {
            trace!("Request: {}", body);
        }

        let request_vec: Option<&[u8]> = match request_str {
            Some(s) => Some(s.as_bytes()),
            None => None,
        };

        self.client.perform_table_request(segment, method, headers_func, request_vec)
    }
}

const HEADER_NEXTPARTITIONKEY: &'static str = "x-ms-continuation-NextPartitionKey";
const HEADER_NEXTROWKEY: &'static str = "x-ms-continuation-NextRowKey";

fn continuation_from_headers(headers: &HeaderMap) -> Option<Continuation> {
    if headers.contains_key(HEADER_NEXTPARTITIONKEY) && headers.contains_key(HEADER_NEXTROWKEY){
        Some(Continuation {
            next_partition_key: headers[HEADER_NEXTPARTITIONKEY].to_str().unwrap().to_string(),
            next_row_key: headers[HEADER_NEXTROWKEY].to_str().unwrap().to_string(),
        })
    } else {
        None
    }
}

#[allow(non_snake_case)]
#[derive(Serialize, Deserialize)]
struct TableEntity {
    TableName: String,
}

#[derive(Deserialize)]
struct EntityCollection<T> {
    value: Vec<T>,
    #[serde(skip)]
    continuation: Option<Continuation>,
}

struct Continuation {
    next_partition_key: String,
    next_row_key: String,
}

enum ContinuationState {
    Start,
    Next(Option<Continuation>),
}

#[inline]
fn entity_path(table_name: &str, partition_key: &str, row_key: &str) -> String {
    table_name.to_owned() + "(PartitionKey='" + partition_key + "',RowKey='" + row_key + "')"
}

#[inline]
pub fn get_batch_mime() -> &'static str {
    "multipart/mixed; boundary=batch_a1e9d677-b28b-435e-a89e-87e6a768a431"
}
<commit_msg>TableStorage to wrap a service and a table into a single object<commit_after>mod batch;
use self::batch::generate_batch_payload;
pub use self::batch::BatchItem;
use azure_sdk_core::errors::{check_status_extract_body, check_status_extract_headers_and_body, extract_status_and_body, AzureError, UnexpectedHTTPResult};
use azure_sdk_storage_core::client::Client;
use azure_sdk_storage_core::{get_default_json_mime, get_json_mime_nometadata, get_json_mime_fullmetadata, ServiceType};
use futures::future::*;
use hyper::{
    client::ResponseFuture,
    header::{self, HeaderValue},
    Method, StatusCode,
};
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json;
use futures::Stream;
use futures::stream;
use http::HeaderMap;

const TABLE_TABLES: &str = "TABLES";

#[derive(Clone)]
pub struct TableService {
    client: Client,
}

impl TableService {
    pub fn new(client: Client) -> Self {
        TableService { client }
    }

    pub fn list_tables(&self) -> impl Future<Item = Vec<String>, Error = AzureError> {
        self.query_entities(TABLE_TABLES, None).and_then(|entities| {
            let e: Vec<String> = entities.into_iter().map(|x: TableEntity| x.TableName).collect();
            ok(e)
        })
    }

    // Create table if not exists.
    pub fn create_table<T: Into<String>>(&self, table_name: T) -> impl Future<Item = (), Error = AzureError> {
        let body = &serde_json::to_string(&TableEntity {
            TableName: table_name.into(),
        })
        .unwrap();
        debug!("body == {}", body);
        let req = self.request_with_default_header(TABLE_TABLES, &Method::POST, Some(body), false);

        done(req)
            .from_err()
            .and_then(move |future_response| check_status_extract_body(future_response, StatusCode::CREATED).and_then(move |_| ok(())))
    }

    pub fn get_entity<T: DeserializeOwned>(
        &self,
        table_name: &str,
        partition_key: &str,
        row_key: &str,
    ) -> impl Future<Item = Option<T>, Error = AzureError> {
        let path = &entity_path(table_name, partition_key, row_key);
        let req = self.request_with_default_header(path, &Method::GET, None, false);
        done(req).from_err().and_then(move |future_response| {
            extract_status_and_body(future_response).and_then(move |(status, body)| {
                if status == StatusCode::NOT_FOUND {
                    ok(None)
                } else if status != StatusCode::OK {
                    err(AzureError::UnexpectedHTTPResult(UnexpectedHTTPResult::new(
                        StatusCode::OK,
                        status,
                        &body,
                    )))
                } else {
                    match serde_json::from_str(&body) {
                        Ok(item) => ok(Some(item)),
                        Err(error) => err(error.into()),
                    }
                }
            })
        })
    }

    pub fn query_entities<T: DeserializeOwned>(
        &self,
        table_name: &str,
        query: Option<&str>,
    ) -> impl Future<Item = Vec<T>, Error = AzureError> {
        let mut path = table_name.to_owned();
        if let Some(clause) = query {
            path.push_str("?");
            path.push_str(clause);
        }

        let req = self.request_with_default_header(path.as_str(), &Method::GET, None, false);

        done(req).from_err().and_then(move |future_response| {
            check_status_extract_body(future_response, StatusCode::OK).and_then(move |body| {
                done(serde_json::from_str::<EntityCollection<T>>(&body))
                    .from_err()
                    .and_then(|ec| ok(ec.value))
            })
        })
    }

    fn query_entity_collection<T: DeserializeOwned>(
        &self,
        table_name: &str,
        query: Option<&str>,
        continuation: Option<&Continuation>,
        fullmetadata: bool,
    ) -> impl Future<Item = EntityCollection<T>, Error = AzureError> {
        let mut path = table_name.to_owned();
        path.push_str("?");
        if let Some(clause) = query {
            path.push_str(clause);
        }
        if let Some(cont) = continuation {
            path.push_str("&NextPartitionKey=");
            path.push_str(&cont.next_partition_key);
            path.push_str("&NextRowKey=");
            path.push_str(&cont.next_row_key);
        }

        let req = self.request_with_default_header(path.as_str(), &Method::GET, None, fullmetadata);

        done(req)
            .from_err()
            .and_then(move |future_response| check_status_extract_headers_and_body(future_response, StatusCode::OK))
            .and_then(move |(headers, body)| done({
                serde_json::from_slice::<EntityCollection<T>>(&body)
                .map(|mut ec| {
                    ec.continuation = continuation_from_headers(&headers);
                    ec
                })
             }).from_err())
    }

    fn stream_query_entities_metadata<'a, T: DeserializeOwned + 'a>(
        &'a self,
        table_name: &'a str,
        query: Option<&'a str>,
        fullmetadata: bool,
    ) ->  impl Stream<Item = T, Error = AzureError> + 'a {

        stream::unfold(ContinuationState::Start, move |cont_state| {
            let cont = match cont_state {
                ContinuationState::Start => None,
                ContinuationState::Next(Some(cont)) => Some(cont),
                ContinuationState::Next(None) => return None,
            };

            let mut path = table_name.to_owned();
            if let Some(clause) = query {
                path.push_str("?");
                path.push_str(clause);
            }

            let req = self.query_entity_collection(table_name, query, cont.as_ref(), fullmetadata);

            Some(req.map(move |ec| {
                (stream::iter_ok(ec.value), ContinuationState::Next(ec.continuation))
            }))
        })
        .flatten()
    }

    pub fn stream_query_entities<'a, T: DeserializeOwned + 'a>(
        &'a self,
        table_name: &'a str,
        query: Option<&'a str>,
    ) ->  impl Stream<Item = T, Error = AzureError> + 'a {
        self.stream_query_entities_metadata(table_name, query, false)
    }

    pub fn stream_query_entities_fullmetadata<'a, T: DeserializeOwned + 'a>(
        &'a self,
        table_name: &'a str,
        query: Option<&'a str>,
    ) ->  impl Stream<Item = T, Error = AzureError> + 'a {
        self.stream_query_entities_metadata(table_name, query, true)
    }

    fn _prepare_insert_entity<T>(&self, table_name: &str, entity: &T) -> Result<ResponseFuture, AzureError>
    where
        T: Serialize,
    {
        let obj_ser = serde_json::to_string(entity)?;
        self.request_with_default_header(table_name, &Method::POST, Some(&obj_ser), false)
    }

    pub fn insert_entity<T: Serialize>(&self, table_name: &str, entity: &T) -> impl Future<Item = (), Error = AzureError> {
        let req = self._prepare_insert_entity(table_name, entity);

        done(req)
            .from_err()
            .and_then(move |future_response| check_status_extract_body(future_response, StatusCode::CREATED).and_then(move |_| ok(())))
    }

    fn _prepare_update_entity<T>(
        &self,
        table_name: &str,
        partition_key: &str,
        row_key: &str,
        entity: &T,
    ) -> Result<ResponseFuture, AzureError>
    where
        T: Serialize,
    {
        let body = &serde_json::to_string(entity)?;
        let path = &entity_path(table_name, partition_key, row_key);
        self.request_with_default_header(path, &Method::PUT, Some(body), false)
    }

    pub fn update_entity<T: Serialize>(
        &self,
        table_name: &str,
        partition_key: &str,
        row_key: &str,
        entity: &T,
    ) -> impl Future<Item = (), Error = AzureError> {
        let req = self._prepare_update_entity(table_name, partition_key, row_key, entity);
        done(req)
            .from_err()
            .and_then(move |future_response| check_status_extract_body(future_response, StatusCode::NO_CONTENT).and_then(move |_| ok(())))
    }

    pub fn delete_entity(&self, table_name: &str, partition_key: &str, row_key: &str) -> impl Future<Item = (), Error = AzureError> {
        let path = &entity_path(table_name, partition_key, row_key);

        let req = self.request(path, &Method::DELETE, None, |ref mut request| {
            request.header(header::ACCEPT, HeaderValue::from_static(get_json_mime_nometadata()));
            request.header(header::IF_MATCH, header::HeaderValue::from_static("*"));
        });
        done(req)
            .from_err()
            .and_then(move |future_response| check_status_extract_body(future_response, StatusCode::NO_CONTENT).and_then(move |_| ok(())))
    }

    pub fn batch<T: Serialize>(
        &self,
        table_name: &str,
        partition_key: &str,
        batch_items: &[BatchItem<T>],
    ) -> impl Future<Item = (), Error = AzureError> {
        let payload = &generate_batch_payload(
            self.client.get_uri_prefix(ServiceType::Table).as_str(),
            table_name,
            partition_key,
            batch_items,
        );

        let req = self.request("$batch", &Method::POST, Some(payload), |ref mut request| {
            request.header(header::CONTENT_TYPE, header::HeaderValue::from_static(get_batch_mime()));
        });
        done(req).from_err().and_then(move |future_response| {
            check_status_extract_body(future_response, StatusCode::ACCEPTED).and_then(move |_| {
                // TODO deal with body response, handle batch failure.
                // let ref body = get_response_body(&mut response)?;
                // info!("{}", body);
                ok(())
            })
        })
    }

    fn request_with_default_header(&self, segment: &str, method: &Method, request_str: Option<&str>, fullmetadata: bool) -> Result<ResponseFuture, AzureError> {
        self.request(segment, method, request_str, |ref mut request| {
            if fullmetadata {
                request.header(header::ACCEPT, HeaderValue::from_static(get_json_mime_fullmetadata()));
            } else {
                request.header(header::ACCEPT, HeaderValue::from_static(get_json_mime_nometadata()));
            }
            request.header(header::ACCEPT, HeaderValue::from_static(get_json_mime_nometadata()));
            if request_str.is_some() {
                request.header(header::CONTENT_TYPE, HeaderValue::from_static(get_default_json_mime()));
            }
        })
    }

    fn request<F>(&self, segment: &str, method: &Method, request_str: Option<&str>, headers_func: F) -> Result<ResponseFuture, AzureError>
    where
        F: FnOnce(&mut ::http::request::Builder),
    {
        trace!("{:?} {}", method, segment);
        if let Some(body) = request_str {
            trace!("Request: {}", body);
        }

        let request_vec: Option<&[u8]> = match request_str {
            Some(s) => Some(s.as_bytes()),
            None => None,
        };

        self.client.perform_table_request(segment, method, headers_func, request_vec)
    }
}

#[derive(Clone)]
pub struct TableStorage {
    service: TableService,
    table_name: String,
}

impl TableStorage {
    pub fn new<S:Into<String>>(service: TableService, table_name: S) -> Self {
        TableStorage {
            service,
            table_name: table_name.into()
        }
    }

    pub fn create_table<T: Into<String>>(&self) -> impl Future<Item = (), Error = AzureError> {
        self.service.create_table(self.table_name.clone())
    }

    pub fn get_entity<T: DeserializeOwned>(
        &self,
        partition_key: &str,
        row_key: &str,
    ) -> impl Future<Item = Option<T>, Error = AzureError> {
        self.service.get_entity(&self.table_name, partition_key, row_key)
    }

    pub fn query_entities<T: DeserializeOwned>(
        &self,
        query: Option<&str>,
    ) -> impl Future<Item = Vec<T>, Error = AzureError> {
        self.service.query_entities(&self.table_name, query)
    }

    pub fn stream_query_entities<'a, T: DeserializeOwned + 'a>(
        &'a self,
        query: Option<&'a str>,
    ) ->  impl Stream<Item = T, Error = AzureError> + 'a {
        self.service.stream_query_entities(&self.table_name, query)
    }

    pub fn stream_query_entities_fullmetadata<'a, T: DeserializeOwned + 'a>(
        &'a self,
        query: Option<&'a str>,
    ) ->  impl Stream<Item = T, Error = AzureError> + 'a {
        self.service.stream_query_entities_fullmetadata(&self.table_name, query)
    }

    pub fn insert_entity<T: Serialize>(&self, entity: &T) -> impl Future<Item = (), Error = AzureError> {
        self.service.insert_entity::<T>(&self.table_name, entity)
    }

    pub fn update_entity<T: Serialize>(
        &self,
        partition_key: &str,
        row_key: &str,
        entity: &T,
    ) -> impl Future<Item = (), Error = AzureError> {
        self.service.update_entity(&self.table_name, partition_key, row_key, entity)
    }

    pub fn delete_entity(&self, partition_key: &str, row_key: &str) -> impl Future<Item = (), Error = AzureError> {
        self.service.delete_entity(&self.table_name, partition_key, row_key)
    }

    pub fn batch<T: Serialize>(
        &self,
        partition_key: &str,
        batch_items: &[BatchItem<T>],
    ) -> impl Future<Item = (), Error = AzureError> {
        self.service.batch(&self.table_name, partition_key, batch_items)
    }
}

const HEADER_NEXTPARTITIONKEY: &'static str = "x-ms-continuation-NextPartitionKey";
const HEADER_NEXTROWKEY: &'static str = "x-ms-continuation-NextRowKey";

fn continuation_from_headers(headers: &HeaderMap) -> Option<Continuation> {
    if headers.contains_key(HEADER_NEXTPARTITIONKEY) && headers.contains_key(HEADER_NEXTROWKEY){
        Some(Continuation {
            next_partition_key: headers[HEADER_NEXTPARTITIONKEY].to_str().unwrap().to_string(),
            next_row_key: headers[HEADER_NEXTROWKEY].to_str().unwrap().to_string(),
        })
    } else {
        None
    }
}

#[allow(non_snake_case)]
#[derive(Serialize, Deserialize)]
struct TableEntity {
    TableName: String,
}

#[derive(Deserialize)]
struct EntityCollection<T> {
    value: Vec<T>,
    #[serde(skip)]
    continuation: Option<Continuation>,
}

struct Continuation {
    next_partition_key: String,
    next_row_key: String,
}

enum ContinuationState {
    Start,
    Next(Option<Continuation>),
}

#[inline]
fn entity_path(table_name: &str, partition_key: &str, row_key: &str) -> String {
    table_name.to_owned() + "(PartitionKey='" + partition_key + "',RowKey='" + row_key + "')"
}

#[inline]
pub fn get_batch_mime() -> &'static str {
    "multipart/mixed; boundary=batch_a1e9d677-b28b-435e-a89e-87e6a768a431"
}
<|endoftext|>


<commit_before>use std::ops::Range;

use byteorder::{ByteOrder, LittleEndian};

use gameboy::{CPU_FREQUENCY, MAX_CPU_CYCLES, MAX_DIV_REG_CYCLES, Gpu, Irq, Memory, Timer};
use gameboy::cartridge::{Cartridge, CartridgeDetails};
use super::memory_map::{self, Address};

const MAIN_MEM_SIZE: usize = 0x2000;
const ZRAM_SIZE: usize = 0x7F;
const MMAP_SIZE: usize = 0x7F;

pub struct Interconnect {
    pub gpu: Gpu,
    pub ram: Memory,
    pub zram: Memory,
    pub mmap_io: Memory,
    pub timer: Timer,
    pub irq: Irq,
    pub cart: Option<Cartridge>,
    pub interrupt: u8,
}

impl Interconnect {
    pub fn new() -> Interconnect {
        Interconnect {
            gpu: Gpu::new(),
            ram: Memory::new(MAIN_MEM_SIZE),
            zram: Memory::new(ZRAM_SIZE),
            mmap_io: Memory::new(MMAP_SIZE),
            timer: Timer::new(),
            irq: Irq::new(),
            cart: None,
            interrupt: 0x00,
        }
    }

    pub fn with_cart(cart: Cartridge) -> Interconnect {
        Interconnect {
            gpu: Gpu::new(),
            ram: Memory::new(MAIN_MEM_SIZE),
            zram: Memory::new(ZRAM_SIZE),
            mmap_io: Memory::new(MMAP_SIZE),
            timer: Timer::new(),
            irq: Irq::new(),
            cart: Some(cart),
            interrupt: 0x00,
        }
    }

    pub fn step(&mut self, cycles: usize) {
        self.gpu.step(&mut self.irq, cycles);
        self.timer.step(&mut self.irq, cycles);
    }

    pub fn cart_details(&self) -> CartridgeDetails {
        let cart = self.cart.as_ref().expect("Cartridge is empty");

        cart.details(&self)
    }

    pub fn write_u8(&mut self, addr: u16, byte: u8) {
        let cart = self.cart.as_mut().expect("Cartridge is empty");

        match memory_map::map_address(addr) {
            Address::Ram(a) |
            Address::RamShadow(a) => self.ram.write_u8(a, byte),
            Address::Gfx(a) => self.gpu.ram.write_u8(a, byte),
            Address::CartRam(a) => cart.ram.write_u8(a, byte),
            Address::CartRom(a) => cart.rom.write_u8(a, byte),
            Address::ZRam(a) => self.zram.write_u8(a, byte),
            Address::Oam(a) => self.gpu.sprite_data.write_u8(a, byte),
            Address::Unused(_) => (),
            Address::Io(a) => {
                match a {
                    0x01...0x02 => println!("err: write to serial driver not supported"),
                    0x04...0x07 => self.timer.write_u8(a, byte),
                    0x0F => self.irq.request_flag = byte,
                    0x10...0x26 => println!("err: write to sound driver not supported"),
                    0x40...0x45 => self.gpu.write_u8(a, byte),
                    0x47...0x49 => self.gpu.write_u8(a, byte),
                    0x4A...0x4B => self.gpu.write_u8(a, byte),
                    0xFF => self.irq.enable_flag = byte,
                    _ => panic!("write memory mapped I/O in unsupported range: {:04X}", a),
                }
            }
            Address::InterruptEnableRegister(a) => self.interrupt = byte,
            _ => {
                panic!("Unable to write byte to: {:#X}, invalid memory region.",
                       addr)
            }
        }
    }

    pub fn read_u8(&self, addr: u16) -> u8 {
        let cart = self.cart.as_ref().expect("Cartridge is empty");

        match memory_map::map_address(addr) {
            Address::Ram(addr) |
            Address::RamShadow(addr) => self.ram.read_u8(addr),
            Address::CartRom(addr) |
            Address::CartRomOtherBank(addr) => cart.rom.read_u8(addr),
            Address::Gfx(value) => self.gpu.ram.read_u8(value),
            Address::CartRam(a) => cart.ram.read_u8(a),
            Address::ZRam(a) => self.zram.read_u8(a),
            Address::Oam(a) => self.gpu.sprite_data.read_u8(a),
            Address::Unused(_) => 0xFF, // Always return high
            Address::Io(a) => {
                match a {
                    0x01...0x02 => {
                        println!("err: read from serial driver not supported");
                        0
                    }
                    0x04...0x07 => self.timer.read_u8(a),
                    0x0F => self.irq.request_flag,
                    0x10...0x26 => {
                        println!("err: read from sound driver not supported");
                        0
                    }
                    0x40...0x45 => self.gpu.read_u8(a),
                    0x47...0x49 => self.gpu.read_u8(a),
                    0x4A...0x4B => self.gpu.read_u8(a),
                    0xFF => self.irq.enable_flag,
                    _ => panic!("read memory mapped I/O in unsupported range"),
                }
            }
            Address::InterruptEnableRegister(a) => self.interrupt,
            _ => panic!("Unable to read address: {:#X}", addr),
        }
    }

    pub fn read_bytes(&self, r: Range<u16>) -> &[u8] {
        let cart = self.cart.as_ref().expect("Cartridge is empty");

        match memory_map::map_address(r.start) {
            Address::Ram(_) |
            Address::RamShadow(_) => self.ram.read_bytes(r),
            Address::CartRom(_) |
            Address::CartRomOtherBank(_) => cart.rom.read_bytes(r),
            Address::Gfx(_) => self.gpu.ram.read_bytes(r),
            Address::CartRam(_) => cart.ram.read_bytes(r),
            Address::ZRam(_) => self.zram.read_bytes(r),
            Address::Io(a) => self.mmap_io.read_bytes(r),
            _ => panic!("Unable to read address range: {:?}", r),
        }
    }

    pub fn write_u16(&mut self, addr: u16, val: u16) {
        let cart = self.cart.as_ref().expect("Cartridge is empty");

        match memory_map::map_address(addr) {
            Address::ZRam(a) => self.zram.write_u16(a, val),
            _ => panic!("Unable to read address: {:#X}", addr),
        }
    }

    pub fn read_u16(&self, addr: u16) -> u16 {
        let cart = self.cart.as_ref().expect("Cartridge is empty");

        match memory_map::map_address(addr) {
            Address::Ram(addr) |
            Address::RamShadow(addr) => self.ram.read_u16(addr),
            Address::CartRom(addr) |
            Address::CartRomOtherBank(addr) => cart.rom.read_u16(addr),
            Address::Gfx(value) => self.gpu.ram.read_u16(value),
            Address::CartRam(a) => cart.ram.read_u16(a),
            Address::ZRam(a) => self.zram.read_u16(a),
            Address::Io(a) => self.mmap_io.read_u16(a),
            _ => panic!("Unable to read address: {:#X}", addr),
        }
    }
}
<commit_msg>Add support for out of range MMAP address space<commit_after>use std::ops::Range;

use byteorder::{ByteOrder, LittleEndian};

use gameboy::{CPU_FREQUENCY, MAX_CPU_CYCLES, MAX_DIV_REG_CYCLES, Gpu, Irq, Memory, Timer};
use gameboy::cartridge::{Cartridge, CartridgeDetails};
use super::memory_map::{self, Address};

const MAIN_MEM_SIZE: usize = 0x2000;
const ZRAM_SIZE: usize = 0x80;
const MMAP_SIZE: usize = 0x80;

pub struct Interconnect {
    pub gpu: Gpu,
    pub ram: Memory,
    pub zram: Memory,
    pub mmap_io: Memory,
    pub timer: Timer,
    pub irq: Irq,
    pub cart: Option<Cartridge>,
    pub interrupt: u8,
}

impl Interconnect {
    pub fn new() -> Interconnect {
        Interconnect {
            gpu: Gpu::new(),
            ram: Memory::new(MAIN_MEM_SIZE),
            zram: Memory::new(ZRAM_SIZE),
            mmap_io: Memory::new(MMAP_SIZE),
            timer: Timer::new(),
            irq: Irq::new(),
            cart: None,
            interrupt: 0x00,
        }
    }

    pub fn with_cart(cart: Cartridge) -> Interconnect {
        Interconnect {
            gpu: Gpu::new(),
            ram: Memory::new(MAIN_MEM_SIZE),
            zram: Memory::new(ZRAM_SIZE),
            mmap_io: Memory::new(MMAP_SIZE),
            timer: Timer::new(),
            irq: Irq::new(),
            cart: Some(cart),
            interrupt: 0x00,
        }
    }

    pub fn step(&mut self, cycles: usize) {
        self.gpu.step(&mut self.irq, cycles);
        self.timer.step(&mut self.irq, cycles);
    }

    pub fn cart_details(&self) -> CartridgeDetails {
        let cart = self.cart.as_ref().expect("Cartridge is empty");

        cart.details(&self)
    }

    pub fn write_u8(&mut self, addr: u16, byte: u8) {
        let cart = self.cart.as_mut().expect("Cartridge is empty");

        match memory_map::map_address(addr) {
            Address::Ram(a) |
            Address::RamShadow(a) => self.ram.write_u8(a, byte),
            Address::Gfx(a) => self.gpu.ram.write_u8(a, byte),
            Address::CartRam(a) => cart.ram.write_u8(a, byte),
            Address::CartRom(a) => cart.rom.write_u8(a, byte),
            Address::ZRam(a) => self.zram.write_u8(a, byte),
            Address::Oam(a) => self.gpu.sprite_data.write_u8(a, byte),
            Address::Unused(_) => (),
            Address::Io(a) => {
                match a {
                    0x01...0x02 => println!("err: write to serial driver not supported"),
                    0x04...0x07 => self.timer.write_u8(a, byte),
                    0x0F => self.irq.request_flag = byte,
                    0x10...0x26 => println!("err: write to sound driver not supported"),
                    0x40...0x45 => self.gpu.write_u8(a, byte),
                    0x47...0x49 => self.gpu.write_u8(a, byte),
                    0x4A...0x4B => self.gpu.write_u8(a, byte),
                    0x7F => self.mmap_io.write_u8(a, byte),
                    0xFF => self.irq.enable_flag = byte,
                    _ => panic!("write memory mapped I/O in unsupported range: {:04X}", a),
                }
            }
            Address::InterruptEnableRegister(a) => self.interrupt = byte,
            _ => {
                panic!("Unable to write byte to: {:#X}, invalid memory region.",
                       addr)
            }
        }
    }

    pub fn read_u8(&self, addr: u16) -> u8 {
        let cart = self.cart.as_ref().expect("Cartridge is empty");

        match memory_map::map_address(addr) {
            Address::Ram(addr) |
            Address::RamShadow(addr) => self.ram.read_u8(addr),
            Address::CartRom(addr) |
            Address::CartRomOtherBank(addr) => cart.rom.read_u8(addr),
            Address::Gfx(value) => self.gpu.ram.read_u8(value),
            Address::CartRam(a) => cart.ram.read_u8(a),
            Address::ZRam(a) => self.zram.read_u8(a),
            Address::Oam(a) => self.gpu.sprite_data.read_u8(a),
            Address::Unused(_) => 0xFF, // Always return high
            Address::Io(a) => {
                match a {
                    0x01...0x02 => {
                        println!("err: read from serial driver not supported");
                        0
                    }
                    0x04...0x07 => self.timer.read_u8(a),
                    0x0F => self.irq.request_flag,
                    0x10...0x26 => {
                        println!("err: read from sound driver not supported");
                        0
                    }
                    0x40...0x45 => self.gpu.read_u8(a),
                    0x47...0x49 => self.gpu.read_u8(a),
                    0x4A...0x4B => self.gpu.read_u8(a),
                    0x7F => self.mmap_io.read_u8(a),
                    0xFF => self.irq.enable_flag,
                    _ => panic!("read memory mapped I/O in unsupported range"),
                }
            }
            Address::InterruptEnableRegister(a) => self.interrupt,
            _ => panic!("Unable to read address: {:#X}", addr),
        }
    }

    pub fn read_bytes(&self, r: Range<u16>) -> &[u8] {
        let cart = self.cart.as_ref().expect("Cartridge is empty");

        match memory_map::map_address(r.start) {
            Address::Ram(_) |
            Address::RamShadow(_) => self.ram.read_bytes(r),
            Address::CartRom(_) |
            Address::CartRomOtherBank(_) => cart.rom.read_bytes(r),
            Address::Gfx(_) => self.gpu.ram.read_bytes(r),
            Address::CartRam(_) => cart.ram.read_bytes(r),
            Address::ZRam(_) => self.zram.read_bytes(r),
            Address::Io(a) => self.mmap_io.read_bytes(r),
            _ => panic!("Unable to read address range: {:?}", r),
        }
    }

    pub fn write_u16(&mut self, addr: u16, val: u16) {
        let cart = self.cart.as_ref().expect("Cartridge is empty");

        match memory_map::map_address(addr) {
            Address::ZRam(a) => self.zram.write_u16(a, val),
            _ => panic!("Unable to read address: {:#X}", addr),
        }
    }

    pub fn read_u16(&self, addr: u16) -> u16 {
        let cart = self.cart.as_ref().expect("Cartridge is empty");

        match memory_map::map_address(addr) {
            Address::Ram(addr) |
            Address::RamShadow(addr) => self.ram.read_u16(addr),
            Address::CartRom(addr) |
            Address::CartRomOtherBank(addr) => cart.rom.read_u16(addr),
            Address::Gfx(value) => self.gpu.ram.read_u16(value),
            Address::CartRam(a) => cart.ram.read_u16(a),
            Address::ZRam(a) => self.zram.read_u16(a),
            Address::Io(a) => self.mmap_io.read_u16(a),
            _ => panic!("Unable to read address: {:#X}", addr),
        }
    }
}
<|endoftext|>