<commit_before>// Copyright © 2017, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate bragi;
extern crate iron_test;
extern crate serde_json;
use super::BragiHandler;
use super::get_value;

pub fn bragi_stops_test(es_wrapper: ::ElasticSearchWrapper) {
    let bragi = BragiHandler::new(format!("{}/munin", es_wrapper.host()));

    // ******************************************
    // we the OSM dataset, three-cities bano dataset and a stop file
    // the current dataset are thus (load order matters):
    // - osm_fixture.osm.pbf
    // - bano-three_cities
    // - stops.txt
    // ******************************************
    let osm2mimir = concat!(env!("OUT_DIR"), "/../../../osm2mimir");
    ::launch_and_assert(osm2mimir,
                        vec!["--input=./tests/fixtures/osm_fixture.osm.pbf".into(),
                             "--level=8".into(),
                             format!("--connection-string={}", es_wrapper.host())],
                        &es_wrapper);

    let bano2mimir = concat!(env!("OUT_DIR"), "/../../../bano2mimir");
    ::launch_and_assert(bano2mimir,
                        vec!["--input=./tests/fixtures/bano-three_cities.csv".into(),
                             format!("--connection-string={}", es_wrapper.host())],
                        &es_wrapper);

    let stops2mimir = concat!(env!("OUT_DIR"), "/../../../stops2mimir");
    ::launch_and_assert(stops2mimir,
                        vec!["--input=./tests/fixtures/stops.txt".into(),
                             "--dataset=dataset1".into(),
                             format!("--connection-string={}", es_wrapper.host())],
                        &es_wrapper);

    stop_attached_to_admin_test(&bragi);
    stop_no_admin_test(&bragi);

    let stops2mimir = concat!(env!("OUT_DIR"), "/../../../stops2mimir");
    ::launch_and_assert(stops2mimir,
                        vec!["--input=./tests/fixtures/stops_dataset2.txt".into(),
                             "--dataset=dataset2".into(),
                             format!("--connection-string={}", es_wrapper.host())],
                        &es_wrapper);

    stop_filtered_by_dataset_test(&bragi);
    stop_all_data_test(&bragi);
    stop_order_by_weight_test(&bragi);
}

fn stop_attached_to_admin_test(bragi: &BragiHandler) {
    // with this query we should find only one response, a stop
    let response = bragi.get("/autocomplete?q=14 juillet&_all_data=true");
    assert_eq!(response.len(), 1);
    let stop = response.first().unwrap();

    assert_eq!(get_value(stop, "type"), "public_transport:stop_area");
    assert_eq!(get_value(stop, "label"), "14 Juillet (Vaux-le-Pénil)");
    assert_eq!(get_value(stop, "name"), "14 Juillet");
    assert_eq!(get_value(stop, "id"), "stop_area:SA:second_station");
    assert_eq!(get_value(stop, "citycode"), "77487");
    assert_eq!(get_value(stop, "postcode"), "77000");

    // this stop area is in the boundary of the admin 'Vaux-le-Pénil',
    // it should have been associated to it
    assert_eq!(get_value(stop, "city"), "Vaux-le-Pénil");
    let admins = stop.get("administrative_regions").and_then(|a| a.as_array());
    assert_eq!(admins.map(|a| a.len()).unwrap_or(0), 1);
}

fn stop_no_admin_test(bragi: &BragiHandler) {
    // we query another stop, but this one is outside the range of an admin,
    // we should get the stop, but with no admin attached to it
    let response = bragi.get("/autocomplete?q=Far west station&_all_data=true");
    assert_eq!(response.len(), 1);
    let stop = response.first().unwrap();

    assert_eq!(get_value(stop, "type"), "public_transport:stop_area");
    assert_eq!(get_value(stop, "label"), "Far west station");
    assert_eq!(get_value(stop, "name"), "Far west station");
    assert_eq!(get_value(stop, "id"), "stop_area:SA:station_no_city");
    assert_eq!(get_value(stop, "city"), "");
    let admins = stop.get("administrative_regions").and_then(|a| a.as_array());
    assert_eq!(admins.map(|a| a.len()).unwrap_or(0), 0);
}

fn stop_filtered_by_dataset_test(bragi: &BragiHandler) {
    // Search stops on all aliases
    let response = bragi.get("/autocomplete?q=14 juillet&_all_data=true");
    assert_eq!(response.len(), 2);

    let stop = response.first().unwrap();
    assert_eq!(get_value(stop, "id"), "stop_area:SA:second_station");

    let stop = response.last().unwrap();
    assert_eq!(get_value(stop, "id"),
               "stop_area:SA:second_station:dataset2");

    // filter by dataset1
    let response = bragi.get("/autocomplete?q=14 juillet&pt_dataset=dataset1");

    assert_eq!(response.len(), 1);

    let stop = response.first().unwrap();
    assert_eq!(get_value(stop, "id"), "stop_area:SA:second_station");
    // filter by dataset2
    let response = bragi.get("/autocomplete?q=14 juillet&pt_dataset=dataset2");

    assert_eq!(response.len(), 1);

    let stop = response.first().unwrap();
    assert_eq!(get_value(stop, "id"),
               "stop_area:SA:second_station:dataset2");
}

fn stop_all_data_test(bragi: &BragiHandler) {
    // search without _all_data, default value : _all_data = false
    let response = bragi.get("/autocomplete?q=14 juillet");
    assert_eq!(response.len(), 0);

    // search wiht _all_data = false
    let response = bragi.get("/autocomplete?q=14 juillet&_all_data=false");
    assert_eq!(response.len(), 0);

    // search wiht _all_data = true
    let response = bragi.get("/autocomplete?q=14 juillet&_all_data=true");
    assert_eq!(response.len(), 2);
}

fn stop_order_by_weight_test(bragi: &BragiHandler) {
    // The StopAreas are sorted by weight. stop_area:SA:weight_3_station having weight 3
    // will be the first element in the result where as stop_area:SA:weight_1_station will
    //always be second.
    let response = bragi.get("/autocomplete?q=weight&_all_data=true");
    assert_eq!(response.len(), 2);

    let stop = response.first().unwrap();

    assert_eq!(get_value(stop, "type"), "public_transport:stop_area");
    assert_eq!(get_value(stop, "label"), "weight three");
    assert_eq!(get_value(stop, "name"), "weight three");
    assert_eq!(get_value(stop, "id"), "stop_area:SA:weight_3_station");
}
<commit_msg>mimir test: another formatting<commit_after>// Copyright © 2017, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate bragi;
extern crate iron_test;
extern crate serde_json;
use super::BragiHandler;
use super::get_value;

pub fn bragi_stops_test(es_wrapper: ::ElasticSearchWrapper) {
    let bragi = BragiHandler::new(format!("{}/munin", es_wrapper.host()));

    // ******************************************
    // we the OSM dataset, three-cities bano dataset and a stop file
    // the current dataset are thus (load order matters):
    // - osm_fixture.osm.pbf
    // - bano-three_cities
    // - stops.txt
    // ******************************************
    let osm2mimir = concat!(env!("OUT_DIR"), "/../../../osm2mimir");
    ::launch_and_assert(osm2mimir,
                        vec!["--input=./tests/fixtures/osm_fixture.osm.pbf".into(),
                             "--level=8".into(),
                             format!("--connection-string={}", es_wrapper.host())],
                        &es_wrapper);

    let bano2mimir = concat!(env!("OUT_DIR"), "/../../../bano2mimir");
    ::launch_and_assert(bano2mimir,
                        vec!["--input=./tests/fixtures/bano-three_cities.csv".into(),
                             format!("--connection-string={}", es_wrapper.host())],
                        &es_wrapper);

    let stops2mimir = concat!(env!("OUT_DIR"), "/../../../stops2mimir");
    ::launch_and_assert(stops2mimir,
                        vec!["--input=./tests/fixtures/stops.txt".into(),
                             "--dataset=dataset1".into(),
                             format!("--connection-string={}", es_wrapper.host())],
                        &es_wrapper);

    stop_attached_to_admin_test(&bragi);
    stop_no_admin_test(&bragi);

    let stops2mimir = concat!(env!("OUT_DIR"), "/../../../stops2mimir");
    ::launch_and_assert(stops2mimir,
                        vec!["--input=./tests/fixtures/stops_dataset2.txt".into(),
                             "--dataset=dataset2".into(),
                             format!("--connection-string={}", es_wrapper.host())],
                        &es_wrapper);

    stop_filtered_by_dataset_test(&bragi);
    stop_all_data_test(&bragi);
    stop_order_by_weight_test(&bragi);
}

fn stop_attached_to_admin_test(bragi: &BragiHandler) {
    // with this query we should find only one response, a stop
    let response = bragi.get("/autocomplete?q=14 juillet&_all_data=true");
    assert_eq!(response.len(), 1);
    let stop = response.first().unwrap();

    assert_eq!(get_value(stop, "type"), "public_transport:stop_area");
    assert_eq!(get_value(stop, "label"), "14 Juillet (Vaux-le-Pénil)");
    assert_eq!(get_value(stop, "name"), "14 Juillet");
    assert_eq!(get_value(stop, "id"), "stop_area:SA:second_station");
    assert_eq!(get_value(stop, "citycode"), "77487");
    assert_eq!(get_value(stop, "postcode"), "77000");

    // this stop area is in the boundary of the admin 'Vaux-le-Pénil',
    // it should have been associated to it
    assert_eq!(get_value(stop, "city"), "Vaux-le-Pénil");
    let admins = stop.get("administrative_regions").and_then(|a| a.as_array());
    assert_eq!(admins.map(|a| a.len()).unwrap_or(0), 1);
}

fn stop_no_admin_test(bragi: &BragiHandler) {
    // we query another stop, but this one is outside the range of an admin,
    // we should get the stop, but with no admin attached to it
    let response = bragi.get("/autocomplete?q=Far west station&_all_data=true");
    assert_eq!(response.len(), 1);
    let stop = response.first().unwrap();

    assert_eq!(get_value(stop, "type"), "public_transport:stop_area");
    assert_eq!(get_value(stop, "label"), "Far west station");
    assert_eq!(get_value(stop, "name"), "Far west station");
    assert_eq!(get_value(stop, "id"), "stop_area:SA:station_no_city");
    assert_eq!(get_value(stop, "city"), "");
    let admins = stop.get("administrative_regions").and_then(|a| a.as_array());
    assert_eq!(admins.map(|a| a.len()).unwrap_or(0), 0);
}

fn stop_filtered_by_dataset_test(bragi: &BragiHandler) {
    // Search stops on all aliases
    let response = bragi.get("/autocomplete?q=14 juillet&_all_data=true");
    assert_eq!(response.len(), 2);

    let stop = response.first().unwrap();
    assert_eq!(get_value(stop, "id"), "stop_area:SA:second_station");

    let stop = response.last().unwrap();
    assert_eq!(get_value(stop, "id"),
               "stop_area:SA:second_station:dataset2");

    // filter by dataset1
    let response = bragi.get("/autocomplete?q=14 juillet&pt_dataset=dataset1");

    assert_eq!(response.len(), 1);

    let stop = response.first().unwrap();
    assert_eq!(get_value(stop, "id"), "stop_area:SA:second_station");
    // filter by dataset2
    let response = bragi.get("/autocomplete?q=14 juillet&pt_dataset=dataset2");

    assert_eq!(response.len(), 1);

    let stop = response.first().unwrap();
    assert_eq!(get_value(stop, "id"),
               "stop_area:SA:second_station:dataset2");
}

fn stop_all_data_test(bragi: &BragiHandler) {
    // search without _all_data, default value : _all_data = false
    let response = bragi.get("/autocomplete?q=14 juillet");
    assert_eq!(response.len(), 0);

    // search wiht _all_data = false
    let response = bragi.get("/autocomplete?q=14 juillet&_all_data=false");
    assert_eq!(response.len(), 0);

    // search wiht _all_data = true
    let response = bragi.get("/autocomplete?q=14 juillet&_all_data=true");
    assert_eq!(response.len(), 2);
}

fn stop_order_by_weight_test(bragi: &BragiHandler) {
    // The StopAreas are sorted by weight. stop_area:SA:weight_3_station having weight 3
    // will be the first element in the result where as stop_area:SA:weight_1_station will
    //always be second.
    let response = bragi.get("/autocomplete?q=weight&_all_data=true");
    assert_eq!(response.len(), 2);

    let stop = response.first().unwrap();

    assert_eq!(get_value(stop, "type"), "public_transport:stop_area");
    assert_eq!(get_value(stop, "label"), "weight three");
    assert_eq!(get_value(stop, "name"), "weight three");
    assert_eq!(get_value(stop, "id"), "stop_area:SA:weight_3_station");
}
<|endoftext|>


<commit_before>fn empty() -> &'static str {
    ""
}

fn hello() -> &'static str {
    "Hello, world!"
}

fn hello_bytes() -> &'static [u8; 13] {
    b"Hello, world!"
}

fn hello_bytes_fat() -> &'static [u8] {
    b"Hello, world!"
}

fn fat_pointer_on_32_bit() {
    Some(5).expect("foo");
}

fn main() {
    assert_eq!(empty(), "");
    assert_eq!(hello(), "Hello, world!");
    assert_eq!(hello_bytes(), b"Hello, world!");
    assert_eq!(hello_bytes_fat(), b"Hello, world!");
    fat_pointer_on_32_bit(); // Should run without crashing.
}
<commit_msg>test mutable string slice indexing<commit_after>fn empty() -> &'static str {
    ""
}

fn hello() -> &'static str {
    "Hello, world!"
}

fn hello_bytes() -> &'static [u8; 13] {
    b"Hello, world!"
}

fn hello_bytes_fat() -> &'static [u8] {
    b"Hello, world!"
}

fn fat_pointer_on_32_bit() {
    Some(5).expect("foo");
}

fn str_indexing() {
    let mut x = "Hello".to_string();
    let _v = &mut x[..3];  // Test IndexMut on String.
}

fn main() {
    assert_eq!(empty(), "");
    assert_eq!(hello(), "Hello, world!");
    assert_eq!(hello_bytes(), b"Hello, world!");
    assert_eq!(hello_bytes_fat(), b"Hello, world!");

    fat_pointer_on_32_bit(); // Should run without crashing.
    str_indexing();
}
<|endoftext|>


<commit_before>use crate::helper::{load_module_test, run_top_level_test_with_args};
use serial_test::serial;

#[serial]
#[test]
fn builtins() {
    load_module_test("src/tests/builtins.pl", "");
}

#[serial]
#[test]
fn call_with_inference_limit() {
    load_module_test("src/tests/call_with_inference_limit.pl", "");
}

#[serial]
#[test]
fn facts() {
    load_module_test("src/tests/facts.pl", "");
}

#[serial]
#[test]
fn hello_world() {
    load_module_test("src/tests/hello_world.pl", "Hello World!\n");
}

#[serial]
#[test]
fn syntax_error() {
    load_module_test(
        "tests-pl/syntax_error.pl",
        "caught: error(syntax_error(incomplete_reduction),read_term/3:6)\n",
    );
}

#[serial]
#[test]
fn predicates() {
    load_module_test("src/tests/predicates.pl", "");
}

#[serial]
#[test]
fn rules() {
    load_module_test("src/tests/rules.pl", "");
}

#[serial]
#[test]
fn setup_call_cleanup_load() {
    load_module_test(
        "src/tests/setup_call_cleanup.pl",
        "1+21+31+2>_14304+_143051+_128981+2>41+2>_143051+2>31+2>31+2>4ba",
    );
}

#[test]
fn setup_call_cleanup_process() {
    run_top_level_test_with_args(
        &["src/tests/setup_call_cleanup.pl", "-f", "-g", "halt"],
        "",
        "1+21+31+2>_15703+_157041+_142971+2>41+2>_157041+2>31+2>31+2>4ba",
    );
}

#[serial]
#[test]
fn clpz_load() {
    load_module_test("src/tests/clpz/test_clpz.pl", "");
}
<commit_msg>correct heap offsets in setup_call_cleanup tests<commit_after>use crate::helper::{load_module_test, run_top_level_test_with_args};
use serial_test::serial;

#[serial]
#[test]
fn builtins() {
    load_module_test("src/tests/builtins.pl", "");
}

#[serial]
#[test]
fn call_with_inference_limit() {
    load_module_test("src/tests/call_with_inference_limit.pl", "");
}

#[serial]
#[test]
fn facts() {
    load_module_test("src/tests/facts.pl", "");
}

#[serial]
#[test]
fn hello_world() {
    load_module_test("src/tests/hello_world.pl", "Hello World!\n");
}

#[serial]
#[test]
fn syntax_error() {
    load_module_test(
        "tests-pl/syntax_error.pl",
        "caught: error(syntax_error(incomplete_reduction),read_term/3:6)\n",
    );
}

#[serial]
#[test]
fn predicates() {
    load_module_test("src/tests/predicates.pl", "");
}

#[serial]
#[test]
fn rules() {
    load_module_test("src/tests/rules.pl", "");
}

#[serial]
#[test]
fn setup_call_cleanup_load() {
    load_module_test(
        "src/tests/setup_call_cleanup.pl",
        "1+21+31+2>_14313+_143141+_129071+2>41+2>_143141+2>31+2>31+2>4ba"
    );
}

#[test]
fn setup_call_cleanup_process() {
    run_top_level_test_with_args(
        &["src/tests/setup_call_cleanup.pl", "-f", "-g", "halt"],
        "",
        "1+21+31+2>_15712+_157131+_143061+2>41+2>_157131+2>31+2>31+2>4ba",
    );
}

#[serial]
#[test]
fn clpz_load() {
    load_module_test("src/tests/clpz/test_clpz.pl", "");
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::mem;
use std::ptr;
use libc::{c_int, c_ulong};

use runtime::Class;
use {Id, Message};

#[allow(improper_ctypes)]
#[link(name = "Foundation", kind = "framework")]
extern {
    static _NSConcreteStackBlock: Class;
}

pub trait BlockArguments {
    fn invoke_block<R>(self, block: &Block<Self, R>) -> R;
}

impl BlockArguments for () {
    fn invoke_block<R>(self, block: &Block<(), R>) -> R {
        let invoke: unsafe extern fn(*mut Block<(), R>) -> R = unsafe {
            mem::transmute(block.invoke)
        };
        let block_ptr = block as *const _ as *mut _;
        unsafe {
            invoke(block_ptr)
        }
    }
}

#[repr(C)]
pub struct Block<A: BlockArguments, R> {
    isa: *const Class,
    flags: c_int,
    _reserved: c_int,
    invoke: unsafe extern fn(*mut Block<A, R>, ...) -> R,
}

impl<A: BlockArguments, R> Block<A, R> {
    pub fn call(&self, args: A) -> R {
        args.invoke_block(self)
    }
}

#[repr(C)]
struct ConcreteBlock<C: Clone> {
    isa: *const Class,
    flags: c_int,
    _reserved: c_int,
    pub invoke: unsafe extern fn(&mut ConcreteBlock<C>, ...),
    descriptor: *const BlockDescriptor<C>,
    pub context: C,
}

impl<C: Clone> ConcreteBlock<C> {
    pub fn new(invoke: unsafe extern fn(&mut ConcreteBlock<C>, ...), context: C) -> ConcreteBlock<C> {
        ConcreteBlock {
            isa: &_NSConcreteStackBlock,
            // 1 << 25 = BLOCK_HAS_COPY_DISPOSE
            flags: 1 << 25,
            _reserved: 0,
            invoke: invoke,
            // TODO: don't leak memory here
            descriptor: unsafe {
                mem::transmute(box BlockDescriptor::<C>::new())
            },
            context: context,
        }
    }

    pub fn copy(&self) -> Id<ConcreteBlock<C>> {
        unsafe {
            let block = msg_send![self copy] as *mut ConcreteBlock<C>;
            Id::from_retained_ptr(block)
        }
    }
}

impl<C: Clone> Message for ConcreteBlock<C> { }

impl<C: Clone> Clone for ConcreteBlock<C> {
    fn clone(&self) -> ConcreteBlock<C> {
        ConcreteBlock::new(self.invoke, self.context.clone())
    }
}

unsafe extern fn block_context_dispose<C: Clone>(block: &mut ConcreteBlock<C>) {
    let mut context = mem::uninitialized();
    ptr::copy_nonoverlapping_memory(&mut context, &block.context, 1);
    drop(context);
}

unsafe extern fn block_context_copy<C: Clone>(dst: &mut ConcreteBlock<C>, src: &ConcreteBlock<C>) {
    dst.context = src.context.clone();
}

#[repr(C)]
struct BlockDescriptor<C: Clone> {
    _reserved: c_ulong,
    block_size: c_ulong,
    copy_helper: unsafe extern fn(&mut ConcreteBlock<C>, &ConcreteBlock<C>),
    dispose_helper: unsafe extern fn(&mut ConcreteBlock<C>),
}

impl<C: Clone> BlockDescriptor<C> {
    pub fn new() -> BlockDescriptor<C> {
        BlockDescriptor {
            _reserved: 0,
            block_size: mem::size_of::<ConcreteBlock<C>>() as c_ulong,
            copy_helper: block_context_copy::<C>,
            dispose_helper: block_context_dispose::<C>,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::mem;
    use objc_test_utils::invoke_int_block;
    use super::ConcreteBlock;

    #[test]
    fn test_create_block() {
        extern fn block_get_int(block: &ConcreteBlock<int>) -> int {
            block.context
        }

        let result = unsafe {
            let block = ConcreteBlock::new(mem::transmute(block_get_int), 13i);
            invoke_int_block(mem::transmute(&block))
        };
        assert!(result == 13);
    }
}
<commit_msg>Implemented Message and a copy method for Block.<commit_after>#![allow(dead_code)]

use std::mem;
use std::ptr;
use libc::{c_int, c_ulong};

use runtime::Class;
use {Id, Message};

#[allow(improper_ctypes)]
#[link(name = "Foundation", kind = "framework")]
extern {
    static _NSConcreteStackBlock: Class;
}

pub trait BlockArguments {
    fn invoke_block<R>(self, block: &Block<Self, R>) -> R;
}

impl BlockArguments for () {
    fn invoke_block<R>(self, block: &Block<(), R>) -> R {
        let invoke: unsafe extern fn(*mut Block<(), R>) -> R = unsafe {
            mem::transmute(block.invoke)
        };
        let block_ptr = block as *const _ as *mut _;
        unsafe {
            invoke(block_ptr)
        }
    }
}

#[repr(C)]
pub struct Block<A: BlockArguments, R> {
    isa: *const Class,
    flags: c_int,
    _reserved: c_int,
    invoke: unsafe extern fn(*mut Block<A, R>, ...) -> R,
}

impl<A: BlockArguments, R> Block<A, R> {
    pub fn copy(&self) -> Id<Block<A, R>> {
        unsafe {
            let block = msg_send![self copy] as *mut Block<A, R>;
            Id::from_retained_ptr(block)
        }
    }

    pub fn call(&self, args: A) -> R {
        args.invoke_block(self)
    }
}

impl<A: BlockArguments, R> Message for Block<A, R> { }

#[repr(C)]
struct ConcreteBlock<C: Clone> {
    isa: *const Class,
    flags: c_int,
    _reserved: c_int,
    pub invoke: unsafe extern fn(&mut ConcreteBlock<C>, ...),
    descriptor: *const BlockDescriptor<C>,
    pub context: C,
}

impl<C: Clone> ConcreteBlock<C> {
    pub fn new(invoke: unsafe extern fn(&mut ConcreteBlock<C>, ...), context: C) -> ConcreteBlock<C> {
        ConcreteBlock {
            isa: &_NSConcreteStackBlock,
            // 1 << 25 = BLOCK_HAS_COPY_DISPOSE
            flags: 1 << 25,
            _reserved: 0,
            invoke: invoke,
            // TODO: don't leak memory here
            descriptor: unsafe {
                mem::transmute(box BlockDescriptor::<C>::new())
            },
            context: context,
        }
    }

    pub fn copy(&self) -> Id<ConcreteBlock<C>> {
        unsafe {
            let block = msg_send![self copy] as *mut ConcreteBlock<C>;
            Id::from_retained_ptr(block)
        }
    }
}

impl<C: Clone> Message for ConcreteBlock<C> { }

impl<C: Clone> Clone for ConcreteBlock<C> {
    fn clone(&self) -> ConcreteBlock<C> {
        ConcreteBlock::new(self.invoke, self.context.clone())
    }
}

unsafe extern fn block_context_dispose<C: Clone>(block: &mut ConcreteBlock<C>) {
    let mut context = mem::uninitialized();
    ptr::copy_nonoverlapping_memory(&mut context, &block.context, 1);
    drop(context);
}

unsafe extern fn block_context_copy<C: Clone>(dst: &mut ConcreteBlock<C>, src: &ConcreteBlock<C>) {
    dst.context = src.context.clone();
}

#[repr(C)]
struct BlockDescriptor<C: Clone> {
    _reserved: c_ulong,
    block_size: c_ulong,
    copy_helper: unsafe extern fn(&mut ConcreteBlock<C>, &ConcreteBlock<C>),
    dispose_helper: unsafe extern fn(&mut ConcreteBlock<C>),
}

impl<C: Clone> BlockDescriptor<C> {
    pub fn new() -> BlockDescriptor<C> {
        BlockDescriptor {
            _reserved: 0,
            block_size: mem::size_of::<ConcreteBlock<C>>() as c_ulong,
            copy_helper: block_context_copy::<C>,
            dispose_helper: block_context_dispose::<C>,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::mem;
    use objc_test_utils::invoke_int_block;
    use super::ConcreteBlock;

    #[test]
    fn test_create_block() {
        extern fn block_get_int(block: &ConcreteBlock<int>) -> int {
            block.context
        }

        let result = unsafe {
            let block = ConcreteBlock::new(mem::transmute(block_get_int), 13i);
            invoke_int_block(mem::transmute(&block))
        };
        assert!(result == 13);
    }
}
<|endoftext|>


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

#![warn(clippy::needless_bool)]

use std::cell::Cell;

macro_rules! bool_comparison_trigger {
    ($($i:ident: $def:expr, $stb:expr );+  $(;)*) => (

        #[derive(Clone)]
        pub struct Trigger {
            $($i: (Cell<bool>, bool, bool)),+
        }

        #[allow(dead_code)]
        impl Trigger {
            pub fn trigger(&self, key: &str) -> bool {
                $(
                    if let stringify!($i) = key {
                        return self.$i.1 && self.$i.2 == $def;
                    }
                 )+
                false
            }
        }
    )
}

#[allow(clippy::if_same_then_else)]
fn main() {
    let x = true;
    let y = false;
    if x { true } else { true };
    if x { false } else { false };
    if x { true } else { false };
    if x { false } else { true };
    if x && y { false } else { true };
    if x { x } else { false }; // would also be questionable, but we don't catch this yet
    bool_ret(x);
    bool_ret2(x);
    bool_ret3(x);
    bool_ret5(x, x);
    bool_ret4(x);
    bool_ret6(x, x);
    needless_bool(x);
    needless_bool2(x);
    needless_bool3(x);
}

#[allow(clippy::if_same_then_else, clippy::needless_return)]
fn bool_ret(x: bool) -> bool {
    if x { return true } else { return true };
}

#[allow(clippy::if_same_then_else, clippy::needless_return)]
fn bool_ret2(x: bool) -> bool {
    if x { return false } else { return false };
}

#[allow(clippy::needless_return)]
fn bool_ret3(x: bool) -> bool {
    if x { return true } else { return false };
}

#[allow(clippy::needless_return)]
fn bool_ret5(x: bool, y: bool) -> bool {
    if x && y { return true } else { return false };
}

#[allow(clippy::needless_return)]
fn bool_ret4(x: bool) -> bool {
    if x { return false } else { return true };
}

#[allow(clippy::needless_return)]
fn bool_ret6(x: bool, y: bool) -> bool {
    if x && y { return false } else { return true };
}

fn needless_bool(x: bool) {
   if x  == true { };
}

fn needless_bool2(x: bool) {
   if x  == false { };
}

fn needless_bool3(x: bool) {

    bool_comparison_trigger! {
        test_one:   false, false;
        test_three: false, false;
        test_two:   true, true;
    }

    if x == true { };
    if x == false { };
}<commit_msg>Fix #3335 rev1: bool_comparison triggers 3 times on same code<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![warn(clippy::needless_bool)]

use std::cell::Cell;

macro_rules! bool_comparison_trigger {
    ($($i:ident: $def:expr, $stb:expr );+  $(;)*) => (

        #[derive(Clone)]
        pub struct Trigger {
            $($i: (Cell<bool>, bool, bool)),+
        }

        #[allow(dead_code)]
        impl Trigger {
            pub fn trigger(&self, key: &str) -> bool {
                $(
                    if let stringify!($i) = key {
                        return self.$i.1 && self.$i.2 == $def;
                    }
                 )+
                false
            }
        }
    )
}

#[allow(clippy::if_same_then_else)]
fn main() {
    let x = true;
    let y = false;
    if x { true } else { true };
    if x { false } else { false };
    if x { true } else { false };
    if x { false } else { true };
    if x && y { false } else { true };
    if x { x } else { false }; // would also be questionable, but we don't catch this yet
    bool_ret(x);
    bool_ret2(x);
    bool_ret3(x);
    bool_ret5(x, x);
    bool_ret4(x);
    bool_ret6(x, x);
    needless_bool(x);
    needless_bool2(x);
    needless_bool3(x);
}

#[allow(clippy::if_same_then_else, clippy::needless_return)]
fn bool_ret(x: bool) -> bool {
    if x { return true } else { return true };
}

#[allow(clippy::if_same_then_else, clippy::needless_return)]
fn bool_ret2(x: bool) -> bool {
    if x { return false } else { return false };
}

#[allow(clippy::needless_return)]
fn bool_ret3(x: bool) -> bool {
    if x { return true } else { return false };
}

#[allow(clippy::needless_return)]
fn bool_ret5(x: bool, y: bool) -> bool {
    if x && y { return true } else { return false };
}

#[allow(clippy::needless_return)]
fn bool_ret4(x: bool) -> bool {
    if x { return false } else { return true };
}

#[allow(clippy::needless_return)]
fn bool_ret6(x: bool, y: bool) -> bool {
    if x && y { return false } else { return true };
}

fn needless_bool(x: bool) {
   if x  == true { };
}

fn needless_bool2(x: bool) {
   if x  == false { };
}

fn needless_bool3(x: bool) {

    bool_comparison_trigger! {
        test_one:   false, false;
        test_three: false, false;
        test_two:   true, true;
    }

    if x == true { };
    if x == false { };
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io::BufReader;
use std::str;

//1 group = 512 bits = 16 * 32 bits
//512 bits = 64 bytes = 16 * 4 bytes
//32 bits = 4 bytes
//MD5 give Hex chars out
fn read_n<R>(reader: R, bytes_to_read: u64) -> Vec<u8>
where
    R: Read,
{
    let mut buf = vec![];
    let mut chunk = reader.take(bytes_to_read);
    // Do appropriate error handling for your situation
    let n = chunk.read_to_end(&mut buf).expect("Didn't read enough");
    assert_eq!(bytes_to_read as usize, n);
    buf
}

fn main() {
    let input_data = b"hello world,aaa";
    let mut reader = BufReader::new(&input_data[..]);

    let first = read_n(&mut reader, 5);
    let _ = read_n(&mut reader, 1);
    let second = read_n(&mut reader, 5);

    println!(
        "{:?}, {:?}",
        str::from_utf8(&first),
        str::from_utf8(&second),
    );
}
<commit_msg>keep coding<commit_after>use std::io::prelude::*;
use std::io::BufReader;
use std::str;

//1 group = 512 bits = 16 * 32 bits
//512 bits = 64 bytes = 16 * 4 bytes
//448 bits = 56 bytes
//32 bits = 4 bytes
//MD5 give Hex chars out
fn read_n<R>(reader: R, bytes_to_read: u64) -> Vec<u8>
where
    R: Read,
{
    let mut buf = vec![];
    let mut chunk = reader.take(bytes_to_read);
    // Do appropriate error handling for your situation
    let n = chunk.read_to_end(&mut buf);

    let size = bytes_to_read as usize;
    //if u < size {
    //
    //}

    //assert_eq!(bytes_to_read as usize, n);
    buf
}

fn read_group<R>(reader: R) -> Vec<u8>
where
    R: Read,
{
    let mut buf = vec![];
    let mut chunk = reader.take(64);
    // Do appropriate error handling for your situation
    let n = chunk.read_to_end(&mut buf).expect("Read issue error:");

    if n < 64 {
        if n < 56 {
            buf.push(0x10u8);
            for _ in 0..(56 - n + 1) {
                buf.push(0x00u8)
            }
        }
    }
    buf
}

fn main() {
    //let input_data = b"hello world,aaa";
    //let mut reader = BufReader::new(&input_data[..]);

    //let first = read_n(&mut reader, 5);
    //let _ = read_n(&mut reader, 1);
    //let second = read_n(&mut reader, 100);

    //println!(
    //    "{:?}, {:?}",
    //    str::from_utf8(&first),
    //    str::from_utf8(&second),
    //);

    let input_data = b"123456789A123456789B123456789C123456789D123456789E";
    let mut reader = BufReader::new(&input_data[..]);

    let word = read_group(&mut reader);
    println!("{:?}", str::from_utf8(&word));
}
<|endoftext|>


<commit_before>//! An asynchronous, pipelined, PostgreSQL client.
//!
//! # Example
//!
//! ```no_run
//! #![feature(async_await)]
//!
//! use futures::{FutureExt, TryStreamExt};
//! use tokio_postgres::{NoTls, Error, Row};
//!
//! # #[cfg(not(feature = "runtime"))] fn main() {}
//! # #[cfg(feature = "runtime")]
//! #[tokio::main] // By default, tokio_postgres uses the tokio crate as its runtime.
//! async fn main() -> Result<(), Error> {
//!     // Connect to the database.
//!     let (mut client, connection) =
//!         tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
//!
//!     // The connection object performs the actual communication with the database,
//!     // so spawn it off to run on its own.
//!     let connection = connection.map(|r| {
//!         if let Err(e) = r {
//!             eprintln!("connection error: {}", e);
//!         }
//!     });
//!     tokio::spawn(connection);
//!
//!     // Now we can prepare a simple statement that just returns its parameter.
//!     let stmt = client.prepare("SELECT $1::TEXT").await?;
//!
//!     // And then execute it, returning a Stream of Rows which we collect into a Vec.
//!     let rows: Vec<Row> = client
//!         .query(&stmt, &[&"hello world"])
//!         .try_collect()
//!         .await?;
//!
//!     // Now we can check that we got back the same string we sent over.
//!     let value: &str = rows[0].get(0);
//!     assert_eq!(value, "hello world");
//!
//!     Ok(())
//! }
//! ```
//!
//! # Behavior
//!
//! Calling a method like `Client::query` on its own does nothing. The associated request is not sent to the database
//! until the future returned by the method is first polled. Requests are executed in the order that they are first
//! polled, not in the order that their futures are created.
//!
//! # Pipelining
//!
//! The client supports *pipelined* requests. Pipelining can improve performance in use cases in which multiple,
//! independent queries need to be executed. In a traditional workflow, each query is sent to the server after the
//! previous query completes. In contrast, pipelining allows the client to send all of the queries to the server up
//! front, minimizing time spent by one side waiting for the other to finish sending data:
//!
//! ```not_rust
//!             Sequential                              Pipelined
//! | Client         | Server          |    | Client         | Server          |
//! |----------------|-----------------|    |----------------|-----------------|
//! | send query 1   |                 |    | send query 1   |                 |
//! |                | process query 1 |    | send query 2   | process query 1 |
//! | receive rows 1 |                 |    | send query 3   | process query 2 |
//! | send query 2   |                 |    | receive rows 1 | process query 3 |
//! |                | process query 2 |    | receive rows 2 |                 |
//! | receive rows 2 |                 |    | receive rows 3 |                 |
//! | send query 3   |                 |
//! |                | process query 3 |
//! | receive rows 3 |                 |
//! ```
//!
//! In both cases, the PostgreSQL server is executing the queries sequentially - pipelining just allows both sides of
//! the connection to work concurrently when possible.
//!
//! Pipelining happens automatically when futures are polled concurrently (for example, by using the futures `join`
//! combinator):
//!
//! ```rust
//! use futures::future;
//! use std::future::Future;
//! use tokio_postgres::{Client, Error, Statement};
//!
//! fn pipelined_prepare(
//!     client: &mut Client,
//! ) -> impl Future<Output = Result<(Statement, Statement), Error>>
//! {
//!     future::try_join(
//!         client.prepare("SELECT * FROM foo"),
//!         client.prepare("INSERT INTO bar (id, name) VALUES ($1, $2)")
//!     )
//! }
//! ```
//!
//! # Runtime
//!
//! The client works with arbitrary `AsyncRead + AsyncWrite` streams. Convenience APIs are provided to handle the
//! connection process, but these are gated by the `runtime` Cargo feature, which is enabled by default. If disabled,
//! all dependence on the tokio runtime is removed.
//!
//! # SSL/TLS support
//!
//! TLS support is implemented via external libraries. `Client::connect` and `Config::connect` take a TLS implementation
//! as an argument. The `NoTls` type in this crate can be used when TLS is not required. Otherwise, the
//! `postgres-openssl` and `postgres-native-tls` crates provide implementations backed by the `openssl` and `native-tls`
//! crates, respectively.
#![doc(html_root_url = "https://docs.rs/tokio-postgres/0.4.0-rc.3")]
#![warn(rust_2018_idioms, clippy::all, missing_docs)]

pub use crate::client::Client;
pub use crate::config::Config;
pub use crate::connection::Connection;
use crate::error::DbError;
pub use crate::error::Error;
pub use crate::portal::Portal;
pub use crate::row::{Row, SimpleQueryRow};
#[cfg(feature = "runtime")]
pub use crate::socket::Socket;
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
pub use crate::tls::NoTls;
pub use crate::transaction::Transaction;
pub use statement::{Column, Statement};

mod bind;
#[cfg(feature = "runtime")]
mod cancel_query;
mod cancel_query_raw;
mod client;
mod codec;
pub mod config;
#[cfg(feature = "runtime")]
mod connect;
mod connect_raw;
#[cfg(feature = "runtime")]
mod connect_socket;
mod connect_tls;
mod connection;
mod copy_in;
mod copy_out;
pub mod error;
mod maybe_tls_stream;
mod portal;
mod prepare;
mod query;
pub mod row;
mod simple_query;
#[cfg(feature = "runtime")]
mod socket;
mod statement;
pub mod tls;
mod transaction;
pub mod types;

/// A convenience function which parses a connection string and connects to the database.
///
/// See the documentation for [`Config`] for details on the connection string format.
///
/// Requires the `runtime` Cargo feature (enabled by default).
///
/// [`Config`]: config/struct.Config.html
#[cfg(feature = "runtime")]
pub async fn connect<T>(
    config: &str,
    tls: T,
) -> Result<(Client, Connection<Socket, T::Stream>), Error>
where
    T: MakeTlsConnect<Socket>,
{
    let config = config.parse::<Config>()?;
    // FIXME https://github.com/rust-lang/rust/issues/64391
    async move {
        config.connect(tls).await
    }.await
}

/// An asynchronous notification.
#[derive(Clone, Debug)]
pub struct Notification {
    process_id: i32,
    channel: String,
    payload: String,
}

impl Notification {
    /// The process ID of the notifying backend process.
    pub fn process_id(&self) -> i32 {
        self.process_id
    }

    /// The name of the channel that the notify has been raised on.
    pub fn channel(&self) -> &str {
        &self.channel
    }

    /// The "payload" string passed from the notifying process.
    pub fn payload(&self) -> &str {
        &self.payload
    }
}

/// An asynchronous message from the server.
#[allow(clippy::large_enum_variant)]
pub enum AsyncMessage {
    /// A notice.
    ///
    /// Notices use the same format as errors, but aren't "errors" per-se.
    Notice(DbError),
    /// A notification.
    ///
    /// Connections can subscribe to notifications with the `LISTEN` command.
    Notification(Notification),
    #[doc(hidden)]
    __NonExhaustive,
}

/// Message returned by the `SimpleQuery` stream.
pub enum SimpleQueryMessage {
    /// A row of data.
    Row(SimpleQueryRow),
    /// A statement in the query has completed.
    ///
    /// The number of rows modified or selected is returned.
    CommandComplete(u64),
    #[doc(hidden)]
    __NonExhaustive,
}
<commit_msg>Clean up workaround<commit_after>//! An asynchronous, pipelined, PostgreSQL client.
//!
//! # Example
//!
//! ```no_run
//! #![feature(async_await)]
//!
//! use futures::{FutureExt, TryStreamExt};
//! use tokio_postgres::{NoTls, Error, Row};
//!
//! # #[cfg(not(feature = "runtime"))] fn main() {}
//! # #[cfg(feature = "runtime")]
//! #[tokio::main] // By default, tokio_postgres uses the tokio crate as its runtime.
//! async fn main() -> Result<(), Error> {
//!     // Connect to the database.
//!     let (mut client, connection) =
//!         tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
//!
//!     // The connection object performs the actual communication with the database,
//!     // so spawn it off to run on its own.
//!     let connection = connection.map(|r| {
//!         if let Err(e) = r {
//!             eprintln!("connection error: {}", e);
//!         }
//!     });
//!     tokio::spawn(connection);
//!
//!     // Now we can prepare a simple statement that just returns its parameter.
//!     let stmt = client.prepare("SELECT $1::TEXT").await?;
//!
//!     // And then execute it, returning a Stream of Rows which we collect into a Vec.
//!     let rows: Vec<Row> = client
//!         .query(&stmt, &[&"hello world"])
//!         .try_collect()
//!         .await?;
//!
//!     // Now we can check that we got back the same string we sent over.
//!     let value: &str = rows[0].get(0);
//!     assert_eq!(value, "hello world");
//!
//!     Ok(())
//! }
//! ```
//!
//! # Behavior
//!
//! Calling a method like `Client::query` on its own does nothing. The associated request is not sent to the database
//! until the future returned by the method is first polled. Requests are executed in the order that they are first
//! polled, not in the order that their futures are created.
//!
//! # Pipelining
//!
//! The client supports *pipelined* requests. Pipelining can improve performance in use cases in which multiple,
//! independent queries need to be executed. In a traditional workflow, each query is sent to the server after the
//! previous query completes. In contrast, pipelining allows the client to send all of the queries to the server up
//! front, minimizing time spent by one side waiting for the other to finish sending data:
//!
//! ```not_rust
//!             Sequential                              Pipelined
//! | Client         | Server          |    | Client         | Server          |
//! |----------------|-----------------|    |----------------|-----------------|
//! | send query 1   |                 |    | send query 1   |                 |
//! |                | process query 1 |    | send query 2   | process query 1 |
//! | receive rows 1 |                 |    | send query 3   | process query 2 |
//! | send query 2   |                 |    | receive rows 1 | process query 3 |
//! |                | process query 2 |    | receive rows 2 |                 |
//! | receive rows 2 |                 |    | receive rows 3 |                 |
//! | send query 3   |                 |
//! |                | process query 3 |
//! | receive rows 3 |                 |
//! ```
//!
//! In both cases, the PostgreSQL server is executing the queries sequentially - pipelining just allows both sides of
//! the connection to work concurrently when possible.
//!
//! Pipelining happens automatically when futures are polled concurrently (for example, by using the futures `join`
//! combinator):
//!
//! ```rust
//! use futures::future;
//! use std::future::Future;
//! use tokio_postgres::{Client, Error, Statement};
//!
//! fn pipelined_prepare(
//!     client: &mut Client,
//! ) -> impl Future<Output = Result<(Statement, Statement), Error>>
//! {
//!     future::try_join(
//!         client.prepare("SELECT * FROM foo"),
//!         client.prepare("INSERT INTO bar (id, name) VALUES ($1, $2)")
//!     )
//! }
//! ```
//!
//! # Runtime
//!
//! The client works with arbitrary `AsyncRead + AsyncWrite` streams. Convenience APIs are provided to handle the
//! connection process, but these are gated by the `runtime` Cargo feature, which is enabled by default. If disabled,
//! all dependence on the tokio runtime is removed.
//!
//! # SSL/TLS support
//!
//! TLS support is implemented via external libraries. `Client::connect` and `Config::connect` take a TLS implementation
//! as an argument. The `NoTls` type in this crate can be used when TLS is not required. Otherwise, the
//! `postgres-openssl` and `postgres-native-tls` crates provide implementations backed by the `openssl` and `native-tls`
//! crates, respectively.
#![doc(html_root_url = "https://docs.rs/tokio-postgres/0.4.0-rc.3")]
#![warn(rust_2018_idioms, clippy::all, missing_docs)]

pub use crate::client::Client;
pub use crate::config::Config;
pub use crate::connection::Connection;
use crate::error::DbError;
pub use crate::error::Error;
pub use crate::portal::Portal;
pub use crate::row::{Row, SimpleQueryRow};
#[cfg(feature = "runtime")]
pub use crate::socket::Socket;
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
pub use crate::tls::NoTls;
pub use crate::transaction::Transaction;
pub use statement::{Column, Statement};

mod bind;
#[cfg(feature = "runtime")]
mod cancel_query;
mod cancel_query_raw;
mod client;
mod codec;
pub mod config;
#[cfg(feature = "runtime")]
mod connect;
mod connect_raw;
#[cfg(feature = "runtime")]
mod connect_socket;
mod connect_tls;
mod connection;
mod copy_in;
mod copy_out;
pub mod error;
mod maybe_tls_stream;
mod portal;
mod prepare;
mod query;
pub mod row;
mod simple_query;
#[cfg(feature = "runtime")]
mod socket;
mod statement;
pub mod tls;
mod transaction;
pub mod types;

/// A convenience function which parses a connection string and connects to the database.
///
/// See the documentation for [`Config`] for details on the connection string format.
///
/// Requires the `runtime` Cargo feature (enabled by default).
///
/// [`Config`]: config/struct.Config.html
#[cfg(feature = "runtime")]
pub async fn connect<T>(
    config: &str,
    tls: T,
) -> Result<(Client, Connection<Socket, T::Stream>), Error>
where
    T: MakeTlsConnect<Socket>,
{
    let config = config.parse::<Config>()?;
    return config.connect(tls).await;
}

/// An asynchronous notification.
#[derive(Clone, Debug)]
pub struct Notification {
    process_id: i32,
    channel: String,
    payload: String,
}

impl Notification {
    /// The process ID of the notifying backend process.
    pub fn process_id(&self) -> i32 {
        self.process_id
    }

    /// The name of the channel that the notify has been raised on.
    pub fn channel(&self) -> &str {
        &self.channel
    }

    /// The "payload" string passed from the notifying process.
    pub fn payload(&self) -> &str {
        &self.payload
    }
}

/// An asynchronous message from the server.
#[allow(clippy::large_enum_variant)]
pub enum AsyncMessage {
    /// A notice.
    ///
    /// Notices use the same format as errors, but aren't "errors" per-se.
    Notice(DbError),
    /// A notification.
    ///
    /// Connections can subscribe to notifications with the `LISTEN` command.
    Notification(Notification),
    #[doc(hidden)]
    __NonExhaustive,
}

/// Message returned by the `SimpleQuery` stream.
pub enum SimpleQueryMessage {
    /// A row of data.
    Row(SimpleQueryRow),
    /// A statement in the query has completed.
    ///
    /// The number of rows modified or selected is returned.
    CommandComplete(u64),
    #[doc(hidden)]
    __NonExhaustive,
}
<|endoftext|>


<commit_before>extern crate elf;
extern crate getopts;

use getopts::Options;
use std::cmp;
use std::env;
use std::fmt;
use std::fs::File;
use std::io;
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use std::mem;
use std::path::Path;
use std::slice;

/// Takes a value and rounds it up to be aligned % 4
macro_rules! align4 {
    ( $e:expr ) => ( ($e) + ((4 - (($e) % 4)) % 4 ) );
}

#[repr(u16)]
#[derive(Clone, Copy, Debug)]
#[allow(dead_code)]
enum TbfHeaderTypes {
    TbfHeaderMain = 1,
    TbfHeaderWriteableFlashRegions = 2,
    TbfHeaderPackageName = 3,
    TbfHeaderPicOption1 = 4,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct TbfHeaderTlv {
    tipe: TbfHeaderTypes,
    length: u16,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct TbfHeaderBase {
    version: u16,
    header_size: u16,
    total_size: u32,
    flags: u32,
    checksum: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct TbfHeaderMain {
    base: TbfHeaderTlv,
    init_fn_offset: u32,
    protected_size: u32,
    minimum_ram_size: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct TbfHeaderWriteableFlashRegion {
    offset: u32,
    size: u32,
}

impl fmt::Display for TbfHeaderBase {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "
               version: {:>8} {:>#10X}
           header_size: {:>8} {:>#10X}
            total_size: {:>8} {:>#10X}
                 flags: {:>8} {:>#10X}
",
            self.version,
            self.version,
            self.header_size,
            self.header_size,
            self.total_size,
            self.total_size,
            self.flags,
            self.flags,
        )
    }
}

impl fmt::Display for TbfHeaderMain {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "
        init_fn_offset: {:>8} {:>#10X}
        protected_size: {:>8} {:>#10X}
      minimum_ram_size: {:>8} {:>#10X}
",
            self.init_fn_offset,
            self.init_fn_offset,
            self.protected_size,
            self.protected_size,
            self.minimum_ram_size,
            self.minimum_ram_size,
        )
    }
}

impl fmt::Display for TbfHeaderWriteableFlashRegion {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "
    flash region:
                offset: {:>8} {:>#10X}
                  size: {:>8} {:>#10X}
",
            self.offset, self.offset, self.size, self.size,
        )
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "OUTFILE");
    opts.optopt("n", "", "set package name", "PACKAGE_NAME");
    opts.optflag("v", "verbose", "be verbose");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };
    let output = matches.opt_str("o");
    let package_name = matches.opt_str("n");
    let verbose = matches.opt_present("v");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };

    let path = Path::new(&input);
    let file = match elf::File::open_path(&path) {
        Ok(f) => f,
        Err(e) => panic!("Error: {:?}", e),
    };

    match output {
        None => {
            let mut out = io::stdout();
            do_work(&file, &mut out, package_name, verbose)
        }
        Some(name) => match File::create(Path::new(&name)) {
            Ok(mut f) => do_work(&file, &mut f, package_name, verbose),
            Err(e) => panic!("Error: {:?}", e),
        },
    }.expect("Failed to write output");
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [-o OUTFILE] FILE", program);
    print!("{}", opts.usage(&brief));
}

fn get_section<'a>(input: &'a elf::File, name: &str) -> elf::Section {
    match input.get_section(name) {
        Some(section) => elf::Section {
            data: section.data.clone(),
            shdr: section.shdr.clone(),
        },
        None => elf::Section {
            data: Vec::new(),
            shdr: elf::types::SectionHeader {
                name: String::from(name),
                shtype: elf::types::SHT_NULL,
                flags: elf::types::SHF_NONE,
                addr: 0,
                offset: 0,
                size: 0,
                link: 0,
                info: 0,
                addralign: 0,
                entsize: 0,
            },
        },
    }
}

unsafe fn as_byte_slice<'a, T: Copy>(input: &'a T) -> &'a [u8] {
    slice::from_raw_parts(input as *const T as *const u8, mem::size_of::<T>())
}

fn do_work(
    input: &elf::File,
    output: &mut Write,
    package_name: Option<String>,
    verbose: bool,
) -> io::Result<()> {
    let package_name = package_name.unwrap_or(String::new());
    let rel_data = input
        .sections
        .iter()
        .find(|section| section.shdr.name == ".rel.data".as_ref())
        .map(|section| section.data.as_ref())
        .unwrap_or(&[] as &[u8]);
    let text = get_section(input, ".text");
    let got = get_section(input, ".got");
    let data = get_section(input, ".data");
    let bss = get_section(input, ".bss");
    let appstate = get_section(input, ".app_state");

    // For these, we only care about the length
    let stack_len = get_section(input, ".stack").data.len() as u32;
    let app_heap_len = get_section(input, ".app_heap").data.len() as u32;
    let kernel_heap_len = get_section(input, ".kernel_heap").data.len() as u32;

    // Need to calculate lengths ahead of time.
    // Need the base and the main section.
    let mut header_length = mem::size_of::<TbfHeaderBase>() + mem::size_of::<TbfHeaderMain>();

    // If we have a package name, add that section.
    let mut post_name_pad = 0;
    if package_name.len() > 0 {
        let name_total_size = align4!(mem::size_of::<TbfHeaderTlv>() + package_name.len());
        header_length += name_total_size;

        // Calculate the padding required after the package name TLV. All blocks
        // must be four byte aligned, so we may need to add some padding.
        post_name_pad = name_total_size - (mem::size_of::<TbfHeaderTlv>() + package_name.len());
    }

    // We have one app flash region, add that.
    if appstate.data.len() > 0 {
        header_length +=
            mem::size_of::<TbfHeaderTlv>() + mem::size_of::<TbfHeaderWriteableFlashRegion>();
    }

    // Calculate the offset between the start of the flash region and the actual
    // app code. Also need to get the padding size.
    let app_start_offset = align4!(header_length);
    let post_header_pad = app_start_offset as usize - header_length;

    // Now we can calculate the entire size of the app in flash.
    let rel_data_len = 4 + rel_data.len(); // +4 because we're going to length-prefix it
    let mut total_size = (header_length + post_header_pad + rel_data_len + text.data.len()
        + got.data.len() + data.data.len() + appstate.data.len()) as u32;

    let ending_pad = if total_size.count_ones() > 1 {
        let power2len = cmp::max(1 << (32 - total_size.leading_zeros()), 512);
        power2len - total_size
    } else {
        0
    };
    total_size += ending_pad;

    // To start we just restrict the app from writing all of the space before
    // its actual code and whatnot.
    let protected_size = 0;

    // First up is the app writeable app_state section. If this is not used or
    // non-existent, it will just be zero and won't matter. But we put it first
    // so that changes to the app won't move it.
    let appstate_offset = app_start_offset as u32;
    let appstate_size = appstate.shdr.size as u32;
    // Make sure we pad back to a multiple of 4.
    let post_appstate_pad =
        align4!(appstate_offset + appstate_size) - (appstate_offset + appstate_size);
    let init_fn_offset = (input.ehdr.entry - text.shdr.addr) as u32;
    let got_size = got.shdr.size as u32;
    let data_size = data.shdr.size as u32;
    let bss_size = bss.shdr.size as u32;
    let minimum_ram_size =
        stack_len + app_heap_len + kernel_heap_len + got_size + data_size + bss_size;

    // Flags default to app is enabled.
    let flags = 0x00000001;

    let tbf_header_version = 2;

    let tbf_header = TbfHeaderBase {
        version: tbf_header_version,
        header_size: header_length as u16,
        total_size: total_size,
        flags: flags,
        checksum: 0,
    };

    let tbf_main = TbfHeaderMain {
        base: TbfHeaderTlv {
            tipe: TbfHeaderTypes::TbfHeaderMain,
            length: (mem::size_of::<TbfHeaderMain>() - mem::size_of::<TbfHeaderTlv>()) as u16,
        },
        init_fn_offset: init_fn_offset,
        protected_size: protected_size as u32,
        minimum_ram_size: minimum_ram_size,
    };

    let tbf_package_name_tlv = TbfHeaderTlv {
        tipe: TbfHeaderTypes::TbfHeaderPackageName,
        length: package_name.len() as u16,
    };

    let tbf_flash_regions_tlv = TbfHeaderTlv {
        tipe: TbfHeaderTypes::TbfHeaderWriteableFlashRegions,
        length: 8,
    };

    let tbf_flash_region = TbfHeaderWriteableFlashRegion {
        offset: appstate_offset,
        size: appstate_size,
    };

    if verbose {
        print!("{}", tbf_header);
        print!("{}", tbf_main);
        print!("{}", tbf_flash_region);
    }

    // Calculate the header checksum.
    let mut header_buf = Cursor::new(Vec::new());

    // Write all bytes to an in-memory file for the header.
    try!(header_buf.write_all(unsafe { as_byte_slice(&tbf_header) }));
    try!(header_buf.write_all(unsafe { as_byte_slice(&tbf_main) }));
    try!(header_buf.write_all(unsafe { as_byte_slice(&tbf_package_name_tlv) }));
    try!(header_buf.write_all(package_name.as_ref()));
    try!(do_pad(&mut header_buf, post_name_pad));

    // Only put these in the header if the app_state section is nonzero.
    if appstate.data.len() > 0 {
        try!(header_buf.write_all(unsafe { as_byte_slice(&tbf_flash_regions_tlv) }));
        try!(header_buf.write_all(unsafe { as_byte_slice(&tbf_flash_region) }));
    }

    // Start from the beginning and iterate through the buffer as words.
    try!(header_buf.seek(SeekFrom::Start(0)));
    let mut wordbuf = [0u8; 4];
    let mut checksum: u32 = 0;
    loop {
        let ret = header_buf.read(&mut wordbuf);
        match ret {
            Ok(count) => {
                // Combine the bytes back into a word, handling if we don't
                // get a full word.
                let mut word = 0;
                for i in 0..count {
                    word |= (wordbuf[i] as u32) << (8 * i);
                }
                checksum ^= word;
                if count != 4 {
                    break;
                }
            }
            Err(_) => println!("Error calculating checksum."),
        }
    }

    // Now we need to insert the checksum into the correct position in the
    // header.
    try!(header_buf.seek(SeekFrom::Start(12)));
    wordbuf[0] = ((checksum >> 0) & 0xFF) as u8;
    wordbuf[1] = ((checksum >> 8) & 0xFF) as u8;
    wordbuf[2] = ((checksum >> 16) & 0xFF) as u8;
    wordbuf[3] = ((checksum >> 24) & 0xFF) as u8;
    try!(header_buf.write(&wordbuf));
    try!(header_buf.seek(SeekFrom::Start(0)));

    fn do_pad(output: &mut Write, length: usize) -> io::Result<()> {
        let mut pad = length;
        let zero_buf = [0u8; 512];
        while pad > 0 {
            let amount_to_write = cmp::min(zero_buf.len(), pad);
            pad -= try!(output.write(&zero_buf[..amount_to_write]));
        }
        Ok(())
    }

    // Write the header and actual app to a binary file.
    try!(output.write_all(header_buf.get_ref()));
    try!(do_pad(output, post_header_pad as usize));
    try!(output.write_all(appstate.data.as_ref()));
    try!(do_pad(output, post_appstate_pad as usize));
    try!(output.write_all(text.data.as_ref()));
    try!(output.write_all(got.data.as_ref()));
    try!(output.write_all(data.data.as_ref()));
    let rel_data_len: [u8; 4] = [
        (rel_data.len() & 0xff) as u8,
        (rel_data.len() >> 8 & 0xff) as u8,
        (rel_data.len() >> 16 & 0xff) as u8,
        (rel_data.len() >> 24 & 0xff) as u8,
    ];
    try!(output.write_all(&rel_data_len));
    try!(output.write_all(rel_data.as_ref()));

    // Pad to get a power of 2 sized flash app.
    try!(do_pad(output, ending_pad as usize));

    Ok(())
}
<commit_msg>rustfmt v0.6<commit_after>extern crate elf;
extern crate getopts;

use getopts::Options;
use std::cmp;
use std::env;
use std::fmt;
use std::fs::File;
use std::io;
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use std::mem;
use std::path::Path;
use std::slice;

/// Takes a value and rounds it up to be aligned % 4
macro_rules! align4 {
    ($e:expr) => {
        ($e) + ((4 - (($e) % 4)) % 4)
    };
}

#[repr(u16)]
#[derive(Clone, Copy, Debug)]
#[allow(dead_code)]
enum TbfHeaderTypes {
    TbfHeaderMain = 1,
    TbfHeaderWriteableFlashRegions = 2,
    TbfHeaderPackageName = 3,
    TbfHeaderPicOption1 = 4,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct TbfHeaderTlv {
    tipe: TbfHeaderTypes,
    length: u16,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct TbfHeaderBase {
    version: u16,
    header_size: u16,
    total_size: u32,
    flags: u32,
    checksum: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct TbfHeaderMain {
    base: TbfHeaderTlv,
    init_fn_offset: u32,
    protected_size: u32,
    minimum_ram_size: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct TbfHeaderWriteableFlashRegion {
    offset: u32,
    size: u32,
}

impl fmt::Display for TbfHeaderBase {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "
               version: {:>8} {:>#10X}
           header_size: {:>8} {:>#10X}
            total_size: {:>8} {:>#10X}
                 flags: {:>8} {:>#10X}
",
            self.version,
            self.version,
            self.header_size,
            self.header_size,
            self.total_size,
            self.total_size,
            self.flags,
            self.flags,
        )
    }
}

impl fmt::Display for TbfHeaderMain {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "
        init_fn_offset: {:>8} {:>#10X}
        protected_size: {:>8} {:>#10X}
      minimum_ram_size: {:>8} {:>#10X}
",
            self.init_fn_offset,
            self.init_fn_offset,
            self.protected_size,
            self.protected_size,
            self.minimum_ram_size,
            self.minimum_ram_size,
        )
    }
}

impl fmt::Display for TbfHeaderWriteableFlashRegion {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "
    flash region:
                offset: {:>8} {:>#10X}
                  size: {:>8} {:>#10X}
",
            self.offset, self.offset, self.size, self.size,
        )
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "OUTFILE");
    opts.optopt("n", "", "set package name", "PACKAGE_NAME");
    opts.optflag("v", "verbose", "be verbose");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };
    let output = matches.opt_str("o");
    let package_name = matches.opt_str("n");
    let verbose = matches.opt_present("v");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };

    let path = Path::new(&input);
    let file = match elf::File::open_path(&path) {
        Ok(f) => f,
        Err(e) => panic!("Error: {:?}", e),
    };

    match output {
        None => {
            let mut out = io::stdout();
            do_work(&file, &mut out, package_name, verbose)
        }
        Some(name) => match File::create(Path::new(&name)) {
            Ok(mut f) => do_work(&file, &mut f, package_name, verbose),
            Err(e) => panic!("Error: {:?}", e),
        },
    }.expect("Failed to write output");
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [-o OUTFILE] FILE", program);
    print!("{}", opts.usage(&brief));
}

fn get_section<'a>(input: &'a elf::File, name: &str) -> elf::Section {
    match input.get_section(name) {
        Some(section) => elf::Section {
            data: section.data.clone(),
            shdr: section.shdr.clone(),
        },
        None => elf::Section {
            data: Vec::new(),
            shdr: elf::types::SectionHeader {
                name: String::from(name),
                shtype: elf::types::SHT_NULL,
                flags: elf::types::SHF_NONE,
                addr: 0,
                offset: 0,
                size: 0,
                link: 0,
                info: 0,
                addralign: 0,
                entsize: 0,
            },
        },
    }
}

unsafe fn as_byte_slice<'a, T: Copy>(input: &'a T) -> &'a [u8] {
    slice::from_raw_parts(input as *const T as *const u8, mem::size_of::<T>())
}

fn do_work(
    input: &elf::File,
    output: &mut Write,
    package_name: Option<String>,
    verbose: bool,
) -> io::Result<()> {
    let package_name = package_name.unwrap_or(String::new());
    let rel_data = input
        .sections
        .iter()
        .find(|section| section.shdr.name == ".rel.data".as_ref())
        .map(|section| section.data.as_ref())
        .unwrap_or(&[] as &[u8]);
    let text = get_section(input, ".text");
    let got = get_section(input, ".got");
    let data = get_section(input, ".data");
    let bss = get_section(input, ".bss");
    let appstate = get_section(input, ".app_state");

    // For these, we only care about the length
    let stack_len = get_section(input, ".stack").data.len() as u32;
    let app_heap_len = get_section(input, ".app_heap").data.len() as u32;
    let kernel_heap_len = get_section(input, ".kernel_heap").data.len() as u32;

    // Need to calculate lengths ahead of time.
    // Need the base and the main section.
    let mut header_length = mem::size_of::<TbfHeaderBase>() + mem::size_of::<TbfHeaderMain>();

    // If we have a package name, add that section.
    let mut post_name_pad = 0;
    if package_name.len() > 0 {
        let name_total_size = align4!(mem::size_of::<TbfHeaderTlv>() + package_name.len());
        header_length += name_total_size;

        // Calculate the padding required after the package name TLV. All blocks
        // must be four byte aligned, so we may need to add some padding.
        post_name_pad = name_total_size - (mem::size_of::<TbfHeaderTlv>() + package_name.len());
    }

    // We have one app flash region, add that.
    if appstate.data.len() > 0 {
        header_length +=
            mem::size_of::<TbfHeaderTlv>() + mem::size_of::<TbfHeaderWriteableFlashRegion>();
    }

    // Calculate the offset between the start of the flash region and the actual
    // app code. Also need to get the padding size.
    let app_start_offset = align4!(header_length);
    let post_header_pad = app_start_offset as usize - header_length;

    // Now we can calculate the entire size of the app in flash.
    let rel_data_len = 4 + rel_data.len(); // +4 because we're going to length-prefix it
    let mut total_size = (header_length + post_header_pad + rel_data_len + text.data.len()
        + got.data.len() + data.data.len() + appstate.data.len()) as u32;

    let ending_pad = if total_size.count_ones() > 1 {
        let power2len = cmp::max(1 << (32 - total_size.leading_zeros()), 512);
        power2len - total_size
    } else {
        0
    };
    total_size += ending_pad;

    // To start we just restrict the app from writing all of the space before
    // its actual code and whatnot.
    let protected_size = 0;

    // First up is the app writeable app_state section. If this is not used or
    // non-existent, it will just be zero and won't matter. But we put it first
    // so that changes to the app won't move it.
    let appstate_offset = app_start_offset as u32;
    let appstate_size = appstate.shdr.size as u32;
    // Make sure we pad back to a multiple of 4.
    let post_appstate_pad =
        align4!(appstate_offset + appstate_size) - (appstate_offset + appstate_size);
    let init_fn_offset = (input.ehdr.entry - text.shdr.addr) as u32;
    let got_size = got.shdr.size as u32;
    let data_size = data.shdr.size as u32;
    let bss_size = bss.shdr.size as u32;
    let minimum_ram_size =
        stack_len + app_heap_len + kernel_heap_len + got_size + data_size + bss_size;

    // Flags default to app is enabled.
    let flags = 0x00000001;

    let tbf_header_version = 2;

    let tbf_header = TbfHeaderBase {
        version: tbf_header_version,
        header_size: header_length as u16,
        total_size: total_size,
        flags: flags,
        checksum: 0,
    };

    let tbf_main = TbfHeaderMain {
        base: TbfHeaderTlv {
            tipe: TbfHeaderTypes::TbfHeaderMain,
            length: (mem::size_of::<TbfHeaderMain>() - mem::size_of::<TbfHeaderTlv>()) as u16,
        },
        init_fn_offset: init_fn_offset,
        protected_size: protected_size as u32,
        minimum_ram_size: minimum_ram_size,
    };

    let tbf_package_name_tlv = TbfHeaderTlv {
        tipe: TbfHeaderTypes::TbfHeaderPackageName,
        length: package_name.len() as u16,
    };

    let tbf_flash_regions_tlv = TbfHeaderTlv {
        tipe: TbfHeaderTypes::TbfHeaderWriteableFlashRegions,
        length: 8,
    };

    let tbf_flash_region = TbfHeaderWriteableFlashRegion {
        offset: appstate_offset,
        size: appstate_size,
    };

    if verbose {
        print!("{}", tbf_header);
        print!("{}", tbf_main);
        print!("{}", tbf_flash_region);
    }

    // Calculate the header checksum.
    let mut header_buf = Cursor::new(Vec::new());

    // Write all bytes to an in-memory file for the header.
    try!(header_buf.write_all(unsafe { as_byte_slice(&tbf_header) }));
    try!(header_buf.write_all(unsafe { as_byte_slice(&tbf_main) }));
    try!(header_buf.write_all(unsafe { as_byte_slice(&tbf_package_name_tlv) }));
    try!(header_buf.write_all(package_name.as_ref()));
    try!(do_pad(&mut header_buf, post_name_pad));

    // Only put these in the header if the app_state section is nonzero.
    if appstate.data.len() > 0 {
        try!(header_buf.write_all(unsafe { as_byte_slice(&tbf_flash_regions_tlv) }));
        try!(header_buf.write_all(unsafe { as_byte_slice(&tbf_flash_region) }));
    }

    // Start from the beginning and iterate through the buffer as words.
    try!(header_buf.seek(SeekFrom::Start(0)));
    let mut wordbuf = [0u8; 4];
    let mut checksum: u32 = 0;
    loop {
        let ret = header_buf.read(&mut wordbuf);
        match ret {
            Ok(count) => {
                // Combine the bytes back into a word, handling if we don't
                // get a full word.
                let mut word = 0;
                for i in 0..count {
                    word |= (wordbuf[i] as u32) << (8 * i);
                }
                checksum ^= word;
                if count != 4 {
                    break;
                }
            }
            Err(_) => println!("Error calculating checksum."),
        }
    }

    // Now we need to insert the checksum into the correct position in the
    // header.
    try!(header_buf.seek(SeekFrom::Start(12)));
    wordbuf[0] = ((checksum >> 0) & 0xFF) as u8;
    wordbuf[1] = ((checksum >> 8) & 0xFF) as u8;
    wordbuf[2] = ((checksum >> 16) & 0xFF) as u8;
    wordbuf[3] = ((checksum >> 24) & 0xFF) as u8;
    try!(header_buf.write(&wordbuf));
    try!(header_buf.seek(SeekFrom::Start(0)));

    fn do_pad(output: &mut Write, length: usize) -> io::Result<()> {
        let mut pad = length;
        let zero_buf = [0u8; 512];
        while pad > 0 {
            let amount_to_write = cmp::min(zero_buf.len(), pad);
            pad -= try!(output.write(&zero_buf[..amount_to_write]));
        }
        Ok(())
    }

    // Write the header and actual app to a binary file.
    try!(output.write_all(header_buf.get_ref()));
    try!(do_pad(output, post_header_pad as usize));
    try!(output.write_all(appstate.data.as_ref()));
    try!(do_pad(output, post_appstate_pad as usize));
    try!(output.write_all(text.data.as_ref()));
    try!(output.write_all(got.data.as_ref()));
    try!(output.write_all(data.data.as_ref()));
    let rel_data_len: [u8; 4] = [
        (rel_data.len() & 0xff) as u8,
        (rel_data.len() >> 8 & 0xff) as u8,
        (rel_data.len() >> 16 & 0xff) as u8,
        (rel_data.len() >> 24 & 0xff) as u8,
    ];
    try!(output.write_all(&rel_data_len));
    try!(output.write_all(rel_data.as_ref()));

    // Pad to get a power of 2 sized flash app.
    try!(do_pad(output, ending_pad as usize));

    Ok(())
}
<|endoftext|>


<commit_before>extern crate byteorder;

use byteorder::{BigEndian, ByteOrder};

struct Memory {
	ram: [u8; 2048],
}

impl Memory {
	fn load_font_into_memory(&mut self) {
		let chip8_fontset: [u8; 80] =
		[
			// Zero
			0b11110000,
			0b10010000,
			0b10010000,
			0b10010000,
			0b11110000,

			// One
			0b00100000,
			0b01100000,
			0b00100000,
			0b00100000,
			0b01110000,

			// Two
		  	0b11110000,
		  	0b00010000,
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,

		  	// Three
		  	0b11110000,
		  	0b00010000,
		  	0b11110000,
		  	0b00010000,
		  	0b11110000,

		  	// Four
		  	0b10010000,
		  	0b10010000,
		  	0b11110000,
		  	0b00010000,
		  	0b00010000,

		  	// Five
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,
		  	0b00010000,
		  	0b11110000,

		  	// Six
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,
		  	0b10010000,
		  	0b11110000,

		  	// Seven
		  	0b11110000,
		  	0b00010000,
		  	0b00100000,
		  	0b01000000,
		  	0b01000000,

		  	// Eight
		  	0b11110000,
		  	0b10010000,
		  	0b11110000,
		  	0b10010000,
		  	0b11110000,

		  	// Nine
		  	0b11110000,
		  	0b10010000,
		  	0b11110000,
		  	0b00010000,
		  	0b11110000,

		  	// A
		  	0b11110000,
		  	0b10010000,
		  	0b11110000,
		  	0b10010000,
		  	0b10010000,

		  	// B
		  	0b11100000,
		  	0b10010000,
		  	0b11100000,
		  	0b10010000,
		  	0b11100000,

		  	// C
		  	0b11110000,
		  	0b10000000,
		  	0b10000000,
		  	0b10000000,
		  	0b11110000,

		  	// D
		  	0b11100000,
		  	0b10010000,
		  	0b10010000,
		  	0b10010000,
		  	0b11100000,

		  	// E
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,

		  	// F
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,
		  	0b10000000,
		  	0b10000000,
		];
		// Font should be loaded into offset 0x50 (80).
		self.ram[0x50..0xA0].copy_from_slice(&chip8_fontset);
	}

	#[inline]
	fn load_rom_into_memory(&mut self, rom: &[u8; 1536]) {
		self.ram[0x200..].copy_from_slice(rom);
	}

	#[inline]
	fn read_unsigned_short(&self, position: u16) -> u16 {
		BigEndian::read_u16(&self.ram[position as usize..])
	}
}

struct Registers {
	// Program counter
	pc: u16,
	// Index register
	index: u16,
	// 15 general-purpose registers + 1 carry flag
	v: [u8; 16],
}

struct Stack {
	// 16 stack addresses
	stack: [u16; 16],
	// Stack pointer
	sp: u16,
}

struct Input {
	// 16 keys
	keys: [u8; 16],
}

struct Display {
	//  64x32, black or white
	screen: [[bool; 64]; 32],
}

pub struct Chip8 {
	memory: Memory,
	registers: Registers,
	stack: Stack,
	input: Input,
	display: Display,
}

impl Chip8 {
	pub fn new_and_init() -> Chip8 {
		let mut chip8 = Chip8 {
			memory: Memory { ram: [0; 2048]},
			// Program counter starts at 0x200
			registers: Registers { pc: 0x200, index: 0, v: [0; 16]},
			stack: Stack { stack: [0; 16], sp: 0},
			input: Input { keys: [0; 16]},
			display: Display { screen: [[false; 64]; 32]},
		};
		chip8.reset();
		return chip8;
	}

	pub fn reset(&mut self) {
		self.memory.ram = [0; 2048];
		self.registers.pc = 0x200;
		self.registers.index = 0;
		self.registers.v = [0; 16];
		self.stack.stack = [0; 16];
		self.stack.sp = 0;
		self.input.keys = [0; 16];
		self.display.screen = [[false; 64]; 32];

		self.memory.load_font_into_memory();
	}

	pub fn load_rom(&mut self, rom: &[u8; 1536]) {
		self.memory.load_rom_into_memory(rom);
	}

	fn fetch_next_opcode(&self) -> u16 {
		self.memory.read_unsigned_short(self.registers.pc)
	}
}

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

    #[test]
    fn test_default_state() {
    	// PC counter should default to 0x200:
    	let chip8 = Chip8::new_and_init();
    	assert_eq!(0x200, chip8.registers.pc);
    	// We should also already have the font in ram:
    	test_font_in_memory(&chip8.memory);
    }

    #[test]
    fn test_load_font() {
    	let mut memory = Memory { ram: [0; 2048]};
    	memory.load_font_into_memory();
    	for i in 0..80 {
    		assert_eq!(0, memory.ram[i]);
    	}
    }

    fn test_font_in_memory(memory: &Memory) {
    	// Check if zero is at the right place:
    	assert_eq!(0b11110000, memory.ram[0x50]);
    	assert_eq!(0b10010000, memory.ram[0x51]);
    	assert_eq!(0b10010000, memory.ram[0x52]);
    	assert_eq!(0b10010000, memory.ram[0x53]);
    	assert_eq!(0b11110000, memory.ram[0x54]);
    }

    #[test]
    fn test_load_rom() {
    	let mut memory = Memory { ram: [0; 2048]};
    	let mut rom: [u8; 1536] = [0; 1536];
    	rom[0] = 0xFF;
    	rom[1] = 0xCC;

    	memory.load_rom_into_memory(&rom);
    	assert_eq!(memory.ram[0x200], 0xFF);
    	assert_eq!(memory.ram[0x201], 0xCC);
    }

    #[test]
    fn test_read_next_opcode() {
    	let mut chip8 = Chip8::new_and_init();
    	chip8.memory.ram[chip8.registers.pc as usize] = 0xFF;
    	chip8.memory.ram[(chip8.registers.pc + 1) as usize] = 0x77;
    	let next_opcode = chip8.fetch_next_opcode();
    	// If fetched in big-endian order, then should match as below:
    	assert_eq!(65399, next_opcode);
    }
}<commit_msg>Start adding opcodes and operations to manipulate the stack<commit_after>// TODO remove this external dependency
extern crate byteorder;

use byteorder::{BigEndian, ByteOrder};

struct Memory {
	ram: [u8; 2048],
}

// TODO reorganize?

impl Memory {
	fn load_font_into_memory(&mut self) {
		let chip8_fontset: [u8; 80] =
		[
			// Zero
			0b11110000,
			0b10010000,
			0b10010000,
			0b10010000,
			0b11110000,

			// One
			0b00100000,
			0b01100000,
			0b00100000,
			0b00100000,
			0b01110000,

			// Two
		  	0b11110000,
		  	0b00010000,
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,

		  	// Three
		  	0b11110000,
		  	0b00010000,
		  	0b11110000,
		  	0b00010000,
		  	0b11110000,

		  	// Four
		  	0b10010000,
		  	0b10010000,
		  	0b11110000,
		  	0b00010000,
		  	0b00010000,

		  	// Five
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,
		  	0b00010000,
		  	0b11110000,

		  	// Six
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,
		  	0b10010000,
		  	0b11110000,

		  	// Seven
		  	0b11110000,
		  	0b00010000,
		  	0b00100000,
		  	0b01000000,
		  	0b01000000,

		  	// Eight
		  	0b11110000,
		  	0b10010000,
		  	0b11110000,
		  	0b10010000,
		  	0b11110000,

		  	// Nine
		  	0b11110000,
		  	0b10010000,
		  	0b11110000,
		  	0b00010000,
		  	0b11110000,

		  	// A
		  	0b11110000,
		  	0b10010000,
		  	0b11110000,
		  	0b10010000,
		  	0b10010000,

		  	// B
		  	0b11100000,
		  	0b10010000,
		  	0b11100000,
		  	0b10010000,
		  	0b11100000,

		  	// C
		  	0b11110000,
		  	0b10000000,
		  	0b10000000,
		  	0b10000000,
		  	0b11110000,

		  	// D
		  	0b11100000,
		  	0b10010000,
		  	0b10010000,
		  	0b10010000,
		  	0b11100000,

		  	// E
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,

		  	// F
		  	0b11110000,
		  	0b10000000,
		  	0b11110000,
		  	0b10000000,
		  	0b10000000,
		];
		// Font should be loaded into offset 0x50 (80).
		self.ram[0x50..0xA0].copy_from_slice(&chip8_fontset);
	}

	#[inline]
	fn load_rom_into_memory(&mut self, rom: &[u8; 1536]) {
		self.ram[0x200..].copy_from_slice(rom);
	}

	#[inline]
	fn read_unsigned_short(&self, position: u16) -> u16 {
		BigEndian::read_u16(&self.ram[position as usize..])
	}
}

struct Registers {
	// Program counter
	pc: u16,
	// Index register
	index: u16,
	// 15 general-purpose registers + 1 carry flag
	v: [u8; 16],
}

struct Stack {
	// 16 stack addresses
	ret_addresses: [u16; 16],
	// Stack pointer
	sp: u16,
}

struct Input {
	// 16 keys
	keys: [u8; 16],
}

// TODO need a flag when need to update (AFAIK two ops should affect that?)

struct Display {
	//  64x32, black or white
	screen: [[bool; 64]; 32],
	needs_draw: bool,
}

pub struct Chip8 {
	memory: Memory,
	registers: Registers,
	stack: Stack,
	input: Input,
	display: Display,
}

impl Chip8 {
	pub fn new_and_init() -> Chip8 {
		let mut chip8 = Chip8 {
			memory: Memory { ram: [0; 2048]},
			// Program counter starts at 0x200
			registers: Registers { pc: 0x200, index: 0, v: [0; 16]},
			stack: Stack { ret_addresses: [0; 16], sp: 0},
			input: Input { keys: [0; 16]},
			display: Display { screen: [[false; 64]; 32], needs_draw: false},
		};
		chip8.reset();
		return chip8;
	}

	pub fn reset(&mut self) {
		self.memory.ram = [0; 2048];
		self.registers.pc = 0x200;
		self.registers.index = 0;
		self.registers.v = [0; 16];
		self.stack.ret_addresses = [0; 16];
		self.stack.sp = 0;
		self.input.keys = [0; 16];
		self.display.screen = [[false; 64]; 32];

		self.memory.load_font_into_memory();
	}

	pub fn load_rom(&mut self, rom: &[u8; 1536]) {
		self.memory.load_rom_into_memory(rom);
	}

	fn execute_next_opcode(&mut self) {
		let opcode = self.memory.read_unsigned_short(self.registers.pc);
		match opcode {
			0x00E0 => {
				// Clear the screen.
				self.display.screen = [[false; 64]; 32];
				self.display.needs_draw = true;
				self.registers.pc += 2;
			},
			0x00EE => {
				// Return from a subroutine.
				self.stack.sp -= 1;
				self.registers.pc = self.stack.ret_addresses[self.stack.sp as usize];
			},
			0x1000...0x1FFF => {
				// Jump
				let address = get_address_from_opcode(opcode);
				self.registers.pc = address;
			},
			0x2000...0x2FFF => {
				// Call a subroutine.
				// The return address should be after the opcode we're executing now.
				self.stack.ret_addresses[self.stack.sp as usize] = self.registers.pc + 2;
				self.stack.sp += 1;
				// Jump to the address in the opcode.
				let address = get_address_from_opcode(opcode);
				self.registers.pc = address;
			},
			_ => {
				// TODO unknown opcode
			}
		}
	}
}

fn get_address_from_opcode(opcode: u16) -> u16 {
	opcode & 0x0FFF
}

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

    /// Memory tests ///

    #[test]
    fn test_load_font() {
    	let mut memory = Memory { ram: [0; 2048]};
    	memory.load_font_into_memory();
    	for i in 0..80 {
    		assert_eq!(0, memory.ram[i]);
    	}
    }

    fn test_font_in_memory(memory: &Memory) {
    	// Check if zero is at the right place:
    	assert_eq!(0b11110000, memory.ram[0x50]);
    	assert_eq!(0b10010000, memory.ram[0x51]);
    	assert_eq!(0b10010000, memory.ram[0x52]);
    	assert_eq!(0b10010000, memory.ram[0x53]);
    	assert_eq!(0b11110000, memory.ram[0x54]);
    }

    #[test]
    fn test_load_rom() {
    	let mut memory = Memory { ram: [0; 2048]};
    	let mut rom: [u8; 1536] = [0; 1536];
    	rom[0] = 0xFF;
    	rom[1] = 0xCC;

    	memory.load_rom_into_memory(&rom);
    	assert_eq!(memory.ram[0x200], 0xFF);
    	assert_eq!(memory.ram[0x201], 0xCC);
    }

    #[test]
    fn test_read_unsigned_short() {
    	let mut chip8 = Chip8::new_and_init();
    	chip8.memory.ram[chip8.registers.pc as usize] = 0xFF;
    	chip8.memory.ram[(chip8.registers.pc + 1) as usize] = 0x77;
    	let next_opcode = chip8.memory.read_unsigned_short(chip8.registers.pc);
    	// If fetched in big-endian order, then should match as below:
    	assert_eq!(65399, next_opcode);
    }

    /// State tests ///

    #[test]
    fn test_default_state() {
    	// PC counter should default to 0x200:
    	let chip8 = Chip8::new_and_init();
    	assert_eq!(0x200, chip8.registers.pc);
    	// We should also already have the font in ram:
    	test_font_in_memory(&chip8.memory);
    }

    /// Opcode tests ///

    #[test]
    fn test_clear_screen() {
    	let mut chip8 = Chip8::new_and_init();
    	chip8.display.screen[0][0] = true;
    	chip8.display.screen[0][1] = true;
    	chip8.display.screen[0][2] = true;

    	chip8.memory.ram[chip8.registers.pc as usize] = 0x00;
    	chip8.memory.ram[(chip8.registers.pc + 1) as usize] = 0xE0;
    	chip8.execute_next_opcode();

    	assert_eq!(false, chip8.display.screen[0][0]);
    	assert_eq!(false, chip8.display.screen[0][1]);
    	assert_eq!(false, chip8.display.screen[0][2]);
    }

    #[test]
    fn test_jump() {
   		let mut chip8 = Chip8::new_and_init();
   		chip8.memory.ram[chip8.registers.pc as usize] = 0x1E;
   		chip8.memory.ram[(chip8.registers.pc + 1) as usize] = 0xEE;
   		chip8.execute_next_opcode();

   		assert_eq!(0xEEE, chip8.registers.pc);
    }

    #[test]
    fn test_push_and_pop_stack() {
    	let mut chip8 = Chip8::new_and_init();
    	// Call subroutine at 2000
    	chip8.memory.ram[chip8.registers.pc as usize] = 0x27;
   		chip8.memory.ram[(chip8.registers.pc + 1) as usize] = 0xD0;

   		// Return back to caller
   		chip8.memory.ram[2000] = 0x00;
   		chip8.memory.ram[2001] = 0xEE;

   		// We won't execute this, will just use it to see that it's our next expected instruction.
   		chip8.memory.ram[(chip8.registers.pc + 2) as usize] = 0xAA;
   		chip8.memory.ram[(chip8.registers.pc + 3) as usize] = 0xAA;

   		// Execute first instruction -- should jump us to address 2000.
   		chip8.execute_next_opcode();
   		assert_eq!(2000, chip8.registers.pc);

   		// Next instruction should bring us back to the caller address + 2.
   		chip8.execute_next_opcode();
   		assert_eq!(0x200 + 2, chip8.registers.pc);

   		// Next two instructions should match 0xAAAA
   		let next_opcode = chip8.memory.read_unsigned_short(chip8.registers.pc);
   		assert_eq!(0xAAAA, next_opcode);
    }
}<|endoftext|>


<commit_before>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::BufferedStream;
use std::string::String;

pub const CR: u8 = b'\r';
pub const LF: u8 = b'\n';
pub const SP: u8 = b' ';
pub const CRLF: [u8, ..2] = [CR,LF];

fn parse_request_line(header: &str) {
    let mut pathname = String::new();
    let mut method = String::new();
    let mut starting = true;
    let mut found_method = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];

        if starting && cbyte != SP {
            method.push_str(ch);
        }
        if starting && cbyte == SP {
            starting = false;
            found_method = true;
            continue;
        }
        if found_method && cbyte != SP {
            pathname.push_str(ch);
        }
        if found_method && cbyte == SP {
            break;
        }

    }

    println!("METHOD: {}", method);
    println!("PATHNAME: {}", pathname);
}

fn main () {

    let listener = TcpListener::bind("127.0.0.1:8099").unwrap();
    let mut acceptor = listener.listen().unwrap();

    fn handle_client(mut stream: BufferedStream<TcpStream>) {

        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        let mut ii = 0u;

        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }
            if ii == 0u { // the Request-Line is always the first line
                parse_request_line(cur_line.as_slice());
                ii += 1;
            }

            body = body + cur_line + "
";
            if cur_line.as_bytes() == CRLF { // TODO: make this check for \r\n explicitly
                break;
            }
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\r\n").unwrap(); // byte literal
        stream.write(b"Content-type: text/html\r\n").unwrap();
        stream.write(b"X-header: from bytes\r\n").unwrap();
        stream.write(body_length.into_bytes().as_slice()).unwrap();
        stream.write(b"\r\n\r\n").unwrap();
        stream.write(body.into_bytes().as_slice()).unwrap();
        stream.flush().unwrap();

        println!("Handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<commit_msg>remove todo that is done<commit_after>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::BufferedStream;
use std::string::String;

pub const CR: u8 = b'\r';
pub const LF: u8 = b'\n';
pub const SP: u8 = b' ';
pub const CRLF: [u8, ..2] = [CR,LF];

fn parse_request_line(header: &str) {
    let mut pathname = String::new();
    let mut method = String::new();
    let mut starting = true;
    let mut found_method = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];

        if starting && cbyte != SP {
            method.push_str(ch);
        }
        if starting && cbyte == SP {
            starting = false;
            found_method = true;
            continue;
        }
        if found_method && cbyte != SP {
            pathname.push_str(ch);
        }
        if found_method && cbyte == SP {
            break;
        }

    }

    println!("METHOD: {}", method);
    println!("PATHNAME: {}", pathname);
}

fn main () {

    let listener = TcpListener::bind("127.0.0.1:8099").unwrap();
    let mut acceptor = listener.listen().unwrap();

    fn handle_client(mut stream: BufferedStream<TcpStream>) {

        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        let mut ii = 0u;

        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }
            if ii == 0u { // the Request-Line is always the first line
                parse_request_line(cur_line.as_slice());
                ii += 1;
            }

            body = body + cur_line + "
";
            if cur_line.as_bytes() == CRLF {
                break;
            }
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\r\n").unwrap(); // byte literal
        stream.write(b"Content-type: text/html\r\n").unwrap();
        stream.write(b"X-header: from bytes\r\n").unwrap();
        stream.write(body_length.into_bytes().as_slice()).unwrap();
        stream.write(b"\r\n\r\n").unwrap();
        stream.write(body.into_bytes().as_slice()).unwrap();
        stream.flush().unwrap();

        println!("Handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<|endoftext|>