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

//!
//! Roughtime server
//!
//! # Configuration
//! The `roughenough` server is configured via a YAML config file. See the documentation
//! for [FileConfig](struct.FileConfig.html) for details.
//!
//! To run the server:
//!
//! ```bash
//! $ cargo run --release --bin server /path/to/config.file
//! ```
//!

extern crate byteorder;
extern crate ctrlc;
extern crate hex;
#[macro_use]
extern crate log;
extern crate mio;
extern crate mio_extras;
extern crate ring;
extern crate roughenough;
extern crate simple_logger;
extern crate time;
extern crate untrusted;
extern crate yaml_rust;

use std::env;
use std::io::ErrorKind;
use std::process;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::Duration;
use std::net::SocketAddr;

use mio::net::UdpSocket;
use mio::{Events, Poll, PollOpt, Ready, Token};
use mio_extras::timer::Timer;

use byteorder::{LittleEndian, WriteBytesExt};

use roughenough::config;
use roughenough::config::ServerConfig;
use roughenough::kms;
use roughenough::key::{LongTermKey, OnlineKey};
use roughenough::merkle::MerkleTree;
use roughenough::{Error, RtMessage, Tag};
use roughenough::{MIN_REQUEST_LENGTH, VERSION};

macro_rules! check_ctrlc {
    ($keep_running:expr) => {
        if !$keep_running.load(Ordering::Acquire) {
            warn!("Ctrl-C caught, exiting...");
            return true;
        }
    }
}

const MESSAGE: Token = Token(0);
const STATUS: Token = Token(1);

fn make_response(srep: &RtMessage, cert_bytes: &[u8], path: &[u8], idx: u32) -> RtMessage {
    let mut index = [0; 4];
    (&mut index as &mut [u8])
        .write_u32::<LittleEndian>(idx)
        .unwrap();

    let sig_bytes = srep.get_field(Tag::SIG).unwrap();
    let srep_bytes = srep.get_field(Tag::SREP).unwrap();

    let mut response = RtMessage::new(5);
    response.add_field(Tag::SIG, sig_bytes).unwrap();
    response.add_field(Tag::PATH, path).unwrap();
    response.add_field(Tag::SREP, srep_bytes).unwrap();
    response.add_field(Tag::CERT, cert_bytes).unwrap();
    response.add_field(Tag::INDX, &index).unwrap();

    response
}

// extract the client's nonce from its request
fn nonce_from_request(buf: &[u8], num_bytes: usize) -> Result<&[u8], Error> {
    if num_bytes < MIN_REQUEST_LENGTH as usize {
        return Err(Error::RequestTooShort);
    }

    let tag_count = &buf[..4];
    let expected_nonc = &buf[8..12];
    let expected_pad = &buf[12..16];

    let tag_count_is_2 = tag_count == [0x02, 0x00, 0x00, 0x00];
    let tag1_is_nonc = expected_nonc == Tag::NONC.wire_value();
    let tag2_is_pad = expected_pad == Tag::PAD.wire_value();

    if tag_count_is_2 && tag1_is_nonc && tag2_is_pad {
        Ok(&buf[0x10..0x50])
    } else {
        Err(Error::InvalidRequest)
    }
}

struct Server {
    config: Box<ServerConfig>,
    online_key: OnlineKey,
    cert_bytes: Vec<u8>,

    response_counter: AtomicUsize,
    num_bad_requests: u64,

    socket: UdpSocket,
    keep_running: Arc<AtomicBool>,
    poll_duration: Option<Duration>,
    timer: Timer<()>,
    poll: Poll,
    events: Events,
    merkle: MerkleTree,
    requests: Vec<(Vec<u8>, SocketAddr)>,
    buf: [u8; 65_536],

}

impl Server {
    pub fn new(config: Box<ServerConfig>, online_key: OnlineKey, cert_bytes: Vec<u8>) -> Server {
        let response_counter = AtomicUsize::new(0);
        let keep_running = Arc::new(AtomicBool::new(true));

        let sock_addr = config.socket_addr().expect("");
        let socket = UdpSocket::bind(&sock_addr).expect("failed to bind to socket");
        let poll_duration = Some(Duration::from_millis(100));

        let mut timer: Timer<()> = Timer::default();
        timer.set_timeout(config.status_interval(), ());

        let poll = Poll::new().unwrap();
        poll.register(&socket, MESSAGE, Ready::readable(), PollOpt::edge())
            .unwrap();
        poll.register(&timer, STATUS, Ready::readable(), PollOpt::edge())
            .unwrap();

        let mut merkle = MerkleTree::new();
        let mut requests = Vec::with_capacity(config.batch_size() as usize);

        Server {
            config,
            online_key,
            cert_bytes,

            response_counter,
            num_bad_requests: 0,
            socket,
            keep_running,
            poll_duration,
            timer,
            poll,
            events: Events::with_capacity(32),
            merkle,
            requests,
            buf: [0u8; 65_536]
        }

    }

    fn get_keep_running(&self) -> Arc<AtomicBool> {
        return self.keep_running.clone()
    }

    fn process_events(&mut self) -> bool {
        self.poll.poll(&mut self.events, self.poll_duration).expect("poll failed");

        for event in self.events.iter() {
            match event.token() {
                MESSAGE => {
                    let mut done = false;

                    'process_batch: loop {
                        check_ctrlc!(self.keep_running);

                        self.merkle.reset();
                        self.requests.clear();

                        let resp_start = self.response_counter.load(Ordering::SeqCst);

                        for i in 0..self.config.batch_size() {
                            match self.socket.recv_from(&mut self.buf) {
                                Ok((num_bytes, src_addr)) => {
                                    if let Ok(nonce) = nonce_from_request(&self.buf, num_bytes) {
                                        self.requests.push((Vec::from(nonce), src_addr));
                                        self.merkle.push_leaf(nonce);
                                    } else {
                                        self.num_bad_requests += 1;
                                        info!(
                                            "Invalid request ({} bytes) from {} (#{} in batch, resp #{})",
                                            num_bytes, src_addr, i, resp_start + i as usize
                                        );
                                    }
                                }
                                Err(e) => match e.kind() {
                                    ErrorKind::WouldBlock => {
                                        done = true;
                                        break;
                                    }
                                    _ => {
                                        error!(
                                            "Error receiving from socket: {:?}: {:?}",
                                            e.kind(),
                                            e
                                        );
                                        break;
                                    }
                                },
                            };
                        }

                        if self.requests.is_empty() {
                            break 'process_batch;
                        }

                        let merkle_root = self.merkle.compute_root();
                        let srep = self.online_key.make_srep(time::get_time(), &merkle_root);

                        for (i, &(ref nonce, ref src_addr)) in self.requests.iter().enumerate() {
                            let paths = self.merkle.get_paths(i);

                            let resp = make_response(&srep, &self.cert_bytes, &paths, i as u32);
                            let resp_bytes = resp.encode().unwrap();

                            let bytes_sent = self.socket
                                .send_to(&resp_bytes, &src_addr)
                                .expect("send_to failed");
                            let num_responses = self.response_counter.fetch_add(1, Ordering::SeqCst);

                            info!(
                                "Responded {} bytes to {} for '{}..' (#{} in batch, resp #{})",
                                bytes_sent,
                                src_addr,
                                hex::encode(&nonce[0..4]),
                                i,
                                num_responses
                            );
                        }
                        if done {
                            break 'process_batch;
                        }
                    }
                }

                STATUS => {
                    info!(
                        "responses {}, invalid requests {}",
                        self.response_counter.load(Ordering::SeqCst),
                        self.num_bad_requests
                    );

                    self.timer.set_timeout(self.config.status_interval(), ());
                }

                _ => unreachable!(),
            }
        }
        false
    }
}

fn polling_loop(config: Box<ServerConfig>, online_key: OnlineKey, cert_bytes: Vec<u8>) -> bool {
/*    let response_counter = AtomicUsize::new(0);
    let keep_running = Arc::new(AtomicBool::new(true));
    let kr = keep_running.clone();

    ctrlc::set_handler(move || kr.store(false, Ordering::Release))
        .expect("failed setting Ctrl-C handler");

    let sock_addr = config.socket_addr().expect("");
    let socket = UdpSocket::bind(&sock_addr).expect("failed to bind to socket");
    let poll_duration = Some(Duration::from_millis(100));

    let mut timer: Timer<()> = Timer::default();
    timer.set_timeout(config.status_interval(), ());

    let mut buf = [0u8; 65_536];
    let mut events = Events::with_capacity(32);
    let mut num_bad_requests = 0u64;

    let poll = Poll::new().unwrap();
    poll.register(&socket, MESSAGE, Ready::readable(), PollOpt::edge())
        .unwrap();
    poll.register(&timer, STATUS, Ready::readable(), PollOpt::edge())
        .unwrap();

    let mut merkle = MerkleTree::new();
    let mut requests = Vec::with_capacity(config.batch_size() as usize);*/

    let mut server = Server::new(config, online_key, cert_bytes);
    let kr = server.get_keep_running();
    let kr_new = kr.clone();

    ctrlc::set_handler(move || kr.store(false, Ordering::Release))
        .expect("failed setting Ctrl-C handler");

    loop {
        check_ctrlc!(kr_new);
        if server.process_events() {
            return true;
        }

    }
}

fn kms_support_str() -> &'static str {
    if cfg!(feature = "awskms") {
        " (+AWS KMS)"
    } else if cfg!(feature = "gcpkms") {
        " (+GCP KMS)"
    } else {
        ""
    }
}

pub fn main() {
    use log::Level;

    simple_logger::init_with_level(Level::Info).unwrap();

    info!("Roughenough server v{}{} starting", VERSION, kms_support_str());

    let mut args = env::args();
    if args.len() != 2 {
        error!("Usage: server <ENV|/path/to/config.yaml>");
        process::exit(1);
    }

    let arg1 = args.nth(1).unwrap();
    let config = match config::make_config(&arg1) {
        Err(e) => {
            error!("{:?}", e);
            process::exit(1)
        }
        Ok(ref cfg) if !config::is_valid_config(&cfg) => process::exit(1),
        Ok(cfg) => cfg,
    };

    let mut online_key = OnlineKey::new();
    let public_key: String;

    let cert_bytes = {
        let seed = match kms::load_seed(&config) {
            Ok(seed) => seed,
            Err(e) => {
                error!("Failed to load seed: {:#?}", e);
                process::exit(1);
            }
        };
        let mut long_term_key = LongTermKey::new(&seed);
        public_key = hex::encode(long_term_key.public_key());

        long_term_key.make_cert(&online_key).encode().unwrap()
    };

    info!("Long-term public key    : {}", public_key);
    info!("Online public key       : {}", online_key);
    info!("Max response batch size : {}", config.batch_size());
    info!("Status updates every    : {} seconds", config.status_interval().as_secs());
    info!("Server listening on     : {}:{}", config.interface(), config.port());

    polling_loop(config, online_key, cert_bytes);

    info!("Done.");
    process::exit(0);
}
<commit_msg>Add send_to_self<commit_after>// Copyright 2017-2018 int08h LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//!
//! Roughtime server
//!
//! # Configuration
//! The `roughenough` server is configured via a YAML config file. See the documentation
//! for [FileConfig](struct.FileConfig.html) for details.
//!
//! To run the server:
//!
//! ```bash
//! $ cargo run --release --bin server /path/to/config.file
//! ```
//!

extern crate byteorder;
extern crate ctrlc;
extern crate hex;
#[macro_use]
extern crate log;
extern crate mio;
extern crate mio_extras;
extern crate ring;
extern crate roughenough;
extern crate simple_logger;
extern crate time;
extern crate untrusted;
extern crate yaml_rust;

use std::env;
use std::io::ErrorKind;
use std::process;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::Duration;
use std::net::SocketAddr;

use mio::net::UdpSocket;
use mio::{Events, Poll, PollOpt, Ready, Token};
use mio_extras::timer::Timer;

use byteorder::{LittleEndian, WriteBytesExt};

use roughenough::config;
use roughenough::config::ServerConfig;
use roughenough::kms;
use roughenough::key::{LongTermKey, OnlineKey};
use roughenough::merkle::MerkleTree;
use roughenough::{Error, RtMessage, Tag};
use roughenough::{MIN_REQUEST_LENGTH, VERSION};

macro_rules! check_ctrlc {
    ($keep_running:expr) => {
        if !$keep_running.load(Ordering::Acquire) {
            warn!("Ctrl-C caught, exiting...");
            return true;
        }
    }
}

const MESSAGE: Token = Token(0);
const STATUS: Token = Token(1);

fn make_response(srep: &RtMessage, cert_bytes: &[u8], path: &[u8], idx: u32) -> RtMessage {
    let mut index = [0; 4];
    (&mut index as &mut [u8])
        .write_u32::<LittleEndian>(idx)
        .unwrap();

    let sig_bytes = srep.get_field(Tag::SIG).unwrap();
    let srep_bytes = srep.get_field(Tag::SREP).unwrap();

    let mut response = RtMessage::new(5);
    response.add_field(Tag::SIG, sig_bytes).unwrap();
    response.add_field(Tag::PATH, path).unwrap();
    response.add_field(Tag::SREP, srep_bytes).unwrap();
    response.add_field(Tag::CERT, cert_bytes).unwrap();
    response.add_field(Tag::INDX, &index).unwrap();

    response
}

// extract the client's nonce from its request
fn nonce_from_request(buf: &[u8], num_bytes: usize) -> Result<&[u8], Error> {
    if num_bytes < MIN_REQUEST_LENGTH as usize {
        return Err(Error::RequestTooShort);
    }

    let tag_count = &buf[..4];
    let expected_nonc = &buf[8..12];
    let expected_pad = &buf[12..16];

    let tag_count_is_2 = tag_count == [0x02, 0x00, 0x00, 0x00];
    let tag1_is_nonc = expected_nonc == Tag::NONC.wire_value();
    let tag2_is_pad = expected_pad == Tag::PAD.wire_value();

    if tag_count_is_2 && tag1_is_nonc && tag2_is_pad {
        Ok(&buf[0x10..0x50])
    } else {
        Err(Error::InvalidRequest)
    }
}

struct Server {
    config: Box<ServerConfig>,
    online_key: OnlineKey,
    cert_bytes: Vec<u8>,

    response_counter: AtomicUsize,
    num_bad_requests: u64,

    socket: UdpSocket,
    keep_running: Arc<AtomicBool>,
    poll_duration: Option<Duration>,
    timer: Timer<()>,
    poll: Poll,
    events: Events,
    merkle: MerkleTree,
    requests: Vec<(Vec<u8>, SocketAddr)>,
    buf: [u8; 65_536],

}

impl Server {
    pub fn new(config: Box<ServerConfig>, online_key: OnlineKey, cert_bytes: Vec<u8>) -> Server {
        let response_counter = AtomicUsize::new(0);
        let keep_running = Arc::new(AtomicBool::new(true));

        let sock_addr = config.socket_addr().expect("");
        let socket = UdpSocket::bind(&sock_addr).expect("failed to bind to socket");
        let poll_duration = Some(Duration::from_millis(100));

        let mut timer: Timer<()> = Timer::default();
        timer.set_timeout(config.status_interval(), ());

        let poll = Poll::new().unwrap();
        poll.register(&socket, MESSAGE, Ready::readable(), PollOpt::edge())
            .unwrap();
        poll.register(&timer, STATUS, Ready::readable(), PollOpt::edge())
            .unwrap();

        let mut merkle = MerkleTree::new();
        let mut requests = Vec::with_capacity(config.batch_size() as usize);

        Server {
            config,
            online_key,
            cert_bytes,

            response_counter,
            num_bad_requests: 0,
            socket,
            keep_running,
            poll_duration,
            timer,
            poll,
            events: Events::with_capacity(32),
            merkle,
            requests,
            buf: [0u8; 65_536]
        }

    }

    fn get_keep_running(&self) -> Arc<AtomicBool> {
        return self.keep_running.clone()
    }

    fn process_events(&mut self) -> bool {
        self.poll.poll(&mut self.events, self.poll_duration).expect("poll failed");

        for event in self.events.iter() {
            match event.token() {
                MESSAGE => {
                    let mut done = false;

                    'process_batch: loop {
                        check_ctrlc!(self.keep_running);

                        self.merkle.reset();
                        self.requests.clear();

                        let resp_start = self.response_counter.load(Ordering::SeqCst);

                        for i in 0..self.config.batch_size() {
                            match self.socket.recv_from(&mut self.buf) {
                                Ok((num_bytes, src_addr)) => {
                                    if let Ok(nonce) = nonce_from_request(&self.buf, num_bytes) {
                                        self.requests.push((Vec::from(nonce), src_addr));
                                        self.merkle.push_leaf(nonce);
                                    } else {
                                        self.num_bad_requests += 1;
                                        info!(
                                            "Invalid request ({} bytes) from {} (#{} in batch, resp #{})",
                                            num_bytes, src_addr, i, resp_start + i as usize
                                        );
                                    }
                                }
                                Err(e) => match e.kind() {
                                    ErrorKind::WouldBlock => {
                                        done = true;
                                        break;
                                    }
                                    _ => {
                                        error!(
                                            "Error receiving from socket: {:?}: {:?}",
                                            e.kind(),
                                            e
                                        );
                                        break;
                                    }
                                },
                            };
                        }

                        if self.requests.is_empty() {
                            break 'process_batch;
                        }

                        let merkle_root = self.merkle.compute_root();
                        let srep = self.online_key.make_srep(time::get_time(), &merkle_root);

                        for (i, &(ref nonce, ref src_addr)) in self.requests.iter().enumerate() {
                            let paths = self.merkle.get_paths(i);

                            let resp = make_response(&srep, &self.cert_bytes, &paths, i as u32);
                            let resp_bytes = resp.encode().unwrap();

                            let bytes_sent = self.socket
                                .send_to(&resp_bytes, &src_addr)
                                .expect("send_to failed");
                            let num_responses = self.response_counter.fetch_add(1, Ordering::SeqCst);

                            info!(
                                "Responded {} bytes to {} for '{}..' (#{} in batch, resp #{})",
                                bytes_sent,
                                src_addr,
                                hex::encode(&nonce[0..4]),
                                i,
                                num_responses
                            );
                        }
                        if done {
                            break 'process_batch;
                        }
                    }
                }

                STATUS => {
                    info!(
                        "responses {}, invalid requests {}",
                        self.response_counter.load(Ordering::SeqCst),
                        self.num_bad_requests
                    );

                    self.timer.set_timeout(self.config.status_interval(), ());
                }

                _ => unreachable!(),
            }
        }
        false
    }

    fn send_to_self(&mut self, data: &[u8]) {
        self.socket.send_to(data, &self.socket.local_addr().unwrap());
    }
}

fn polling_loop(config: Box<ServerConfig>, online_key: OnlineKey, cert_bytes: Vec<u8>) -> bool {
/*    let response_counter = AtomicUsize::new(0);
    let keep_running = Arc::new(AtomicBool::new(true));
    let kr = keep_running.clone();

    ctrlc::set_handler(move || kr.store(false, Ordering::Release))
        .expect("failed setting Ctrl-C handler");

    let sock_addr = config.socket_addr().expect("");
    let socket = UdpSocket::bind(&sock_addr).expect("failed to bind to socket");
    let poll_duration = Some(Duration::from_millis(100));

    let mut timer: Timer<()> = Timer::default();
    timer.set_timeout(config.status_interval(), ());

    let mut buf = [0u8; 65_536];
    let mut events = Events::with_capacity(32);
    let mut num_bad_requests = 0u64;

    let poll = Poll::new().unwrap();
    poll.register(&socket, MESSAGE, Ready::readable(), PollOpt::edge())
        .unwrap();
    poll.register(&timer, STATUS, Ready::readable(), PollOpt::edge())
        .unwrap();

    let mut merkle = MerkleTree::new();
    let mut requests = Vec::with_capacity(config.batch_size() as usize);*/

    let mut server = Server::new(config, online_key, cert_bytes);
    let kr = server.get_keep_running();
    let kr_new = kr.clone();

    ctrlc::set_handler(move || kr.store(false, Ordering::Release))
        .expect("failed setting Ctrl-C handler");

    loop {
        check_ctrlc!(kr_new);
        if server.process_events() {
            return true;
        }

    }
}

fn kms_support_str() -> &'static str {
    if cfg!(feature = "awskms") {
        " (+AWS KMS)"
    } else if cfg!(feature = "gcpkms") {
        " (+GCP KMS)"
    } else {
        ""
    }
}

pub fn main() {
    use log::Level;

    simple_logger::init_with_level(Level::Info).unwrap();

    info!("Roughenough server v{}{} starting", VERSION, kms_support_str());

    let mut args = env::args();
    if args.len() != 2 {
        error!("Usage: server <ENV|/path/to/config.yaml>");
        process::exit(1);
    }

    let arg1 = args.nth(1).unwrap();
    let config = match config::make_config(&arg1) {
        Err(e) => {
            error!("{:?}", e);
            process::exit(1)
        }
        Ok(ref cfg) if !config::is_valid_config(&cfg) => process::exit(1),
        Ok(cfg) => cfg,
    };

    let mut online_key = OnlineKey::new();
    let public_key: String;

    let cert_bytes = {
        let seed = match kms::load_seed(&config) {
            Ok(seed) => seed,
            Err(e) => {
                error!("Failed to load seed: {:#?}", e);
                process::exit(1);
            }
        };
        let mut long_term_key = LongTermKey::new(&seed);
        public_key = hex::encode(long_term_key.public_key());

        long_term_key.make_cert(&online_key).encode().unwrap()
    };

    info!("Long-term public key    : {}", public_key);
    info!("Online public key       : {}", online_key);
    info!("Max response batch size : {}", config.batch_size());
    info!("Status updates every    : {} seconds", config.status_interval().as_secs());
    info!("Server listening on     : {}:{}", config.interface(), config.port());

    polling_loop(config, online_key, cert_bytes);

    info!("Done.");
    process::exit(0);
}
<|endoftext|>


<commit_before>use dbus::{MessageItem};
use bluetooth_utils;

use std::error::Error;

static GATT_SERVICE_INTERFACE: &'static str = "org.bluez.GattService1";

#[derive(Clone, Debug)]
pub struct BluetoothGATTService {
    object_path: String,
}

impl BluetoothGATTService {
    pub fn new(object_path: String)
           -> BluetoothGATTService {
        BluetoothGATTService {
            object_path: object_path
        }
    }

    pub fn get_object_path(&self) -> String {
        self.object_path.clone()
    }

    fn get_property(&self, prop: &str) -> Result<MessageItem, Box<Error>> {
        bluetooth_utils::get_property(GATT_SERVICE_INTERFACE, &self.object_path, prop)
    }

/*
 * Properties
 */

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt#n33
    pub fn get_uuid(&self) -> Result<String, Box<Error>> {
        let uuid = try!(self.get_property("UUID"));
        Ok(String::from(uuid.inner::<&str>().unwrap()))
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt#n37
    pub fn is_primary(&self) -> Result<bool, Box<Error>> {
        let primary = try!(self.get_property("Primary"));
        Ok(primary.inner::<bool>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt#n42
    pub fn get_device(&self) -> Result<String, Box<Error>> {
        let device = try!(self.get_property("Device"));
        Ok(String::from(device.inner::<&str>().unwrap()))
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt#n48
    pub fn get_gatt_characteristics(&self) -> Result<Vec<String>,Box<Error>> {
        bluetooth_utils::list_characteristics(&self.object_path)
    }
}
<commit_msg>Add Included Services placeholder<commit_after>use dbus::{MessageItem};
use bluetooth_utils;

use std::error::Error;

static GATT_SERVICE_INTERFACE: &'static str = "org.bluez.GattService1";

#[derive(Clone, Debug)]
pub struct BluetoothGATTService {
    object_path: String,
}

impl BluetoothGATTService {
    pub fn new(object_path: String)
           -> BluetoothGATTService {
        BluetoothGATTService {
            object_path: object_path
        }
    }

    pub fn get_object_path(&self) -> String {
        self.object_path.clone()
    }

    fn get_property(&self, prop: &str) -> Result<MessageItem, Box<Error>> {
        bluetooth_utils::get_property(GATT_SERVICE_INTERFACE, &self.object_path, prop)
    }

/*
 * Properties
 */

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt#n33
    pub fn get_uuid(&self) -> Result<String, Box<Error>> {
        let uuid = try!(self.get_property("UUID"));
        Ok(String::from(uuid.inner::<&str>().unwrap()))
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt#n37
    pub fn is_primary(&self) -> Result<bool, Box<Error>> {
        let primary = try!(self.get_property("Primary"));
        Ok(primary.inner::<bool>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt#n42
    pub fn get_device(&self) -> Result<String, Box<Error>> {
        let device = try!(self.get_property("Device"));
        Ok(String::from(device.inner::<&str>().unwrap()))
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/gatt-api.txt#n48
    pub fn get_includes(&self) -> Result<Vec<String>, Box<Error>> {
        Err(Box::from("Not implemented"))
    }

    pub fn get_gatt_characteristics(&self) -> Result<Vec<String>,Box<Error>> {
        bluetooth_utils::list_characteristics(&self.object_path)
    }
}
<|endoftext|>


<commit_before>/// Figure 1.7 Read commands from standard input and execute them
///
/// Takeaways:
///
/// - this was astonishingly very straightforward to port to rust
///   without any stumbling blocks
/// - IMO the if let around fork() makes the code more readable
///   than the C counterpart. also the parent/child distinction
///   in the original C program should have been an if/else block
///
/// $ echo man | f07-read-execute 2>&1
/// What manual page do you want?
/// % %

extern crate libc;
#[macro_use(cstr, as_char)]
extern crate apue;

use libc::{STDIN_FILENO, c_char, printf, strlen, fgets, fdopen, fork, waitpid};
use apue::{array_to_string, LibcResult};
use apue::my_libc::execlp;

const MAXLINE: usize = 100;

fn main() {
    unsafe {
        let mut buf: [c_char; MAXLINE] = std::mem::uninitialized();
        let stdin = fdopen(STDIN_FILENO, &('r' as c_char));
        let mut status = 0;
        printf(cstr!("%% ")); // print prompt (printf requires %% to print %)
        while !fgets(as_char!(buf), MAXLINE as _, stdin).is_null() {
            let len = strlen(as_char!(buf));
            if buf[len - 1] == '\n' as _ {
                buf[len - 1] = 0;
            }
            if let Some(pid) = fork().to_option() {
                if pid == 0 {
                    // child
                    execlp(as_char!(buf), as_char!(buf), 0);
                    panic!("could not execute {}", array_to_string(&buf));
                } else {
                    // parent
                    if let Some(_) = waitpid(pid, &mut status, 0).to_option() {
                        printf(cstr!("%% "));
                    } else {
                        panic!("waitpid error");
                    }
                }
            } else {
                panic!("fork error");
            }
        }
    }
}
<commit_msg>fix f07 for linux<commit_after>/// Figure 1.7 Read commands from standard input and execute them
///
/// Takeaways:
///
/// - this was astonishingly very straightforward to port to rust
///   without any stumbling blocks
/// - IMO the if let around fork() makes the code more readable
///   than the C counterpart. also the parent/child distinction
///   in the original C program should have been an if/else block
///
/// $ echo tty | f07-read-execute 2>&1
/// not a tty
/// % %

extern crate libc;
#[macro_use(cstr, as_char)]
extern crate apue;

use libc::{STDIN_FILENO, c_char, printf, strlen, fgets, fdopen, fork, waitpid};
use apue::{array_to_string, LibcResult};
use apue::my_libc::execlp;

const MAXLINE: usize = 100;

fn main() {
    unsafe {
        let mut buf: [c_char; MAXLINE] = std::mem::uninitialized();
        let stdin = fdopen(STDIN_FILENO, &('r' as c_char));
        let mut status = 0;
        printf(cstr!("%% ")); // print prompt (printf requires %% to print %)
        while !fgets(as_char!(buf), MAXLINE as _, stdin).is_null() {
            let len = strlen(as_char!(buf));
            if buf[len - 1] == '\n' as _ {
                buf[len - 1] = 0;
            }
            if let Some(pid) = fork().to_option() {
                if pid == 0 {
                    // child
                    execlp(as_char!(buf), as_char!(buf), 0);
                    panic!("could not execute {}", array_to_string(&buf));
                } else {
                    // parent
                    if let Some(_) = waitpid(pid, &mut status, 0).to_option() {
                        printf(cstr!("%% "));
                    } else {
                        panic!("waitpid error");
                    }
                }
            } else {
                panic!("fork error");
            }
        }
    }
}
<|endoftext|>


<commit_before>
use std::collections::BTreeMap;

use assembler::parser::{Literal, Node, InstructionField};

// MARK: - Constants

const BYTES_PER_INSTRUCTION: usize = 2;
const DIRECTIVE_ORG: &'static str = "org";
const DIRECTIVE_DB : &'static str = "db";

// MARK: - Semantic Analysis

/**
 @return () in the event the arguments are valid for the directive, or a failure reason.
 */
fn validate_directive_semantics<'a>(identifier: &'a str, arguments: &Vec<Literal<'a>>) -> Result<(), String> {
    /*
     The 'org' directive is used to set the current output origin address. The directive requires
     a single numeric literal in the range $000-$FFF.
     */
    if identifier == DIRECTIVE_ORG {
        if arguments.len() != 1 {
            return Err(format!("Incorrect number of parameters ({}) for directive .org, expecting 1", arguments.len()));
        }

        match arguments[0] {
            Literal::Numeric(a) if a <= 4095 => {}
            _ => {
                return Err(format!("Directive .org requires 1 numeric literal in the range $000-$FFF."));
            }
        }

        return Ok(());
    }

    /*
     The 'db' directive is used to emit a series of bytes at the current location.
     A list of 1 or more literals is required, either numeric or string.
     A string literal is emitted without a null-terminator.
     */
    if identifier == DIRECTIVE_DB {
        if arguments.len() == 0 {
            return Err(format!("Incorrect number of parameters ({}) for directive .db, expecting 1 or more.", arguments.len()));
        }

        for argument in arguments {
            if let &Literal::Numeric(value) = argument {
                if value > 0xFF {
                    return Err(format!("All numeric parameters to .db must be 1-byte literals (${:X} > $FF)", value));
                }
            }
        }

        return Ok(());
    }

    Err(format!("Unrecognized directive .{}", identifier))
}

/**
 @return The number of bytes the directive represents within the output stream.
 */
fn size_of_directive<'a>(identifier: &'a str, arguments: &Vec<Literal<'a>>) -> usize {
    // The origin directive is not emitted.
    if identifier == DIRECTIVE_ORG {
        return 0;
    }

    // The number of bytes emitted by .db is the sum of argument lengths.
    if identifier == DIRECTIVE_DB {
        return arguments.iter().fold(0, |acc, argument| {
            match *argument {
                Literal::Numeric(number) if number <= 0xFF => { acc + 1 }
                Literal::String(string) => { acc + string.len() }
                _ => {
                    panic!("Semantic analysis for directive .{} failed.", identifier);
                }
            }
        });
    }

    // The first pass at semantic analysis should have caught an invalid directive.
    panic!("Semantic analysis for directive .{} failed.", identifier);
}

// MARK: - Pass 1: Define Labels

/**
 In a 2-pass assembler, the first pass is used to resolve the address of all labels
 declared in the assembly. This involves walking the ASL, computing the size of instructions
 and directives in the output stream and using that information to establish the label-address map.
 @param syntax_list The un-filtered syntax list.
 @return A tuple of (the filtered syntax list with all labels removed,
     the map of labels to their corresponding addresses) on success or a string describing
     the reason the first pass failed.
 */
fn define_and_filter_labels<'a>(syntax_list: Vec<Node<'a>>) -> Result<(Vec<Node<'a>>, BTreeMap<&'a str, usize>), String> {
    let mut label_address_map = BTreeMap::new();
    let mut current_address = 0x000;

    // Define all labels and process '.org' directives.
    for node in syntax_list.iter() {
        match *node {
            Node::Directive { identifier, ref arguments } => {
                // Validate the directive and that the arguments match the identifier.
                try!(validate_directive_semantics(identifier, arguments));

                // Adjust address by directive size.
                current_address = current_address + size_of_directive(identifier, arguments);

                // The origin directive changes the current address.
                if let (DIRECTIVE_ORG, &Literal::Numeric(address)) = (identifier, &arguments[0]) {
                    current_address = address;
                }
            }

            Node::Label { identifier } => {
                // Map the label to the current address and remove from the ASL.
                if label_address_map.contains_key(&identifier) {
                    return Err(format!("Attempted re-definition of label {}.", identifier));
                }

                label_address_map.insert(identifier, current_address);
            }

            Node::Instruction { mnemonic: _, fields: _ } => {
                // All Chip8 instructions are the same length.
                current_address = current_address + BYTES_PER_INSTRUCTION;
            }
        }
    }

    // Remove any label nodes from the ASL as they have now been resolved.
    let filtered_asl = syntax_list.into_iter().filter(|node| {
        match *node {
            Node::Label { identifier: _ } => false,
            Node::Directive { identifier: _, arguments: _ } => true,
            Node::Instruction { mnemonic: _, fields: _ } => true
        }
    }).collect();

    // Semantic analysis for directives and labels is complete.
    Ok((filtered_asl, label_address_map))
}

/**
 Analyze the ASL for the assembly and convert it into an output byte stream.
 */
pub fn assemble<'a>(syntax_list: Vec<Node<'a>>) -> Result<(), String> {
    let _ = try!(define_and_filter_labels(syntax_list));
    Ok(())
}

// MARK: - Tests

#[cfg(test)]
mod tests {

  use super::*;
  use super::{validate_directive_semantics, size_of_directive};

  use assembler::scanner::Scanner;
  use assembler::parser::*;

  #[test]
  fn test_validate_directive_semantics_for_org() {
    let mut params = vec![];
    assert_eq!(validate_directive_semantics("org", &params), Err("Incorrect number of parameters (0) for directive .org, expecting 1".to_string()));
    params = vec![Literal::Numeric(1), Literal::Numeric(3)];
    assert_eq!(validate_directive_semantics("org", &params), Err("Incorrect number of parameters (2) for directive .org, expecting 1".to_string()));
    params = vec![Literal::Numeric(0x1000)];
    assert_eq!(validate_directive_semantics("org", &params), Err("Directive .org requires 1 numeric literal in the range $000-$FFF.".to_string()));
    params = vec![Literal::String("TEST_STRING")];
    assert_eq!(validate_directive_semantics("org", &params), Err("Directive .org requires 1 numeric literal in the range $000-$FFF.".to_string()));
    params = vec![Literal::Numeric(0xFFF)];
    assert_eq!(validate_directive_semantics("org", &params), Ok(()));
    params = vec![Literal::Numeric(0x000)];
    assert_eq!(validate_directive_semantics("org", &params), Ok(()));
  }

  #[test]
  fn test_validate_directive_semantics_for_db() {
    let mut params = vec![];
    assert_eq!(validate_directive_semantics("db", &params), Err("Incorrect number of parameters (0) for directive .db, expecting 1 or more.".to_string()));
    params = vec![Literal::Numeric(0x100)];
    assert_eq!(validate_directive_semantics("db", &params), Err("All numeric parameters to .db must be 1-byte literals ($100 > $FF)".to_string()));
    params = vec![Literal::String("TEST_STRING")];
    assert_eq!(validate_directive_semantics("db", &params), Ok(()));
    params = vec![Literal::Numeric(0xFF)];
    assert_eq!(validate_directive_semantics("db", &params), Ok(()));
    params = vec![Literal::Numeric(0x00)];
    assert_eq!(validate_directive_semantics("db", &params), Ok(()));
    params = vec![Literal::String("TEST_STRING"), Literal::Numeric(0x00)];
    assert_eq!(validate_directive_semantics("db", &params), Ok(()));
  }

  #[test]
  fn test_validate_directive_semantics_for_invalid_directive() {
    let mut params = vec![];
    assert_eq!(validate_directive_semantics("dw", &params), Err("Unrecognized directive .dw".to_string()));
    params = vec![Literal::Numeric(0x100)];
    assert_eq!(validate_directive_semantics("dw", &params), Err("Unrecognized directive .dw".to_string()));
  }

  #[test]
  fn test_size_of_directive_for_org() {
    assert_eq!(size_of_directive("org", &vec![]), 0);
    assert_eq!(size_of_directive("org", &vec![Literal::Numeric(0x100)]), 0);
    assert_eq!(size_of_directive("org", &vec![Literal::Numeric(0x100), Literal::String("TEST_STRING")]), 0);
  }

  #[test]
  fn test_size_of_directive_for_db() {
    assert_eq!(size_of_directive("db", &vec![]), 0);
    assert_eq!(size_of_directive("db", &vec![Literal::Numeric(0xFF)]), 1);
    assert_eq!(size_of_directive("db", &vec![Literal::String("TEST_STRING")]), 11);
    assert_eq!(size_of_directive("db", &vec![Literal::String("TEST_STRING"), Literal::Numeric(0x00)]), 12);
  }

}
<commit_msg>More tests for size_of_directive.<commit_after>
use std::collections::BTreeMap;

use assembler::parser::{Literal, Node, InstructionField};

// MARK: - Constants

const BYTES_PER_INSTRUCTION: usize = 2;
const DIRECTIVE_ORG: &'static str = "org";
const DIRECTIVE_DB : &'static str = "db";

// MARK: - Semantic Analysis

/**
 @return () in the event the arguments are valid for the directive, or a failure reason.
 */
fn validate_directive_semantics<'a>(identifier: &'a str, arguments: &Vec<Literal<'a>>) -> Result<(), String> {
    /*
     The 'org' directive is used to set the current output origin address. The directive requires
     a single numeric literal in the range $000-$FFF.
     */
    if identifier == DIRECTIVE_ORG {
        if arguments.len() != 1 {
            return Err(format!("Incorrect number of parameters ({}) for directive .org, expecting 1", arguments.len()));
        }

        match arguments[0] {
            Literal::Numeric(a) if a <= 4095 => {}
            _ => {
                return Err(format!("Directive .org requires 1 numeric literal in the range $000-$FFF."));
            }
        }

        return Ok(());
    }

    /*
     The 'db' directive is used to emit a series of bytes at the current location.
     A list of 1 or more literals is required, either numeric or string.
     A string literal is emitted without a null-terminator.
     */
    if identifier == DIRECTIVE_DB {
        if arguments.len() == 0 {
            return Err(format!("Incorrect number of parameters ({}) for directive .db, expecting 1 or more.", arguments.len()));
        }

        for argument in arguments {
            if let &Literal::Numeric(value) = argument {
                if value > 0xFF {
                    return Err(format!("All numeric parameters to .db must be 1-byte literals (${:X} > $FF)", value));
                }
            }
        }

        return Ok(());
    }

    Err(format!("Unrecognized directive .{}", identifier))
}

/**
 @return The number of bytes the directive represents within the output stream.
 */
fn size_of_directive<'a>(identifier: &'a str, arguments: &Vec<Literal<'a>>) -> usize {
    // The origin directive is not emitted.
    if identifier == DIRECTIVE_ORG {
        return 0;
    }

    // The number of bytes emitted by .db is the sum of argument lengths.
    if identifier == DIRECTIVE_DB {
        return arguments.iter().fold(0, |acc, argument| {
            match *argument {
                Literal::Numeric(number) if number <= 0xFF => { acc + 1 }
                Literal::String(string) => { acc + string.len() }
                _ => {
                    panic!("Semantic analysis for directive .{} failed.", identifier);
                }
            }
        });
    }

    // The first pass at semantic analysis should have caught an invalid directive.
    panic!("Semantic analysis for directive .{} failed.", identifier);
}

// MARK: - Pass 1: Define Labels

/**
 In a 2-pass assembler, the first pass is used to resolve the address of all labels
 declared in the assembly. This involves walking the ASL, computing the size of instructions
 and directives in the output stream and using that information to establish the label-address map.
 @param syntax_list The un-filtered syntax list.
 @return A tuple of (the filtered syntax list with all labels removed,
     the map of labels to their corresponding addresses) on success or a string describing
     the reason the first pass failed.
 */
fn define_and_filter_labels<'a>(syntax_list: Vec<Node<'a>>) -> Result<(Vec<Node<'a>>, BTreeMap<&'a str, usize>), String> {
    let mut label_address_map = BTreeMap::new();
    let mut current_address = 0x000;

    // Define all labels and process '.org' directives.
    for node in syntax_list.iter() {
        match *node {
            Node::Directive { identifier, ref arguments } => {
                // Validate the directive and that the arguments match the identifier.
                try!(validate_directive_semantics(identifier, arguments));

                // Adjust address by directive size.
                current_address = current_address + size_of_directive(identifier, arguments);

                // The origin directive changes the current address.
                if let (DIRECTIVE_ORG, &Literal::Numeric(address)) = (identifier, &arguments[0]) {
                    current_address = address;
                }
            }

            Node::Label { identifier } => {
                // Map the label to the current address and remove from the ASL.
                if label_address_map.contains_key(&identifier) {
                    return Err(format!("Attempted re-definition of label {}.", identifier));
                }

                label_address_map.insert(identifier, current_address);
            }

            Node::Instruction { mnemonic: _, fields: _ } => {
                // All Chip8 instructions are the same length.
                current_address = current_address + BYTES_PER_INSTRUCTION;
            }
        }
    }

    // Remove any label nodes from the ASL as they have now been resolved.
    let filtered_asl = syntax_list.into_iter().filter(|node| {
        match *node {
            Node::Label { identifier: _ } => false,
            Node::Directive { identifier: _, arguments: _ } => true,
            Node::Instruction { mnemonic: _, fields: _ } => true
        }
    }).collect();

    // Semantic analysis for directives and labels is complete.
    Ok((filtered_asl, label_address_map))
}

/**
 Analyze the ASL for the assembly and convert it into an output byte stream.
 */
pub fn assemble<'a>(syntax_list: Vec<Node<'a>>) -> Result<(), String> {
    let _ = try!(define_and_filter_labels(syntax_list));
    Ok(())
}

// MARK: - Tests

#[cfg(test)]
mod tests {

  use super::*;
  use super::{validate_directive_semantics, size_of_directive};

  use assembler::scanner::Scanner;
  use assembler::parser::*;

  #[test]
  fn test_validate_directive_semantics_for_org() {
    let mut params = vec![];
    assert_eq!(validate_directive_semantics("org", &params), Err("Incorrect number of parameters (0) for directive .org, expecting 1".to_string()));
    params = vec![Literal::Numeric(1), Literal::Numeric(3)];
    assert_eq!(validate_directive_semantics("org", &params), Err("Incorrect number of parameters (2) for directive .org, expecting 1".to_string()));
    params = vec![Literal::Numeric(0x1000)];
    assert_eq!(validate_directive_semantics("org", &params), Err("Directive .org requires 1 numeric literal in the range $000-$FFF.".to_string()));
    params = vec![Literal::String("TEST_STRING")];
    assert_eq!(validate_directive_semantics("org", &params), Err("Directive .org requires 1 numeric literal in the range $000-$FFF.".to_string()));
    params = vec![Literal::Numeric(0xFFF)];
    assert_eq!(validate_directive_semantics("org", &params), Ok(()));
    params = vec![Literal::Numeric(0x000)];
    assert_eq!(validate_directive_semantics("org", &params), Ok(()));
  }

  #[test]
  fn test_validate_directive_semantics_for_db() {
    let mut params = vec![];
    assert_eq!(validate_directive_semantics("db", &params), Err("Incorrect number of parameters (0) for directive .db, expecting 1 or more.".to_string()));
    params = vec![Literal::Numeric(0x100)];
    assert_eq!(validate_directive_semantics("db", &params), Err("All numeric parameters to .db must be 1-byte literals ($100 > $FF)".to_string()));
    params = vec![Literal::String("TEST_STRING")];
    assert_eq!(validate_directive_semantics("db", &params), Ok(()));
    params = vec![Literal::Numeric(0xFF)];
    assert_eq!(validate_directive_semantics("db", &params), Ok(()));
    params = vec![Literal::Numeric(0x00)];
    assert_eq!(validate_directive_semantics("db", &params), Ok(()));
    params = vec![Literal::String("TEST_STRING"), Literal::Numeric(0x00)];
    assert_eq!(validate_directive_semantics("db", &params), Ok(()));
  }

  #[test]
  fn test_validate_directive_semantics_for_invalid_directive() {
    let mut params = vec![];
    assert_eq!(validate_directive_semantics("dw", &params), Err("Unrecognized directive .dw".to_string()));
    params = vec![Literal::Numeric(0x100)];
    assert_eq!(validate_directive_semantics("dw", &params), Err("Unrecognized directive .dw".to_string()));
  }

  #[test]
  fn test_size_of_directive_for_org() {
    assert_eq!(size_of_directive("org", &vec![]), 0);
    assert_eq!(size_of_directive("org", &vec![Literal::Numeric(0x100)]), 0);
    assert_eq!(size_of_directive("org", &vec![Literal::Numeric(0x100), Literal::String("TEST_STRING")]), 0);
  }

  #[test]
  fn test_size_of_directive_for_db() {
    assert_eq!(size_of_directive("db", &vec![]), 0);
    assert_eq!(size_of_directive("db", &vec![Literal::Numeric(0xFF)]), 1);
    assert_eq!(size_of_directive("db", &vec![Literal::String("TEST_STRING")]), 11);
    assert_eq!(size_of_directive("db", &vec![Literal::String("TEST_STRING"), Literal::Numeric(0x00)]), 12);
  }

  #[test]
  #[should_panic]
  fn test_size_of_directive_panics_for_invalid_directive() {
    size_of_directive("dw", &vec![]);
  }

}
<|endoftext|>


<commit_before>/// MPI-based method for summing many arrays

// Argument parsing
#[macro_use] extern crate clap;
// logging
#[macro_use] extern crate log;
extern crate ndarray;
extern crate env_logger;
// lastly, this library
extern crate cabarrus;
use cabarrus::errors::*;
use std::cmp::min;
use ndarray as nd;
use ndarray::prelude::*;

pub fn main() {
    // Main can't return a Result, and the ? operator needs the enclosing function to return Result
    inner_main().expect("Could not recover. Exiting.");
}
pub fn inner_main() -> Result<()> {
    env_logger::init().unwrap();
    let args = app_from_crate!()
        .arg_from_usage("<size> 'how many workers there are' ")
        .arg_from_usage("<rank> 'which worker am I, starting from 0' ")
        .arg_from_usage("<addends>.. 'files contains matrices to add'")
        .arg_from_usage("<output> 'file in which to store the resulting matrix'")
        .get_matches();

    let mats = args.values_of("addends").unwrap();
    let size = value_t!(args, "size", usize).unwrap_or_else(|e| e.exit());
    let rank = value_t!(args, "rank", usize).unwrap_or_else(|e| e.exit());
    let chunksize = (mats.len() + size - 1) / size;

    let mut accum = None;
    for matname in mats.skip(rank*chunksize).take(chunksize) {
        let ref matfile = cabarrus::numpy::open_matrix_mmap(matname)?;
        let ref mat = cabarrus::numpy::read_matrix_mmap(matfile)?;
        accum = Some(match accum {
            Some(mut acc) => {acc += mat; acc}
            None => mat * 1.0
        });
    }
    if let Some(ref acc) = accum {
        cabarrus::numpy::write_matrix(args.value_of("output").unwrap(), acc)?;
    }
    Ok(())
}
<commit_msg>be clearer about array copy<commit_after>/// MPI-based method for summing many arrays

// Argument parsing
#[macro_use] extern crate clap;
extern crate ndarray;
extern crate env_logger;
// lastly, this library
extern crate cabarrus;
use cabarrus::errors::*;

pub fn main() {
    // Main can't return a Result, and the ? operator needs the enclosing function to return Result
    inner_main().expect("Could not recover. Exiting.");
}
pub fn inner_main() -> Result<()> {
    env_logger::init().unwrap();
    let args = app_from_crate!()
        .arg_from_usage("<size> 'how many workers there are' ")
        .arg_from_usage("<rank> 'which worker am I, starting from 0' ")
        .arg_from_usage("<addends>.. 'files contains matrices to add'")
        .arg_from_usage("<output> 'file in which to store the resulting matrix'")
        .get_matches();

    let mats = args.values_of("addends").unwrap();
    let size = value_t!(args, "size", usize).unwrap_or_else(|e| e.exit());
    let rank = value_t!(args, "rank", usize).unwrap_or_else(|e| e.exit());
    let chunksize = (mats.len() + size - 1) / size;

    let mut accum = None;
    for matname in mats.skip(rank*chunksize).take(chunksize) {
        let ref matfile = cabarrus::numpy::open_matrix_mmap(matname)?;
        let ref mat = cabarrus::numpy::read_matrix_mmap(matfile)?;
        accum = Some(match accum {
            Some(mut acc) => {acc += mat; acc}
            None => mat.to_owned()
        });
    }
    if let Some(ref acc) = accum {
        cabarrus::numpy::write_matrix(args.value_of("output").unwrap(), acc)?;
    }
    Ok(())
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

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

use bindgen::cargo::cargo_expand;
use bindgen::cargo::cargo_lock::{self, Lock};
use bindgen::cargo::cargo_metadata::{self, Metadata};
use bindgen::cargo::cargo_toml;

/// Parse a dependency string used in Cargo.lock
fn parse_dep_string(dep_string: &str) -> (&str, &str) {
    let split: Vec<&str> = dep_string.split_whitespace().collect();

    (split[0], split[1])
}

/// A reference to a package including it's name and the specific version.
pub struct PackageRef {
    pub name: String,
    pub version: String,
}

/// A collection of metadata for a library from cargo.
#[derive(Clone, Debug)]
pub struct Cargo {
    manifest_path: PathBuf,
    binding_crate_name: String,

    lock: Option<Lock>,
    metadata: Metadata,
}

impl Cargo {
    /// Gather metadata from cargo for a specific library and binding crate
    /// name. If dependency finding isn't needed then Cargo.lock files don't
    /// need to be parsed.
    pub fn load(crate_dir: &Path,
                binding_crate_name: Option<&str>,
                use_cargo_lock: bool) -> Result<Cargo, String> {
        let toml_path = crate_dir.join("Cargo.toml");
        let lock_path = crate_dir.join("Cargo.lock");

        let lock = if use_cargo_lock {
            Some(cargo_lock::lock(&lock_path)
                            .map_err(|x| format!("couldn't load {:?}: {:?}", lock_path, x))?)
        } else {
            None
        };
        let metadata = cargo_metadata::metadata(&toml_path)
                                      .map_err(|_| format!("couldn't execute `cargo metadata` with manifest {:?}.", toml_path))?;

        // Use the specified binding crate name or infer it from the manifest
        let manifest = cargo_toml::manifest(&toml_path)
                                  .map_err(|_| format!("couldn't load {:?}.", toml_path))?;

        let binding_crate_name = binding_crate_name.map_or(manifest.package.name.clone(),
                                                           |x| x.to_owned());

        Ok(Cargo {
            manifest_path: toml_path,
            binding_crate_name: binding_crate_name,
            lock: lock,
            metadata: metadata,
        })
    }

    pub fn binding_crate_name(&self) -> &str {
        &self.binding_crate_name
    }

    pub fn binding_crate_ref(&self) -> PackageRef {
        self.find_pkg_ref(&self.binding_crate_name).unwrap()
    }

    /// Finds the package reference in `cargo metadata` that has `package_name`
    /// ignoring the version.
    fn find_pkg_ref(&self, package_name: &str) -> Option<PackageRef> {
        for package in &self.metadata.packages {
            if package.name == package_name {
                return Some(PackageRef {
                    name: package_name.to_owned(),
                    version: package.version.clone(),
                });
            }
        }
        None
    }

    /// Finds the package reference for a dependency of a crate using
    /// `Cargo.lock`.
    pub fn find_dep_ref(&self, package: &PackageRef, dependency_name: &str) -> Option<PackageRef> {
        if self.lock.is_none() {
            return None;
        }
        let lock = self.lock.as_ref().unwrap();

        if lock.root.name == package.name &&
           lock.root.version == package.version {
            if let Some(ref deps) = lock.root.dependencies {
                for dep in deps {
                    let (name, version) = parse_dep_string(dep);

                    if name == dependency_name {
                        return Some(PackageRef {
                            name: name.to_owned(),
                            version: version.to_owned(),
                        });
                    }
                }
            }
            return None;
        }

        if let &Some(ref lock_packages) = &lock.package {
            for lock_package in lock_packages {
                if lock_package.name == package.name &&
                   lock_package.version == package.version {
                    if let Some(ref deps) = lock_package.dependencies {
                        for dep in deps {
                            let (name, version) = parse_dep_string(dep);

                            if name == dependency_name {
                                return Some(PackageRef {
                                    name: name.to_owned(),
                                    version: version.to_owned(),
                                });
                            }
                        }
                    }
                    return None;
                }
            }
        }
        None
    }

    /// Finds the directory for a specified package reference.
    pub fn find_crate_dir(&self, package: &PackageRef) -> Option<PathBuf> {
        for meta_package in &self.metadata.packages {
            if meta_package.name == package.name &&
               meta_package.version == package.version {
                return Path::new(&meta_package.manifest_path).parent()
                                                             .map(|x| x.to_owned());
            }
        }
        None
    }

    /// Finds `src/lib.rs` for a specified package reference.
    pub fn find_crate_src(&self, package: &PackageRef) -> Option<PathBuf> {
        let kind_lib = String::from("lib");
        let kind_staticlib = String::from("staticlib");
        let kind_cdylib = String::from("cdylib");

        for meta_package in &self.metadata.packages {
            if meta_package.name == package.name &&
               meta_package.version == package.version {
                for target in &meta_package.targets {
                    if target.kind.contains(&kind_lib) ||
                       target.kind.contains(&kind_staticlib) ||
                       target.kind.contains(&kind_cdylib) {
                        return Some(PathBuf::from(&target.src_path));
                    }
                }
                break;
            }
        }
        None
    }

    pub fn expand_crate(&self, package: &PackageRef) -> Result<String, String> {
        cargo_expand::expand(&self.manifest_path, &package.name, &package.version)
    }
}
<commit_msg>Also generate headers for rlib crates<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

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

use bindgen::cargo::cargo_expand;
use bindgen::cargo::cargo_lock::{self, Lock};
use bindgen::cargo::cargo_metadata::{self, Metadata};
use bindgen::cargo::cargo_toml;

/// Parse a dependency string used in Cargo.lock
fn parse_dep_string(dep_string: &str) -> (&str, &str) {
    let split: Vec<&str> = dep_string.split_whitespace().collect();

    (split[0], split[1])
}

/// A reference to a package including it's name and the specific version.
pub struct PackageRef {
    pub name: String,
    pub version: String,
}

/// A collection of metadata for a library from cargo.
#[derive(Clone, Debug)]
pub struct Cargo {
    manifest_path: PathBuf,
    binding_crate_name: String,

    lock: Option<Lock>,
    metadata: Metadata,
}

impl Cargo {
    /// Gather metadata from cargo for a specific library and binding crate
    /// name. If dependency finding isn't needed then Cargo.lock files don't
    /// need to be parsed.
    pub fn load(crate_dir: &Path,
                binding_crate_name: Option<&str>,
                use_cargo_lock: bool) -> Result<Cargo, String> {
        let toml_path = crate_dir.join("Cargo.toml");
        let lock_path = crate_dir.join("Cargo.lock");

        let lock = if use_cargo_lock {
            Some(cargo_lock::lock(&lock_path)
                            .map_err(|x| format!("couldn't load {:?}: {:?}", lock_path, x))?)
        } else {
            None
        };
        let metadata = cargo_metadata::metadata(&toml_path)
                                      .map_err(|_| format!("couldn't execute `cargo metadata` with manifest {:?}.", toml_path))?;

        // Use the specified binding crate name or infer it from the manifest
        let manifest = cargo_toml::manifest(&toml_path)
                                  .map_err(|_| format!("couldn't load {:?}.", toml_path))?;

        let binding_crate_name = binding_crate_name.map_or(manifest.package.name.clone(),
                                                           |x| x.to_owned());

        Ok(Cargo {
            manifest_path: toml_path,
            binding_crate_name: binding_crate_name,
            lock: lock,
            metadata: metadata,
        })
    }

    pub fn binding_crate_name(&self) -> &str {
        &self.binding_crate_name
    }

    pub fn binding_crate_ref(&self) -> PackageRef {
        self.find_pkg_ref(&self.binding_crate_name).unwrap()
    }

    /// Finds the package reference in `cargo metadata` that has `package_name`
    /// ignoring the version.
    fn find_pkg_ref(&self, package_name: &str) -> Option<PackageRef> {
        for package in &self.metadata.packages {
            if package.name == package_name {
                return Some(PackageRef {
                    name: package_name.to_owned(),
                    version: package.version.clone(),
                });
            }
        }
        None
    }

    /// Finds the package reference for a dependency of a crate using
    /// `Cargo.lock`.
    pub fn find_dep_ref(&self, package: &PackageRef, dependency_name: &str) -> Option<PackageRef> {
        if self.lock.is_none() {
            return None;
        }
        let lock = self.lock.as_ref().unwrap();

        if lock.root.name == package.name &&
           lock.root.version == package.version {
            if let Some(ref deps) = lock.root.dependencies {
                for dep in deps {
                    let (name, version) = parse_dep_string(dep);

                    if name == dependency_name {
                        return Some(PackageRef {
                            name: name.to_owned(),
                            version: version.to_owned(),
                        });
                    }
                }
            }
            return None;
        }

        if let &Some(ref lock_packages) = &lock.package {
            for lock_package in lock_packages {
                if lock_package.name == package.name &&
                   lock_package.version == package.version {
                    if let Some(ref deps) = lock_package.dependencies {
                        for dep in deps {
                            let (name, version) = parse_dep_string(dep);

                            if name == dependency_name {
                                return Some(PackageRef {
                                    name: name.to_owned(),
                                    version: version.to_owned(),
                                });
                            }
                        }
                    }
                    return None;
                }
            }
        }
        None
    }

    /// Finds the directory for a specified package reference.
    pub fn find_crate_dir(&self, package: &PackageRef) -> Option<PathBuf> {
        for meta_package in &self.metadata.packages {
            if meta_package.name == package.name &&
               meta_package.version == package.version {
                return Path::new(&meta_package.manifest_path).parent()
                                                             .map(|x| x.to_owned());
            }
        }
        None
    }

    /// Finds `src/lib.rs` for a specified package reference.
    pub fn find_crate_src(&self, package: &PackageRef) -> Option<PathBuf> {
        let kind_lib = String::from("lib");
        let kind_staticlib = String::from("staticlib");
        let kind_rlib = String::from("rlib");
        let kind_cdylib = String::from("cdylib");

        for meta_package in &self.metadata.packages {
            if meta_package.name == package.name &&
               meta_package.version == package.version {
                for target in &meta_package.targets {
                    if target.kind.contains(&kind_lib) ||
                       target.kind.contains(&kind_staticlib) ||
                       target.kind.contains(&kind_rlib) ||
                       target.kind.contains(&kind_cdylib) {
                        return Some(PathBuf::from(&target.src_path));
                    }
                }
                break;
            }
        }
        None
    }

    pub fn expand_crate(&self, package: &PackageRef) -> Result<String, String> {
        cargo_expand::expand(&self.manifest_path, &package.name, &package.version)
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use middle::typing::ast::*;
use middle::typing::type_rewriting::*;
use middle::typing::ast::Type::*;
use middle::typing::ast::IType::*;
use middle::typing::surface::*;
use middle::typing::typing_printer::*;

pub struct Depth
{
  surface: Surface,
  exprs_info: Vec<ExprType>,
  under_unit: bool
}

impl Depth
{
  pub fn infer(grammar: IGrammar) -> TGrammar {
    let mut engine = Depth::new(grammar);
    engine.surface.surface();
    engine.warn_recursive_type();
    engine.reduce_all_rec();
    engine.depth();
    engine.reduce_all_invisible();
    let grammar = engine.surface.grammar;
    if grammar.attributes.print_typing.debug() {
      println!("After applying Depth.");
      print_debug(&grammar);
    }
    grammar.map_exprs_info(engine.exprs_info)
  }

  fn new(grammar: IGrammar) -> Depth {
    Depth {
      surface: Surface::new(grammar),
      exprs_info: vec![],
      under_unit: false
    }
  }

  fn surface_expr(&mut self, expr_idx: usize) {
    self.surface.visit_expr(expr_idx);
    if self.surface.grammar.attributes.print_typing.debug() {
      println!("Applying Surface in Depth on expr {}.", expr_idx);
      print_debug(&self.surface.grammar);
      println!("");
    }
  }

  fn reduce_all_rec(&mut self) {
    let tys: Vec<_> = self.surface.grammar.exprs_info.iter().map(|e| e.ty.clone()).collect();
    let tys: Vec<_> = tys.into_iter().map(|ty| TypeRewriting::reduce_rec(&self.surface.grammar, ty)).collect();
    for (expr_info, ty) in self.surface.grammar.exprs_info.iter_mut().zip(tys.into_iter()) {
      expr_info.ty = ty;
    }
  }

  fn reduce_all_invisible(&mut self) {
    for expr_info in self.surface.grammar.exprs_info.clone() {
      let ty = TypeRewriting::reduce_final(expr_info.ty);
      self.exprs_info.push(ExprType::new(expr_info.span, ty))
    }
  }

  fn depth(&mut self) {
    for rule in self.surface.grammar.rules.clone() {
      self.visit_expr(rule.expr_idx);
    }
  }

  fn type_of(&self, expr_idx: usize) -> IType {
    self.surface.type_of(expr_idx)
  }

  fn warn_recursive_type(&mut self) {
    let mut rec_set = RecSet::empty();
    for rule in &self.surface.grammar.rules {
      if let Rec(r) = self.type_of(rule.expr_idx) {
        rec_set = rec_set.union(r);
      }
    }
    rec_set = rec_set.keep_only_polymorphic_paths();
    if !rec_set.is_empty() {
      for rec_path in rec_set.path_set {
        self.surface.grammar.find_rule_by_ident(&rec_path.path[0]).span().unstable()
          .warning(format!("infinite recursive type automatically replaced by `(^)`: {}\n\
            Semantic actions along the path are ignored.", rec_path.display()))
          .emit();
      }
    }
  }
}

impl ExprByIndex for Depth
{
  fn expr_by_index(&self, index: usize) -> Expression {
    self.surface.expr_by_index(index)
  }
}

impl Visitor<()> for Depth
{
  fn visit_expr(&mut self, this: usize) {
    let this_ty = self.type_of(this);
    assert!(this_ty != Infer,
      format!("Every expression must be typed during the surface inference: {}: {:?}",
        this, self.expr_by_index(this)));

    if self.under_unit {
      self.surface.type_expr(this, Regular(Unit));
      walk_expr(self, this);
    }
    else if this_ty.is_unit_kind() {
      let old = self.under_unit;
      self.under_unit = true;
      walk_expr(self, this);
      self.under_unit = old;
    }
    else {
      walk_expr(self, this);
    }
  }

  // Depth rules
  unit_visitor_impl!(sequence);
  unit_visitor_impl!(choice);

  fn visit_type_ascription(&mut self, _this: usize, child: usize, _ty: IType) {
    self.surface_expr(child);
    self.visit_expr(child);
  }

  fn visit_syntactic_predicate(&mut self, _this: usize, child: usize) {
    self.surface_expr(child);
    self.visit_expr(child);
  }

  fn visit_semantic_action(&mut self, _this: usize, child: usize, _action: syn::Expr) {
    self.surface_expr(child);
    self.visit_expr(child);
  }
}
<commit_msg>[Typing] Allow type ascription of Rust type, external rule call, and external semantic actions. It is related to #80. It closes #95.<commit_after>// Copyright 2016 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use middle::typing::ast::*;
use middle::typing::type_rewriting::*;
use middle::typing::ast::Type::*;
use middle::typing::ast::IType::*;
use middle::typing::surface::*;
use middle::typing::typing_printer::*;

pub struct Depth
{
  surface: Surface,
  exprs_info: Vec<ExprType>,
  under_unit: bool,
  under_ty_ascription: Option<IType>
}

impl Depth
{
  pub fn infer(grammar: IGrammar) -> TGrammar {
    let mut engine = Depth::new(grammar);
    engine.surface.surface();
    engine.warn_recursive_type();
    engine.reduce_all_rec();
    engine.depth();
    engine.reduce_all_invisible();
    engine.check_all_rules_have_type();
    let grammar = engine.surface.grammar;
    if grammar.attributes.print_typing.debug() {
      println!("After applying Depth.");
      print_debug(&grammar);
    }
    grammar.map_exprs_info(engine.exprs_info)
  }

  fn new(grammar: IGrammar) -> Depth {
    Depth {
      surface: Surface::new(grammar),
      exprs_info: vec![],
      under_unit: false,
      under_ty_ascription: None
    }
  }

  fn surface_expr(&mut self, expr_idx: usize) {
    self.surface.visit_expr(expr_idx);
    if self.surface.grammar.attributes.print_typing.debug() {
      println!("Applying Surface in Depth on expr {}.", expr_idx);
      print_debug(&self.surface.grammar);
      println!("");
    }
  }

  fn reduce_all_rec(&mut self) {
    let tys: Vec<_> = self.surface.grammar.exprs_info.iter().map(|e| e.ty.clone()).collect();
    let tys: Vec<_> = tys.into_iter().map(|ty| TypeRewriting::reduce_rec(&self.surface.grammar, ty)).collect();
    for (expr_info, ty) in self.surface.grammar.exprs_info.iter_mut().zip(tys.into_iter()) {
      expr_info.ty = ty;
    }
  }

  fn reduce_all_invisible(&mut self) {
    for expr_info in self.surface.grammar.exprs_info.clone() {
      let ty = TypeRewriting::reduce_final(expr_info.ty);
      self.exprs_info.push(ExprType::new(expr_info.span, ty))
    }
  }

  fn check_all_rules_have_type(&mut self) {
    for rule in self.surface.grammar.rules.clone() {
      if self.type_of(rule.expr_idx) == External {
        rule.name.span().unstable()
          .error(format!("could not infer the type of this rule, please use type ascription, e.g. `r: Expr = e`."))
          .emit();
      }
    }
  }

  fn depth(&mut self) {
    for rule in self.surface.grammar.rules.clone() {
      self.visit_expr(rule.expr_idx);
    }
  }

  fn type_of(&self, expr_idx: usize) -> IType {
    self.surface.type_of(expr_idx)
  }

  fn warn_recursive_type(&mut self) {
    let mut rec_set = RecSet::empty();
    for rule in &self.surface.grammar.rules {
      if let Rec(r) = self.type_of(rule.expr_idx) {
        rec_set = rec_set.union(r);
      }
    }
    rec_set = rec_set.keep_only_polymorphic_paths();
    if !rec_set.is_empty() {
      for rec_path in rec_set.path_set {
        self.surface.grammar.find_rule_by_ident(&rec_path.path[0]).span().unstable()
          .warning(format!("infinite recursive type automatically replaced by `(^)`: {}\n\
            Semantic actions along the path are ignored.", rec_path.display()))
          .emit();
      }
    }
  }

  fn visit_expr_switch_ascription(&mut self, this: usize, new: Option<IType>) {
    let old = self.under_ty_ascription.clone();
    self.under_ty_ascription = new;
    self.visit_expr(this);
    self.under_ty_ascription = old;
  }

  fn error_if_not_match_ty_ascription(&self, this: usize, ty: IType, aty: IType) {
    if !ty.syntactic_eq(&self.surface.grammar, &aty) {
      self.surface.grammar[this].span().unstable()
        .error(format!("found type {} but expected type {}",
          ty.display(&self.surface.grammar), aty.display(&self.surface.grammar)))
        .emit();
    }
  }
}

impl ExprByIndex for Depth
{
  fn expr_by_index(&self, index: usize) -> Expression {
    self.surface.expr_by_index(index)
  }
}

impl Visitor<()> for Depth
{
  fn visit_expr(&mut self, this: usize) {
    let this_ty = self.type_of(this);
    assert!(this_ty != Infer,
      format!("Every expression must be typed during the surface inference: {}: {:?}",
        this, self.expr_by_index(this)));

    if self.under_unit {
      self.surface.type_expr(this, Regular(Unit));
      walk_expr(self, this);
    }
    else if this_ty.is_unit_kind() && self.under_ty_ascription.is_none() {
      let old = self.under_unit;
      self.under_unit = true;
      walk_expr(self, this);
      self.under_unit = old;
    }
    else {
      if let Some(aty) = self.under_ty_ascription.clone() {
        if this_ty == External {
          self.surface.type_expr(this, aty);
        }
        else {
          self.error_if_not_match_ty_ascription(this, this_ty, aty);
        }
      }
      walk_expr(self, this);
    }
  }

  // Depth rules
  unit_visitor_impl!(choice);

  // If we are under a type ascription, then a single element of the sequence must take that type, all others must be unit.
  fn visit_sequence(&mut self, _this: usize, children: Vec<usize>) {
    if self.under_ty_ascription.is_some() {
      for child in children {
        let child_ty = self.type_of(child);
        if child_ty.is_unit_kind() {
          self.visit_expr_switch_ascription(child, None);
        }
        else {
          self.visit_expr(child);
        }
      }
    }
    else {
      walk_exprs(self, children);
    }
  }

  fn visit_type_ascription(&mut self, this: usize, child: usize, ty: IType) {
    if let Some(aty) = self.under_ty_ascription.clone() {
      self.error_if_not_match_ty_ascription(this, ty.clone(), aty);
    }
    self.surface_expr(child);
    self.visit_expr_switch_ascription(child, Some(ty));
  }

  fn visit_syntactic_predicate(&mut self, _this: usize, child: usize) {
    self.surface_expr(child);
    self.visit_expr(child);
  }

  // We rely on the Rust compiler to spot type mismatch between semantic action's return type and type ascription.
  fn visit_semantic_action(&mut self, _this: usize, child: usize, _action: syn::Expr) {
    self.surface_expr(child);
    self.visit_expr_switch_ascription(child, None);
  }
}
<|endoftext|>