<commit_before>extern crate mime = "mime-types";
extern crate conduit;

use std::fmt::Show;
use std::collections::HashMap;
use std::io::fs::File;
use std::io::util::NullReader;
use conduit::{Request, Response, Handler};

pub struct Static {
    path: Path,
    types: mime::Types
}

impl Static {
    pub fn new(path: Path) -> Static {
        Static {
            path: path,
            types: mime::Types::new()
                .ok().expect("Couldn't load mime-types")
        }
    }
}

impl Handler for Static {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show>> {
        let request_path = request.path().slice_from(1);
        let path = self.path.join(request_path);

        if !self.path.is_ancestor_of(&path) {
            return Ok(Response {
                status: (404, "Not Found"),
                headers: HashMap::new(),
                body: box NullReader
            })
        }

        let mime = self.types.mime_for_path(&path);
        let file = try!(File::open(&path).map_err(|e| box e as Box<Show>));

        let mut headers = HashMap::new();
        headers.insert("Content-Type".to_str(), vec!(mime.to_str()));

        Ok(Response {
            status: (200, "OK"),
            headers: headers,
            body: box file as Box<Reader + Send>
        })
    }
}

#[cfg(test)]
mod tests {
    extern crate test = "conduit-test";

    use std::io::{fs, File, TempDir, UserRWX};

    use conduit;
    use conduit::Handler;
    use Static;

    #[test]
    fn test_static() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        let handler = Static::new(root.clone());
        File::create(&root.join("Cargo.toml")).write(b"[package]").unwrap();
        let mut req = test::MockRequest::new(conduit::Get, "/Cargo.toml");
        let mut res = handler.call(&mut req).ok().expect("No response");
        let body = res.body.read_to_str().ok().expect("No body");
        assert_eq!(body.as_slice(), "[package]");
        assert_eq!(res.headers.find_equiv(&"Content-Type")
                      .expect("No content-type"),
                   &vec!("text/plain".to_str()));
    }

    #[test]
    fn test_mime_types() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        fs::mkdir(&root.join("src"), UserRWX).unwrap();
        File::create(&root.join("src/fixture.css")).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/src/fixture.css");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.headers.find_equiv(&"Content-Type")
                      .expect("No content-type"),
                   &vec!("text/css".to_str()));
    }
}
<commit_msg>Translate fs errors to 404s instead of errors<commit_after>extern crate mime = "mime-types";
extern crate conduit;

use std::fmt::Show;
use std::collections::HashMap;
use std::io::fs::File;
use std::io::util::NullReader;
use conduit::{Request, Response, Handler};

pub struct Static {
    path: Path,
    types: mime::Types
}

impl Static {
    pub fn new(path: Path) -> Static {
        Static {
            path: path,
            types: mime::Types::new()
                .ok().expect("Couldn't load mime-types")
        }
    }
}

impl Handler for Static {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show>> {
        let request_path = request.path().slice_from(1);
        let path = self.path.join(request_path);

        if !self.path.is_ancestor_of(&path) {
            return Ok(Response {
                status: (404, "Not Found"),
                headers: HashMap::new(),
                body: box NullReader
            })
        }

        let mime = self.types.mime_for_path(&path);
        let mut file = match File::open(&path) {
            Ok(f) => f,
            Err(..) => {
                return Ok(Response {
                    status: (404, "Not Found"),
                    headers: HashMap::new(),
                    body: box NullReader,
                })
            }
        };
        let stat = try!(file.stat().map_err(|e| box e as Box<Show>));

        let mut headers = HashMap::new();
        headers.insert("Content-Type".to_str(), vec![mime.to_str()]);
        headers.insert("Content-Length".to_str(), vec![stat.size.to_str()]);

        Ok(Response {
            status: (200, "OK"),
            headers: headers,
            body: box file as Box<Reader + Send>
        })
    }
}

#[cfg(test)]
mod tests {
    extern crate test = "conduit-test";

    use std::io::{fs, File, TempDir, UserRWX};

    use conduit;
    use conduit::Handler;
    use Static;

    #[test]
    fn test_static() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        let handler = Static::new(root.clone());
        File::create(&root.join("Cargo.toml")).write(b"[package]").unwrap();
        let mut req = test::MockRequest::new(conduit::Get, "/Cargo.toml");
        let mut res = handler.call(&mut req).ok().expect("No response");
        let body = res.body.read_to_str().ok().expect("No body");
        assert_eq!(body.as_slice(), "[package]");
        assert_eq!(res.headers.find_equiv(&"Content-Type"),
                   Some(&vec!("text/plain".to_str())));
        assert_eq!(res.headers.find_equiv(&"Content-Length"),
                   Some(&vec!["9".to_str()]));
    }

    #[test]
    fn test_mime_types() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        fs::mkdir(&root.join("src"), UserRWX).unwrap();
        File::create(&root.join("src/fixture.css")).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/src/fixture.css");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.headers.find_equiv(&"Content-Type"),
                   Some(&vec!("text/css".to_str())));
        assert_eq!(res.headers.find_equiv(&"Content-Length"),
                   Some(&vec!["0".to_str()]));
    }

    #[test]
    fn test_missing() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/nope");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 404);
    }
}
<|endoftext|>


<commit_before>extern crate dbus;

use std;
use std::env;
use general::*;
use device::DeviceType;

/// Get a list of Network Manager connections sorted by path.
///
/// # Examples
///
/// ```no_run
/// use network_manager::connection;
/// let connections = connection::list().unwrap();
/// println!("{:?}", connections);
/// ```
pub fn list() -> Result<Vec<Connection>, String> {
    let message = dbus_message!(NM_SERVICE_MANAGER,
                                NM_SETTINGS_PATH,
                                NM_SETTINGS_INTERFACE,
                                "ListConnections");
    let response = dbus_connect!(message);
    let paths: dbus::arg::Array<dbus::Path, _> = response.get1().unwrap();
    let mut connections: Vec<_> = paths.map(|p| get_connection(p).unwrap()).collect();
    connections.sort_by(|a, b| a.cmp(b));

    Ok(connections)
}

#[test]
fn test_list_function() {
    let connections = list().unwrap();
    assert!(connections.len() > 0);
    for (index, val) in connections.iter().enumerate() {
        assert_ne!(Connection { ..Default::default() }, val.clone());
        assert_eq!(index as i32, i32::from(val));
    }
}

/// Creates a Network Manager connection.
///
/// # Examples
///
/// ```
/// let connection = network_manager::connection::create(
///     "resin_io",
///     network_manager::device::DeviceType::WiFi,
///     network_manager::general::Security::WPA2,
///     "super_secret_passphase"
///     ).unwrap();
/// println!("{:?}", connection);
/// ```
pub fn create(s: &str, dt: DeviceType, sc: Security, p: &str) -> Result<Connection, String> {
    // Create a connection
    // Get the connection
    // Return the connection

    let connection1 = Connection {
        path: "/org/freedesktop/NetworkManager/ActiveConnection/187".to_string(),
        id: "resin_io".to_string(),
        uuid: "3c8e6e8b-b895-4b07-97a5-bbc192c3b436".to_string(),
        ssid: "resin_io".to_string(),
        active_path: "test".to_string(),
        state: ConnectionState::Deactivated, /* device: "wlp4s0".to_string(),
                                              * interface: DeviceType::WiFi,
                                              * security: Security::WPA2,
                                              * state: ConnectionState::Activated, */
    };

    Ok(connection1)
}

/// Deletes a Network Manager connection.
///
/// # Examples
///
/// ```
/// let mut connections = network_manager::connection::list().unwrap();
/// network_manager::connection::delete(connections.pop().unwrap()).unwrap();
/// ```
pub fn delete(connection: Connection) -> Result<(), String> {
    let message = dbus_message!(NM_SERVICE_MANAGER,
                                connection.path,
                                NM_CONNECTION_INTERFACE,
                                "Delete");
    dbus_connect!(message);

    Ok(())
}

/// Enables a Network Manager connection.
///
/// # Examples
///
/// ```no_run
/// use network_manager::connection;
/// let connections = connection::list().unwrap();
/// let mut connection = connections[0].clone();
/// connection::enable(&mut connection, 10).unwrap();
/// println!("{:?}", connection.state);
/// ```
pub fn enable(connection: &mut Connection, time_out: i32) -> Result<(), String> {
    update_state(connection).expect("Unable to get connection state");
    match connection.state {
        ConnectionState::Activated => Ok(()),
        ConnectionState::Activating => wait(connection, time_out, ConnectionState::Activated),
        ConnectionState::Unknown => Err("Unable to get connection state".to_string()),
        _ => {
            let mut message = dbus_message!(NM_SERVICE_MANAGER,
                                            NM_SERVICE_PATH,
                                            NM_SERVICE_INTERFACE,
                                            "ActivateConnection");
            message.append_items(&[dbus::MessageItem::ObjectPath(connection.path
                                                                     .to_string()
                                                                     .into()),
                                   dbus::MessageItem::ObjectPath("/".into()),
                                   dbus::MessageItem::ObjectPath("/".into())]);
            dbus_connect!(message);

            wait(connection, time_out, ConnectionState::Activated)
        }
    }
}

/// Disables a Network Manager connection.
///
/// # Examples
///
/// ```no_run
/// use network_manager::connection;
/// let connections = connection::list().unwrap();
/// let mut connection = connections[0].clone();
/// connection::disable(&mut connection, 10).unwrap();
/// println!("{:?}", connection.state);
/// ```
pub fn disable(connection: &mut Connection, time_out: i32) -> Result<(), String> {
    update_state(connection).expect("Unable to get connection state");
    match connection.state {
        ConnectionState::Deactivated => Ok(()),
        ConnectionState::Deactivating => wait(connection, time_out, ConnectionState::Deactivated),
        ConnectionState::Unknown => Err("Unable to get connection state".to_string()),
        _ => {
            let mut message = dbus_message!(NM_SERVICE_MANAGER,
                                            NM_SERVICE_PATH,
                                            NM_SERVICE_INTERFACE,
                                            "DeactivateConnection");
            message.append_items(&[dbus::MessageItem::ObjectPath(connection.active_path
                                                                     .to_string()
                                                                     .into())]);
            dbus_connect!(message);

            wait(connection, time_out, ConnectionState::Deactivated)
        }
    }
}

//#[test]
fn test_enable_disable_functions() {
    let connections = list().unwrap();
    let mut connection;

    // set enviorment variable $TEST_WIFI_SSID with the wifi's SSID that you want to test
    // e.g.  export TEST_WIFI_SSID="Resin.io Wifi"
    let wifiEnvVar = "TEST_WIFI_SSID";
    match env::var(wifiEnvVar) {
        Ok(ssid) => {
            connection = connections.iter()
                .filter(|c| c.ssid == ssid)
                .nth(0)
                .unwrap()
                .clone()
        }
        Err(e) => {
            panic!("couldn't retrieve enviorment variable {}: {}",
                   wifiEnvVar,
                   e)
        }
    };

    assert!(connection.state == ConnectionState::Activated ||
            connection.state == ConnectionState::Deactivated);

    match connection.state {
        ConnectionState::Activated => {
            disable(&mut connection, 10).unwrap();
            assert_eq!(ConnectionState::Deactivated, connection.state);

            enable(&mut connection, 10).unwrap();
            assert_eq!(ConnectionState::Activated, connection.state);
        }
        ConnectionState::Deactivated => {
            enable(&mut connection, 10).unwrap();
            assert_eq!(ConnectionState::Activated, connection.state);

            disable(&mut connection, 10).unwrap();
            assert_eq!(ConnectionState::Deactivated, connection.state);
        }
        _ => (),
    }
}

fn get_connection(path: dbus::Path) -> Result<Connection, String> {
    let mut connection = Connection { path: dbus_path_to_string(path), ..Default::default() };

    let message = dbus_message!(NM_SERVICE_MANAGER,
                                connection.path.clone(),
                                NM_CONNECTION_INTERFACE,
                                "GetSettings");
    let response = dbus_connect!(message);
    let dictionary: dbus::arg::Dict<&str,
                                    dbus::arg::Dict<&str, dbus::arg::Variant<dbus::arg::Iter>, _>,
                                    _> = response.get1().unwrap();

    for (_, v1) in dictionary {
        for (k2, v2) in v1 {
            match k2 {
                "id" => {
                    connection.id = v2.0
                        .clone()
                        .get::<&str>()
                        .unwrap()
                        .to_string();
                }
                "uuid" => {
                    connection.uuid = v2.0
                        .clone()
                        .get::<&str>()
                        .unwrap()
                        .to_string();
                }
                "ssid" => {
                    connection.ssid =
                        std::str::from_utf8(&v2.0
                                                 .clone()
                                                 .get::<dbus::arg::Array<u8, _>>()
                                                 .unwrap()
                                                 .collect::<Vec<u8>>())
                                .unwrap()
                                .to_string();
                }
                _ => (),
            }
        }
    }

    update_state(&mut connection).unwrap();

    Ok(connection)
}

fn update_state(connection: &mut Connection) -> Result<(), String> {
    let active_paths: Vec<String> = dbus_property!(NM_SERVICE_MANAGER,
                                                   NM_SERVICE_PATH,
                                                   NM_SERVICE_INTERFACE,
                                                   "ActiveConnections")
            .unwrap()
            .inner::<&Vec<dbus::MessageItem>>()
            .unwrap()
            .iter()
            .map(|p| dbus_path_to_string(p.inner::<&dbus::Path>().unwrap().to_owned()))
            .collect();

    let settings_paths = active_paths.iter().map(|p| {
        dbus_path_to_string(dbus_property!(NM_SERVICE_MANAGER,
                                           p,
                                           NM_ACTIVE_INTERFACE,
                                           "Connection")
                                    .unwrap()
                                    .inner::<&dbus::Path>()
                                    .unwrap()
                                    .to_owned())
    });

    connection.active_path = "".to_string();
    connection.state = ConnectionState::Deactivated;

    for (active_path, settings_path) in active_paths.iter().zip(settings_paths) {
        if connection.path == settings_path {
            connection.active_path = active_path.to_owned();

            let result = dbus_property!(NM_SERVICE_MANAGER,
                                        connection.active_path.clone(),
                                        NM_ACTIVE_INTERFACE,
                                        "State");
            if let Ok(val) = result {
                connection.state = ConnectionState::from(val.inner::<u32>().unwrap())
            }

            break;
        }
    }

    Ok(())
}

fn wait(connection: &mut Connection,
        time_out: i32,
        target_state: ConnectionState)
        -> Result<(), String> {
    if time_out == 0 {
        return Ok(());
    }

    let mut total_time = 0;
    while total_time < time_out {
        update_state(connection).unwrap();
        if connection.state == target_state {
            return Ok(());
        }
        std::thread::sleep(std::time::Duration::from_secs(1));
        total_time += 1;
    }

    Err("service timed out".to_string())
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Connection {
    pub path: String,
    pub active_path: String,
    pub id: String,
    pub uuid: String,
    pub ssid: String,
    pub state: ConnectionState, /* device: String,
                                 * device_type: DeviceType,
                                 * security: Security, */
}

impl Default for Connection {
    fn default() -> Connection {
        Connection {
            path: "".to_string(),
            active_path: "".to_string(),
            id: "".to_string(),
            uuid: "".to_string(),
            ssid: "".to_string(),
            state: ConnectionState::Unknown,
        }
    }
}

impl Ord for Connection {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        i32::from(self).cmp(&i32::from(other))
    }
}

impl PartialOrd for Connection {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<'a> From<&'a Connection> for i32 {
    fn from(val: &Connection) -> i32 {
        val.clone()
            .path
            .rsplit('/')
            .nth(0)
            .unwrap()
            .parse::<i32>()
            .unwrap()
    }
}
<commit_msg>Enabling back the connection::test_enable_disable_functions test<commit_after>extern crate dbus;

use std;
use std::env;
use general::*;
use device::DeviceType;

/// Get a list of Network Manager connections sorted by path.
///
/// # Examples
///
/// ```no_run
/// use network_manager::connection;
/// let connections = connection::list().unwrap();
/// println!("{:?}", connections);
/// ```
pub fn list() -> Result<Vec<Connection>, String> {
    let message = dbus_message!(NM_SERVICE_MANAGER,
                                NM_SETTINGS_PATH,
                                NM_SETTINGS_INTERFACE,
                                "ListConnections");
    let response = dbus_connect!(message);
    let paths: dbus::arg::Array<dbus::Path, _> = response.get1().unwrap();
    let mut connections: Vec<_> = paths.map(|p| get_connection(p).unwrap()).collect();
    connections.sort_by(|a, b| a.cmp(b));

    Ok(connections)
}

#[test]
fn test_list_function() {
    let connections = list().unwrap();
    assert!(connections.len() > 0);
    for (index, val) in connections.iter().enumerate() {
        assert_ne!(Connection { ..Default::default() }, val.clone());
        assert_eq!(index as i32, i32::from(val));
    }
}

/// Creates a Network Manager connection.
///
/// # Examples
///
/// ```
/// let connection = network_manager::connection::create(
///     "resin_io",
///     network_manager::device::DeviceType::WiFi,
///     network_manager::general::Security::WPA2,
///     "super_secret_passphase"
///     ).unwrap();
/// println!("{:?}", connection);
/// ```
pub fn create(s: &str, dt: DeviceType, sc: Security, p: &str) -> Result<Connection, String> {
    // Create a connection
    // Get the connection
    // Return the connection

    let connection1 = Connection {
        path: "/org/freedesktop/NetworkManager/ActiveConnection/187".to_string(),
        id: "resin_io".to_string(),
        uuid: "3c8e6e8b-b895-4b07-97a5-bbc192c3b436".to_string(),
        ssid: "resin_io".to_string(),
        active_path: "test".to_string(),
        state: ConnectionState::Deactivated, /* device: "wlp4s0".to_string(),
                                              * interface: DeviceType::WiFi,
                                              * security: Security::WPA2,
                                              * state: ConnectionState::Activated, */
    };

    Ok(connection1)
}

/// Deletes a Network Manager connection.
///
/// # Examples
///
/// ```
/// let mut connections = network_manager::connection::list().unwrap();
/// network_manager::connection::delete(connections.pop().unwrap()).unwrap();
/// ```
pub fn delete(connection: Connection) -> Result<(), String> {
    let message = dbus_message!(NM_SERVICE_MANAGER,
                                connection.path,
                                NM_CONNECTION_INTERFACE,
                                "Delete");
    dbus_connect!(message);

    Ok(())
}

/// Enables a Network Manager connection.
///
/// # Examples
///
/// ```no_run
/// use network_manager::connection;
/// let connections = connection::list().unwrap();
/// let mut connection = connections[0].clone();
/// connection::enable(&mut connection, 10).unwrap();
/// println!("{:?}", connection.state);
/// ```
pub fn enable(connection: &mut Connection, time_out: i32) -> Result<(), String> {
    update_state(connection).expect("Unable to get connection state");
    match connection.state {
        ConnectionState::Activated => Ok(()),
        ConnectionState::Activating => wait(connection, time_out, ConnectionState::Activated),
        ConnectionState::Unknown => Err("Unable to get connection state".to_string()),
        _ => {
            let mut message = dbus_message!(NM_SERVICE_MANAGER,
                                            NM_SERVICE_PATH,
                                            NM_SERVICE_INTERFACE,
                                            "ActivateConnection");
            message.append_items(&[dbus::MessageItem::ObjectPath(connection.path
                                                                     .to_string()
                                                                     .into()),
                                   dbus::MessageItem::ObjectPath("/".into()),
                                   dbus::MessageItem::ObjectPath("/".into())]);
            dbus_connect!(message);

            wait(connection, time_out, ConnectionState::Activated)
        }
    }
}

/// Disables a Network Manager connection.
///
/// # Examples
///
/// ```no_run
/// use network_manager::connection;
/// let connections = connection::list().unwrap();
/// let mut connection = connections[0].clone();
/// connection::disable(&mut connection, 10).unwrap();
/// println!("{:?}", connection.state);
/// ```
pub fn disable(connection: &mut Connection, time_out: i32) -> Result<(), String> {
    update_state(connection).expect("Unable to get connection state");
    match connection.state {
        ConnectionState::Deactivated => Ok(()),
        ConnectionState::Deactivating => wait(connection, time_out, ConnectionState::Deactivated),
        ConnectionState::Unknown => Err("Unable to get connection state".to_string()),
        _ => {
            let mut message = dbus_message!(NM_SERVICE_MANAGER,
                                            NM_SERVICE_PATH,
                                            NM_SERVICE_INTERFACE,
                                            "DeactivateConnection");
            message.append_items(&[dbus::MessageItem::ObjectPath(connection.active_path
                                                                     .to_string()
                                                                     .into())]);
            dbus_connect!(message);

            wait(connection, time_out, ConnectionState::Deactivated)
        }
    }
}

#[test]
fn test_enable_disable_functions() {
    let connections = list().unwrap();
    let mut connection;

    // set enviorment variable $TEST_WIFI_SSID with the wifi's SSID that you want to test
    // e.g.  export TEST_WIFI_SSID="Resin.io Wifi"
    let wifiEnvVar = "TEST_WIFI_SSID";
    match env::var(wifiEnvVar) {
        Ok(ssid) => {
            connection = connections.iter()
                .filter(|c| c.ssid == ssid)
                .nth(0)
                .unwrap()
                .clone()
        }
        Err(e) => {
            panic!("couldn't retrieve enviorment variable {}: {}",
                   wifiEnvVar,
                   e)
        }
    };

    assert!(connection.state == ConnectionState::Activated ||
            connection.state == ConnectionState::Deactivated);

    match connection.state {
        ConnectionState::Activated => {
            disable(&mut connection, 10).unwrap();
            assert_eq!(ConnectionState::Deactivated, connection.state);

            enable(&mut connection, 10).unwrap();
            assert_eq!(ConnectionState::Activated, connection.state);
        }
        ConnectionState::Deactivated => {
            enable(&mut connection, 10).unwrap();
            assert_eq!(ConnectionState::Activated, connection.state);

            disable(&mut connection, 10).unwrap();
            assert_eq!(ConnectionState::Deactivated, connection.state);
        }
        _ => (),
    }
}

fn get_connection(path: dbus::Path) -> Result<Connection, String> {
    let mut connection = Connection { path: dbus_path_to_string(path), ..Default::default() };

    let message = dbus_message!(NM_SERVICE_MANAGER,
                                connection.path.clone(),
                                NM_CONNECTION_INTERFACE,
                                "GetSettings");
    let response = dbus_connect!(message);
    let dictionary: dbus::arg::Dict<&str,
                                    dbus::arg::Dict<&str, dbus::arg::Variant<dbus::arg::Iter>, _>,
                                    _> = response.get1().unwrap();

    for (_, v1) in dictionary {
        for (k2, v2) in v1 {
            match k2 {
                "id" => {
                    connection.id = v2.0
                        .clone()
                        .get::<&str>()
                        .unwrap()
                        .to_string();
                }
                "uuid" => {
                    connection.uuid = v2.0
                        .clone()
                        .get::<&str>()
                        .unwrap()
                        .to_string();
                }
                "ssid" => {
                    connection.ssid =
                        std::str::from_utf8(&v2.0
                                                 .clone()
                                                 .get::<dbus::arg::Array<u8, _>>()
                                                 .unwrap()
                                                 .collect::<Vec<u8>>())
                                .unwrap()
                                .to_string();
                }
                _ => (),
            }
        }
    }

    update_state(&mut connection).unwrap();

    Ok(connection)
}

fn update_state(connection: &mut Connection) -> Result<(), String> {
    let active_paths: Vec<String> = dbus_property!(NM_SERVICE_MANAGER,
                                                   NM_SERVICE_PATH,
                                                   NM_SERVICE_INTERFACE,
                                                   "ActiveConnections")
            .unwrap()
            .inner::<&Vec<dbus::MessageItem>>()
            .unwrap()
            .iter()
            .map(|p| dbus_path_to_string(p.inner::<&dbus::Path>().unwrap().to_owned()))
            .collect();

    let settings_paths = active_paths.iter().map(|p| {
        dbus_path_to_string(dbus_property!(NM_SERVICE_MANAGER,
                                           p,
                                           NM_ACTIVE_INTERFACE,
                                           "Connection")
                                    .unwrap()
                                    .inner::<&dbus::Path>()
                                    .unwrap()
                                    .to_owned())
    });

    connection.active_path = "".to_string();
    connection.state = ConnectionState::Deactivated;

    for (active_path, settings_path) in active_paths.iter().zip(settings_paths) {
        if connection.path == settings_path {
            connection.active_path = active_path.to_owned();

            let result = dbus_property!(NM_SERVICE_MANAGER,
                                        connection.active_path.clone(),
                                        NM_ACTIVE_INTERFACE,
                                        "State");
            if let Ok(val) = result {
                connection.state = ConnectionState::from(val.inner::<u32>().unwrap())
            }

            break;
        }
    }

    Ok(())
}

fn wait(connection: &mut Connection,
        time_out: i32,
        target_state: ConnectionState)
        -> Result<(), String> {
    if time_out == 0 {
        return Ok(());
    }

    let mut total_time = 0;
    while total_time < time_out {
        update_state(connection).unwrap();
        if connection.state == target_state {
            return Ok(());
        }
        std::thread::sleep(std::time::Duration::from_secs(1));
        total_time += 1;
    }

    Err("service timed out".to_string())
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Connection {
    pub path: String,
    pub active_path: String,
    pub id: String,
    pub uuid: String,
    pub ssid: String,
    pub state: ConnectionState, /* device: String,
                                 * device_type: DeviceType,
                                 * security: Security, */
}

impl Default for Connection {
    fn default() -> Connection {
        Connection {
            path: "".to_string(),
            active_path: "".to_string(),
            id: "".to_string(),
            uuid: "".to_string(),
            ssid: "".to_string(),
            state: ConnectionState::Unknown,
        }
    }
}

impl Ord for Connection {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        i32::from(self).cmp(&i32::from(other))
    }
}

impl PartialOrd for Connection {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<'a> From<&'a Connection> for i32 {
    fn from(val: &Connection) -> i32 {
        val.clone()
            .path
            .rsplit('/')
            .nth(0)
            .unwrap()
            .parse::<i32>()
            .unwrap()
    }
}
<|endoftext|>


<commit_before><commit_msg>Fixed for latest Rust: link_args -> link(name=..)<commit_after><|endoftext|>


<commit_before>use cpu::arm64::asm::*;
use cpu::arm64::*;
use cpu::{Mem, Reg, trap};
use cpu::arm64::reg::*;
use baseline::buffer::*;
use baseline::codegen::CondCode;
use lexer::position::Position;
use mem::ptr_width;
use object::IntArray;
use ty::MachineMode;
use vtable::VTable;

pub fn prolog(buf: &mut Buffer, stacksize: i32) {
    buf.emit_u32(stp_pre(1, REG_FP, REG_LR, REG_SP, -2));
    buf.emit_u32(add_reg(1, REG_FP, REG_SP, REG_ZERO));

    if stacksize > 0 {
        let scratch = get_scratch();
        load_int_const(buf, scratch, stacksize);
        buf.emit_u32(sub_reg(1, REG_SP, REG_SP, scratch));
    }
}

pub fn epilog(buf: &mut Buffer, stacksize: i32) {
    if stacksize > 0 {
        let scratch = get_scratch();
        load_int_const(buf, scratch, stacksize);
        buf.emit_u32(add_reg(1, REG_SP, REG_SP, scratch));
    }

    buf.emit_u32(add_reg(1, REG_SP, REG_FP, REG_ZERO));
    buf.emit_u32(ldp_post(1, REG_FP, REG_LR, REG_SP, 2));
    buf.emit_u32(ret());
}

pub fn direct_call(buf: &mut Buffer, ptr: *const u8) {
    let disp = buf.add_addr(ptr);
    let pos = buf.pos() as i32;

    let scratch = get_scratch();

    load_constpool(buf, REG_RESULT, disp + pos);
    br(scratch);
}

pub fn indirect_call(buf: &mut Buffer, index: u32) {
    let obj = REG_PARAMS[0];

    // REG_RESULT = [obj] (load vtable)
    load_mem(buf, MachineMode::Ptr, REG_RESULT, Mem::Base(obj, 0));

    // calculate offset of VTable entry
    let disp = VTable::offset_of_method_table() + (index as i32) * ptr_width();

    // load vtable entry
    load_mem(buf, MachineMode::Ptr, REG_RESULT, Mem::Base(REG_RESULT, disp));

    // call *REG_RESULT
    buf.emit_u32(blr(REG_RESULT));
}

pub fn load_array_elem(buf: &mut Buffer, mode: MachineMode, dest: Reg, array: Reg, index: Reg) {
    assert!(mode == MachineMode::Int32);

    load_mem(buf, mode, dest, Mem::Index(array, index, mode.size(), IntArray::offset_of_data()));
}

pub fn store_array_elem(buf: &mut Buffer, mode: MachineMode, array: Reg, index: Reg, value: Reg) {
    assert!(mode == MachineMode::Int32);

    store_mem(buf, MachineMode::Int32,
              Mem::Index(array, index, 4, IntArray::offset_of_data()), value);
}

pub fn test_if_nil_bailout(buf: &mut Buffer, pos: Position, reg: Reg) {
    cmp_reg(buf, MachineMode::Ptr, reg, reg);

    let lbl = buf.create_label();
    jump_if(buf, CondCode::Zero, lbl);
    buf.emit_bailout(lbl, trap::NIL, pos);
}

pub fn test_if_nil(buf: &mut Buffer, reg: Reg) -> Label {
    cmp_reg(buf, MachineMode::Ptr, reg, reg);

    let lbl = buf.create_label();
    jump_if(buf, CondCode::Zero, lbl);

    lbl
}

pub fn set(buf: &mut Buffer, dest: Reg, op: CondCode) {
    buf.emit_u32(cmp_imm(0, dest, 0, 0));
    buf.emit_u32(cset(0, dest, CondCode::NotEqual.into()));
}

pub fn cmp_mem(buf: &mut Buffer, mode: MachineMode, mem: Mem, rhs: Reg) {
    unimplemented!();
}

pub fn cmp_mem_imm(buf: &mut Buffer, mode: MachineMode, mem: Mem, imm: i32) {
    unimplemented!();
}

pub fn cmp_reg(buf: &mut Buffer, mode: MachineMode, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn test_and_jump_if(buf: &mut Buffer, cond: CondCode, reg: Reg, lbl: Label) {
    assert!(cond == CondCode::Zero || cond == CondCode::NonZero);

    unimplemented!();
}

pub fn jump_if(buf: &mut Buffer, cond: CondCode, lbl: Label) {
    unimplemented!();
}

pub fn jump(buf: &mut Buffer, lbl: Label) {
    unimplemented!();
}

pub fn int_div(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn int_mod(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn int_mul(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn int_add(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn int_sub(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn int_shl(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn int_or(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn int_and(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn int_xor(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn check_index_out_of_bounds(buf: &mut Buffer, pos: Position, array: Reg,
                                 index: Reg, temp: Reg) {
    unimplemented!();
}

pub fn load_nil(buf: &mut Buffer, dest: Reg) {
    unimplemented!();
}

pub fn load_mem(buf: &mut Buffer, mode: MachineMode, dest: Reg, mem: Mem) {
    unimplemented!();
}

pub fn store_mem(buf: &mut Buffer, mode: MachineMode, mem: Mem, src: Reg) {
    unimplemented!();
}

pub fn copy_reg(buf: &mut Buffer, mode: MachineMode, dest: Reg, src: Reg) {
    unimplemented!();
}

pub fn load_constpool(buf: &mut Buffer, dest: Reg, disp: i32) {
    unimplemented!();
}

pub fn call_reg(buf: &mut Buffer, reg: Reg) {
    buf.emit_u32(blr(reg));
}

pub fn debug(buf: &mut Buffer) {
    unimplemented!();
}

pub fn load_int_const(buf: &mut Buffer, dest: Reg, imm: i32) {
    let register_size = 32;
    let imm = imm as i64 as u64;

    if fits_movz(imm, register_size) {
        buf.emit_u32(movz(0, dest, imm as u32, 0));

    } else if fits_movn(imm, register_size) {
        buf.emit_u32(movn(0, dest, imm as u32, 0));

    } else {
        unimplemented!();
    }
}

pub fn load_true(buf: &mut Buffer, dest: Reg) {
    buf.emit_u32(movz(0, dest, 1, 0));
}

pub fn load_false(buf: &mut Buffer, dest: Reg) {
    buf.emit_u32(movz(0, dest, 0, 0));
}

pub fn int_neg(buf: &mut Buffer, dest: Reg, src: Reg) {
    buf.emit_u32(sub_reg(0, dest, REG_ZERO, src));
}

pub fn int_not(buf: &mut Buffer, dest: Reg, src: Reg) {
    buf.emit_u32(orn_shreg(0, dest, REG_ZERO, src, Shift::LSL, 0));
}

pub fn bool_not(buf: &mut Buffer, dest: Reg, src: Reg) {
    let scratch = get_scratch();

    buf.emit_u32(movz(0, scratch, 1, 0));
    buf.emit_u32(eor_shreg(0, dest, src, scratch, Shift::LSL, 0));
    buf.emit_u32(uxtb(dest, dest));
}

fn get_scratch() -> Reg {
    SCRATCH[0]
}
<commit_msg>arm64: implement more instructions<commit_after>use cpu::arm64::asm::*;
use cpu::arm64::*;
use cpu::{Mem, Reg, trap};
use cpu::arm64::reg::*;
use baseline::buffer::*;
use baseline::codegen::CondCode;
use lexer::position::Position;
use mem::ptr_width;
use object::IntArray;
use ty::MachineMode;
use vtable::VTable;

pub fn prolog(buf: &mut Buffer, stacksize: i32) {
    buf.emit_u32(stp_pre(1, REG_FP, REG_LR, REG_SP, -2));
    buf.emit_u32(add_reg(1, REG_FP, REG_SP, REG_ZERO));

    if stacksize > 0 {
        let scratch = get_scratch();
        load_int_const(buf, scratch, stacksize);
        buf.emit_u32(sub_reg(1, REG_SP, REG_SP, scratch));
    }
}

pub fn epilog(buf: &mut Buffer, stacksize: i32) {
    if stacksize > 0 {
        let scratch = get_scratch();
        load_int_const(buf, scratch, stacksize);
        buf.emit_u32(add_reg(1, REG_SP, REG_SP, scratch));
    }

    buf.emit_u32(add_reg(1, REG_SP, REG_FP, REG_ZERO));
    buf.emit_u32(ldp_post(1, REG_FP, REG_LR, REG_SP, 2));
    buf.emit_u32(ret());
}

pub fn direct_call(buf: &mut Buffer, ptr: *const u8) {
    let disp = buf.add_addr(ptr);
    let pos = buf.pos() as i32;

    let scratch = get_scratch();

    load_constpool(buf, REG_RESULT, disp + pos);
    br(scratch);
}

pub fn indirect_call(buf: &mut Buffer, index: u32) {
    let obj = REG_PARAMS[0];

    // REG_RESULT = [obj] (load vtable)
    load_mem(buf, MachineMode::Ptr, REG_RESULT, Mem::Base(obj, 0));

    // calculate offset of VTable entry
    let disp = VTable::offset_of_method_table() + (index as i32) * ptr_width();

    // load vtable entry
    load_mem(buf, MachineMode::Ptr, REG_RESULT, Mem::Base(REG_RESULT, disp));

    // call *REG_RESULT
    buf.emit_u32(blr(REG_RESULT));
}

pub fn load_array_elem(buf: &mut Buffer, mode: MachineMode, dest: Reg, array: Reg, index: Reg) {
    assert!(mode == MachineMode::Int32);

    load_mem(buf, mode, dest, Mem::Index(array, index, mode.size(), IntArray::offset_of_data()));
}

pub fn store_array_elem(buf: &mut Buffer, mode: MachineMode, array: Reg, index: Reg, value: Reg) {
    assert!(mode == MachineMode::Int32);

    store_mem(buf, MachineMode::Int32,
              Mem::Index(array, index, 4, IntArray::offset_of_data()), value);
}

pub fn test_if_nil_bailout(buf: &mut Buffer, pos: Position, reg: Reg) {
    cmp_reg(buf, MachineMode::Ptr, reg, reg);

    let lbl = buf.create_label();
    jump_if(buf, CondCode::Zero, lbl);
    buf.emit_bailout(lbl, trap::NIL, pos);
}

pub fn test_if_nil(buf: &mut Buffer, reg: Reg) -> Label {
    cmp_reg(buf, MachineMode::Ptr, reg, reg);

    let lbl = buf.create_label();
    jump_if(buf, CondCode::Zero, lbl);

    lbl
}

pub fn set(buf: &mut Buffer, dest: Reg, op: CondCode) {
    buf.emit_u32(cmp_imm(0, dest, 0, 0));
    buf.emit_u32(cset(0, dest, CondCode::NotEqual.into()));
}

pub fn cmp_mem(buf: &mut Buffer, mode: MachineMode, mem: Mem, rhs: Reg) {
    unimplemented!();
}

pub fn cmp_mem_imm(buf: &mut Buffer, mode: MachineMode, mem: Mem, imm: i32) {
    unimplemented!();
}

pub fn cmp_reg(buf: &mut Buffer, mode: MachineMode, lhs: Reg, rhs: Reg) {
    buf.emit_u32(cmp_shreg(size_flag(mode), lhs, rhs, Shift::LSL, 0));
}

pub fn test_and_jump_if(buf: &mut Buffer, cond: CondCode, reg: Reg, lbl: Label) {
    assert!(cond == CondCode::Zero || cond == CondCode::NonZero);

    unimplemented!();
}

pub fn jump_if(buf: &mut Buffer, cond: CondCode, lbl: Label) {
    unimplemented!();
}

pub fn jump(buf: &mut Buffer, lbl: Label) {
    unimplemented!();
}

pub fn int_div(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    buf.emit_u32(sdiv(0, dest, lhs, rhs));
}

pub fn int_mod(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    unimplemented!();
}

pub fn int_mul(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    buf.emit_u32(mul(0, dest, lhs, rhs));
}

pub fn int_add(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    buf.emit_u32(add_reg(0, dest, lhs, rhs));
}

pub fn int_sub(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    buf.emit_u32(sub_reg(0, dest, lhs, rhs));
}

pub fn int_shl(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    buf.emit_u32(lslv(0, dest, lhs, reg));
}

pub fn int_or(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    buf.emit_u32(orr_shreg(0, dest, lhs, rhs, Shift::LSL, 0));
}

pub fn int_and(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    buf.emit_u32(and_shreg(0, dest, lhs, rhs, Shift::LSL, 0));
}

pub fn int_xor(buf: &mut Buffer, dest: Reg, lhs: Reg, rhs: Reg) {
    buf.emit_u32(eor_shreg(0, dest, lhs, rhs, Shift::LSL, 0));
}

pub fn check_index_out_of_bounds(buf: &mut Buffer, pos: Position, array: Reg,
                                 index: Reg, temp: Reg) {
    unimplemented!();
}

pub fn load_nil(buf: &mut Buffer, dest: Reg) {
    unimplemented!();
}

pub fn load_mem(buf: &mut Buffer, mode: MachineMode, dest: Reg, mem: Mem) {
    unimplemented!();
}

pub fn store_mem(buf: &mut Buffer, mode: MachineMode, mem: Mem, src: Reg) {
    unimplemented!();
}

pub fn copy_reg(buf: &mut Buffer, mode: MachineMode, dest: Reg, src: Reg) {
    buf.emit_u32(orr_shreg(0, dest, REG_ZERO, src, Shift::LSL, 0));
}

pub fn load_constpool(buf: &mut Buffer, dest: Reg, disp: i32) {
    unimplemented!();
}

pub fn call_reg(buf: &mut Buffer, reg: Reg) {
    buf.emit_u32(blr(reg));
}

pub fn debug(buf: &mut Buffer) {
    unimplemented!();
}

pub fn load_int_const(buf: &mut Buffer, dest: Reg, imm: i32) {
    let register_size = 32;
    let imm = imm as i64 as u64;

    if fits_movz(imm, register_size) {
        buf.emit_u32(movz(0, dest, imm as u32, 0));

    } else if fits_movn(imm, register_size) {
        buf.emit_u32(movn(0, dest, imm as u32, 0));

    } else {
        unimplemented!();
    }
}

pub fn load_true(buf: &mut Buffer, dest: Reg) {
    buf.emit_u32(movz(0, dest, 1, 0));
}

pub fn load_false(buf: &mut Buffer, dest: Reg) {
    buf.emit_u32(movz(0, dest, 0, 0));
}

pub fn int_neg(buf: &mut Buffer, dest: Reg, src: Reg) {
    buf.emit_u32(sub_reg(0, dest, REG_ZERO, src));
}

pub fn int_not(buf: &mut Buffer, dest: Reg, src: Reg) {
    buf.emit_u32(orn_shreg(0, dest, REG_ZERO, src, Shift::LSL, 0));
}

pub fn bool_not(buf: &mut Buffer, dest: Reg, src: Reg) {
    let scratch = get_scratch();

    buf.emit_u32(movz(0, scratch, 1, 0));
    buf.emit_u32(eor_shreg(0, dest, src, scratch, Shift::LSL, 0));
    buf.emit_u32(uxtb(dest, dest));
}

fn size_flag(mode: MachineMode) -> u32 {
    match mode {
        MachineMode::Int8 | MachineMode::Int32 => 0,
        MachineMode::Ptr => 1,
    }
}

fn get_scratch() -> Reg {
    SCRATCH[0]
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # DFA compiler
//!
//! The DFA compiler converts NDFAs into DFAs, using a DFA builder.
//!

use std::marker::PhantomData;

use super::dfa_builder::*;
use super::state_machine::*;

///
/// Builds a deterministic finite automaton from a NDFA
///
pub struct DfaCompiler<InputSymbol: PartialOrd, OutputSymbol, DfaType, Ndfa: StateMachine<InputSymbol, OutputSymbol>, Builder: DfaBuilder<InputSymbol, OutputSymbol, DfaType>> {
    /// State machine that is to be compiled
    ndfa: Ndfa,

    /// Builder where the state machine should be generated
    builder: Builder,

    // Phantom data to poke Rust's type system (it's too dumb to see that InputSymbol is used in both Ndfa and Builder there via the type constraint)
    #[allow(dead_code)]
    phantom: (PhantomData<InputSymbol>, PhantomData<OutputSymbol>, PhantomData<DfaType>)
}

impl<InputSymbol: PartialOrd, OutputSymbol, DfaType, Ndfa: StateMachine<InputSymbol, OutputSymbol>, Builder: DfaBuilder<InputSymbol, OutputSymbol, DfaType>>
    DfaCompiler<InputSymbol, OutputSymbol, DfaType, Ndfa, Builder> {
    ///
    /// Builds a DFA using an NDFA and a builder
    ///
    pub fn build(ndfa: Ndfa, builder: Builder) -> DfaType {
        let compiler = DfaCompiler::new(ndfa, builder);
        compiler.compile()
    }

    ///
    /// Creates a new DFA compiler using a particular builder and NDFA
    ///
    pub fn new(ndfa: Ndfa, builder: Builder) -> Self {
        DfaCompiler { ndfa: ndfa, builder: builder, phantom: (PhantomData, PhantomData, PhantomData) }
    }

    ///
    /// Compiles the NDFA into a DFA
    ///
    pub fn compile(self) -> DfaType {
        unimplemented!()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use super::super::regular_pattern::*;
    use super::super::state_machine::*;
    use super::super::symbol_range_dfa::*;

    #[test]
    fn can_create_compiler() {
        let ndfa     = "abc".into_pattern().to_ndfa("success");
        let builder  = SymbolRangeDfaBuilder::new();

        DfaCompiler::new(ndfa, builder);
    }

    #[test]
    fn can_build_dfa() {
        let ndfa     = "abc".into_pattern().to_ndfa("success");
        let builder  = SymbolRangeDfaBuilder::new();

        DfaCompiler::build(ndfa, builder);
    }
}
<commit_msg>Implement the functions needed to merge states and transitions<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # DFA compiler
//!
//! The DFA compiler converts NDFAs into DFAs, using a DFA builder.
//!

use std::marker::PhantomData;
use std::collections::HashSet;
use std::collections::HashMap;
use std::iter::*;

use super::dfa_builder::*;
use super::state_machine::*;

///
/// Builds a deterministic finite automaton from a NDFA
///
pub struct DfaCompiler<InputSymbol: Ord+Clone, OutputSymbol, DfaType, Ndfa: StateMachine<InputSymbol, OutputSymbol>, Builder: DfaBuilder<InputSymbol, OutputSymbol, DfaType>> {
    /// State machine that is to be compiled
    ndfa: Ndfa,

    /// Builder where the state machine should be generated
    builder: Builder,

    // Phantom data to poke Rust's type system (it's too dumb to see that InputSymbol is used in both Ndfa and Builder there via the type constraint)
    #[allow(dead_code)]
    phantom: (PhantomData<InputSymbol>, PhantomData<OutputSymbol>, PhantomData<DfaType>)
}

/// Represents a state in the DFA (one or more states from the source)
#[derive(Eq, PartialEq, Hash, Clone)]
struct DfaState {
    source_states: Vec<StateId>
}

impl DfaState {
    /// Creates a DFA state from a set of source states
    fn create(source_states: Vec<StateId>) -> DfaState {
        let mut set = HashSet::new();
        for state in source_states {
            set.insert(state);
        }

        DfaState { source_states: Vec::from_iter(set.into_iter()) }
    }

    /// Removes any duplicate states from source_states
    fn dedupe(&mut self) {
        self.source_states.sort();
        self.source_states.dedup();
    }
}

/// Represents the transitions for a source state
struct DfaTransitions<InputSymbol> {
    transitions: Vec<(InputSymbol, DfaState)>
}

impl<InputSymbol: Ord+Clone> DfaTransitions<InputSymbol> {
    /// Goes through the transitions in the object and merges the states of any with the same symbol
    fn merge_states(&mut self) {
        if self.transitions.len() > 0 {
            // Order the transitions so that if two transitions have the same input symbol, they are neighbours
            self.transitions.sort_by(|a, b| {
                let &(ref symbol_a, _) = a;
                let &(ref symbol_b, _) = b;

                symbol_a.cmp(symbol_b)
            });

            // For any transition that has a duplicate state, combine it with the previous state
            let mut new_transitions = vec![];
            new_transitions.push(self.transitions[0].clone());

            for transit_idx in 1..self.transitions.len() {
                let len          = new_transitions.len();
                let this_transit = &mut self.transitions[transit_idx];

                if new_transitions[len-1].0 == this_transit.0 {
                    // Same symbol: expand this state
                    new_transitions[len-1].1.source_states.append(&mut this_transit.1.source_states);
                } else {
                    // Different symbol: add new state
                    new_transitions.push(this_transit.clone());
                }
            }

            // Ensure all of the states are sorted and de-duplicated
            for transit in &mut new_transitions {
                transit.1.dedupe();
            }

            // Update the transitions
            self.transitions = new_transitions;
        }
    }
}

impl<InputSymbol: Ord+Clone, OutputSymbol, DfaType, Ndfa: StateMachine<InputSymbol, OutputSymbol>, Builder: DfaBuilder<InputSymbol, OutputSymbol, DfaType>>
    DfaCompiler<InputSymbol, OutputSymbol, DfaType, Ndfa, Builder> {
    ///
    /// Builds a DFA using an NDFA and a builder
    ///
    pub fn build(ndfa: Ndfa, builder: Builder) -> DfaType {
        let compiler = DfaCompiler::new(ndfa, builder);
        compiler.compile()
    }

    ///
    /// Creates a new DFA compiler using a particular builder and NDFA
    ///
    pub fn new(ndfa: Ndfa, builder: Builder) -> Self {
        DfaCompiler { ndfa: ndfa, builder: builder, phantom: (PhantomData, PhantomData, PhantomData) }
    }

    ///
    /// Compiles the NDFA into a DFA
    ///
    pub fn compile(self) -> DfaType {
        // TODO: Convert overlapping symbol ranges to non-overlapping symbol ranges
        // This is only needed for input symbol types that implement SymbolRange

        // Work out the state mapping for each input symbol
        let mut states: HashMap<DfaState, DfaTransitions<InputSymbol>> = HashMap::new();
        let mut to_process  = vec![];

        // All state machines have state 0 as their starting state
        let state_zero = DfaState::create(vec![0]);

        states.insert(state_zero.clone(), DfaTransitions { transitions: vec![] });
        to_process.push(state_zero);

        // Assign final IDs to the states

        // TODO: Build the DFA

        unimplemented!()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use super::super::regular_pattern::*;
    use super::super::state_machine::*;
    use super::super::symbol_range_dfa::*;

    #[test]
    fn can_create_compiler() {
        let ndfa     = "abc".into_pattern().to_ndfa("success");
        let builder  = SymbolRangeDfaBuilder::new();

        DfaCompiler::new(ndfa, builder);
    }

    #[test]
    fn can_build_dfa() {
        let ndfa     = "abc".into_pattern().to_ndfa("success");
        let builder  = SymbolRangeDfaBuilder::new();

        DfaCompiler::build(ndfa, builder);
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Read};
use std::fmt;

use {AsyncRead, AsyncWrite};
use codec::Decoder;
use framed::Fuse;

use futures::{Async, AsyncSink, Poll, Stream, Sink, StartSend};
use bytes::BytesMut;

/// Trait of helper objects to write out messages as bytes, for use with
/// `FramedWrite`.
pub trait Encoder {
    /// The type of items consumed by the `Encoder`
    type Item;

    /// The type of encoding errors.
    ///
    /// `FramedWrite` requires `Encoder`s errors to implement `From<io::Error>`
    /// in the interest letting it return `Error`s directly.
    type Error: From<io::Error>;

    /// Encodes a frame into the buffer provided.
    ///
    /// This method will encode `msg` into the byte buffer provided by `buf`.
    /// The `buf` provided is an internal buffer of the `Framed` instance and
    /// will be written out when possible.
    fn encode(&mut self, item: Self::Item, dst: &mut BytesMut)
              -> Result<(), Self::Error>;
}

/// A `Sink` of frames encoded to an `AsyncWrite`.
pub struct FramedWrite<T, E> {
    inner: FramedWrite2<Fuse<T, E>>,
}

pub struct FramedWrite2<T> {
    inner: T,
    buffer: BytesMut,
}

const INITIAL_CAPACITY: usize = 8 * 1024;
const BACKPRESSURE_BOUNDARY: usize = INITIAL_CAPACITY;

impl<T, E> FramedWrite<T, E>
    where T: AsyncWrite,
          E: Encoder,
{
    /// Creates a new `FramedWrite` with the given `encoder`.
    pub fn new(inner: T, encoder: E) -> FramedWrite<T, E> {
        FramedWrite {
            inner: framed_write2(Fuse(inner, encoder)),
        }
    }
}

impl<T, E> FramedWrite<T, E> {
    /// Returns a reference to the underlying I/O stream wrapped by
    /// `FramedWrite`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_ref(&self) -> &T {
        &self.inner.inner.0
    }

    /// Returns a mutable reference to the underlying I/O stream wrapped by
    /// `FramedWrite`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner.inner.0
    }

    /// Consumes the `FramedWrite`, returning its underlying I/O stream.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_inner(self) -> T {
        self.inner.inner.0
    }

    /// Returns a reference to the underlying decoder.
    pub fn encoder(&self) -> &E {
        &self.inner.inner.1
    }

    /// Returns a mutable reference to the underlying decoder.
    pub fn encoder_mut(&mut self) -> &mut E {
        &mut self.inner.inner.1
    }
}

impl<T, E> Sink for FramedWrite<T, E>
    where T: AsyncWrite,
          E: Encoder,
{
    type SinkItem = E::Item;
    type SinkError = E::Error;

    fn start_send(&mut self, item: E::Item) -> StartSend<E::Item, E::Error> {
        self.inner.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.inner.poll_complete()
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        Ok(try!(self.inner.close()))
    }
}

impl<T, D> Stream for FramedWrite<T, D>
    where T: Stream,
{
    type Item = T::Item;
    type Error = T::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.inner.inner.0.poll()
    }
}

impl<T, U> fmt::Debug for FramedWrite<T, U>
    where T: fmt::Debug,
          U: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("FramedWrite")
         .field("inner", &self.inner.get_ref().0)
         .field("encoder", &self.inner.get_ref().1)
         .field("buffer", &self.inner.buffer)
         .finish()
    }
}

// ===== impl FramedWrite2 =====

pub fn framed_write2<T>(inner: T) -> FramedWrite2<T> {
    FramedWrite2 {
        inner: inner,
        buffer: BytesMut::with_capacity(INITIAL_CAPACITY),
    }
}

pub fn framed_write2_with_buffer<T>(inner: T, mut buf: BytesMut) -> FramedWrite2<T> {
    if buf.capacity() < INITIAL_CAPACITY {
        let bytes_to_reserve = INITIAL_CAPACITY - buf.capacity();
        buf.reserve(bytes_to_reserve);
    }
    FramedWrite2 {
        inner: inner,
        buffer: buf,
    }
}

impl<T> FramedWrite2<T> {
    pub fn get_ref(&self) -> &T {
        &self.inner
    }

    pub fn into_inner(self) -> T {
        self.inner
    }

    pub fn into_parts(self) -> (T, BytesMut) {
        (self.inner, self.buffer)
    }

    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner
    }
}

impl<T> Sink for FramedWrite2<T>
    where T: AsyncWrite + Encoder,
{
    type SinkItem = T::Item;
    type SinkError = T::Error;

    fn start_send(&mut self, item: T::Item) -> StartSend<T::Item, T::Error> {
        // If the buffer is already over 8KiB, then attempt to flush it. If after flushing it's
        // *still* over 8KiB, then apply backpressure (reject the send).
        if self.buffer.len() >= BACKPRESSURE_BOUNDARY {
            try!(self.poll_complete());

            if self.buffer.len() >= BACKPRESSURE_BOUNDARY {
                return Ok(AsyncSink::NotReady(item));
            }
        }

        try!(self.inner.encode(item, &mut self.buffer));

        Ok(AsyncSink::Ready)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        trace!("flushing framed transport");

        while !self.buffer.is_empty() {
            trace!("writing; remaining={}", self.buffer.len());

            let n = try_nb!(self.inner.write(&self.buffer));

            if n == 0 {
                return Err(io::Error::new(io::ErrorKind::WriteZero, "failed to
                                          write frame to transport").into());
            }

            // TODO: Add a way to `bytes` to do this w/o returning the drained
            // data.
            let _ = self.buffer.split_to(n);
        }

        // Try flushing the underlying IO
        try_nb!(self.inner.flush());

        trace!("framed transport flushed");
        return Ok(Async::Ready(()));
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        try_ready!(self.poll_complete());
        Ok(try!(self.inner.shutdown()))
    }
}

impl<T: Decoder> Decoder for FramedWrite2<T> {
    type Item = T::Item;
    type Error = T::Error;

    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<T::Item>, T::Error> {
        self.inner.decode(src)
    }

    fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<T::Item>, T::Error> {
        self.inner.decode_eof(src)
    }
}

impl<T: Read> Read for FramedWrite2<T> {
    fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
        self.inner.read(dst)
    }
}

impl<T: AsyncRead> AsyncRead for FramedWrite2<T> {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        self.inner.prepare_uninitialized_buffer(buf)
    }
}
<commit_msg>Fix variable names in doc comment from `encode` (#69)<commit_after>use std::io::{self, Read};
use std::fmt;

use {AsyncRead, AsyncWrite};
use codec::Decoder;
use framed::Fuse;

use futures::{Async, AsyncSink, Poll, Stream, Sink, StartSend};
use bytes::BytesMut;

/// Trait of helper objects to write out messages as bytes, for use with
/// `FramedWrite`.
pub trait Encoder {
    /// The type of items consumed by the `Encoder`
    type Item;

    /// The type of encoding errors.
    ///
    /// `FramedWrite` requires `Encoder`s errors to implement `From<io::Error>`
    /// in the interest letting it return `Error`s directly.
    type Error: From<io::Error>;

    /// Encodes a frame into the buffer provided.
    ///
    /// This method will encode `item` into the byte buffer provided by `dst`.
    /// The `dst` provided is an internal buffer of the `Framed` instance and
    /// will be written out when possible.
    fn encode(&mut self, item: Self::Item, dst: &mut BytesMut)
              -> Result<(), Self::Error>;
}

/// A `Sink` of frames encoded to an `AsyncWrite`.
pub struct FramedWrite<T, E> {
    inner: FramedWrite2<Fuse<T, E>>,
}

pub struct FramedWrite2<T> {
    inner: T,
    buffer: BytesMut,
}

const INITIAL_CAPACITY: usize = 8 * 1024;
const BACKPRESSURE_BOUNDARY: usize = INITIAL_CAPACITY;

impl<T, E> FramedWrite<T, E>
    where T: AsyncWrite,
          E: Encoder,
{
    /// Creates a new `FramedWrite` with the given `encoder`.
    pub fn new(inner: T, encoder: E) -> FramedWrite<T, E> {
        FramedWrite {
            inner: framed_write2(Fuse(inner, encoder)),
        }
    }
}

impl<T, E> FramedWrite<T, E> {
    /// Returns a reference to the underlying I/O stream wrapped by
    /// `FramedWrite`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_ref(&self) -> &T {
        &self.inner.inner.0
    }

    /// Returns a mutable reference to the underlying I/O stream wrapped by
    /// `FramedWrite`.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner.inner.0
    }

    /// Consumes the `FramedWrite`, returning its underlying I/O stream.
    ///
    /// Note that care should be taken to not tamper with the underlying stream
    /// of data coming in as it may corrupt the stream of frames otherwise
    /// being worked with.
    pub fn into_inner(self) -> T {
        self.inner.inner.0
    }

    /// Returns a reference to the underlying decoder.
    pub fn encoder(&self) -> &E {
        &self.inner.inner.1
    }

    /// Returns a mutable reference to the underlying decoder.
    pub fn encoder_mut(&mut self) -> &mut E {
        &mut self.inner.inner.1
    }
}

impl<T, E> Sink for FramedWrite<T, E>
    where T: AsyncWrite,
          E: Encoder,
{
    type SinkItem = E::Item;
    type SinkError = E::Error;

    fn start_send(&mut self, item: E::Item) -> StartSend<E::Item, E::Error> {
        self.inner.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.inner.poll_complete()
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        Ok(try!(self.inner.close()))
    }
}

impl<T, D> Stream for FramedWrite<T, D>
    where T: Stream,
{
    type Item = T::Item;
    type Error = T::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.inner.inner.0.poll()
    }
}

impl<T, U> fmt::Debug for FramedWrite<T, U>
    where T: fmt::Debug,
          U: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("FramedWrite")
         .field("inner", &self.inner.get_ref().0)
         .field("encoder", &self.inner.get_ref().1)
         .field("buffer", &self.inner.buffer)
         .finish()
    }
}

// ===== impl FramedWrite2 =====

pub fn framed_write2<T>(inner: T) -> FramedWrite2<T> {
    FramedWrite2 {
        inner: inner,
        buffer: BytesMut::with_capacity(INITIAL_CAPACITY),
    }
}

pub fn framed_write2_with_buffer<T>(inner: T, mut buf: BytesMut) -> FramedWrite2<T> {
    if buf.capacity() < INITIAL_CAPACITY {
        let bytes_to_reserve = INITIAL_CAPACITY - buf.capacity();
        buf.reserve(bytes_to_reserve);
    }
    FramedWrite2 {
        inner: inner,
        buffer: buf,
    }
}

impl<T> FramedWrite2<T> {
    pub fn get_ref(&self) -> &T {
        &self.inner
    }

    pub fn into_inner(self) -> T {
        self.inner
    }

    pub fn into_parts(self) -> (T, BytesMut) {
        (self.inner, self.buffer)
    }

    pub fn get_mut(&mut self) -> &mut T {
        &mut self.inner
    }
}

impl<T> Sink for FramedWrite2<T>
    where T: AsyncWrite + Encoder,
{
    type SinkItem = T::Item;
    type SinkError = T::Error;

    fn start_send(&mut self, item: T::Item) -> StartSend<T::Item, T::Error> {
        // If the buffer is already over 8KiB, then attempt to flush it. If after flushing it's
        // *still* over 8KiB, then apply backpressure (reject the send).
        if self.buffer.len() >= BACKPRESSURE_BOUNDARY {
            try!(self.poll_complete());

            if self.buffer.len() >= BACKPRESSURE_BOUNDARY {
                return Ok(AsyncSink::NotReady(item));
            }
        }

        try!(self.inner.encode(item, &mut self.buffer));

        Ok(AsyncSink::Ready)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        trace!("flushing framed transport");

        while !self.buffer.is_empty() {
            trace!("writing; remaining={}", self.buffer.len());

            let n = try_nb!(self.inner.write(&self.buffer));

            if n == 0 {
                return Err(io::Error::new(io::ErrorKind::WriteZero, "failed to
                                          write frame to transport").into());
            }

            // TODO: Add a way to `bytes` to do this w/o returning the drained
            // data.
            let _ = self.buffer.split_to(n);
        }

        // Try flushing the underlying IO
        try_nb!(self.inner.flush());

        trace!("framed transport flushed");
        return Ok(Async::Ready(()));
    }

    fn close(&mut self) -> Poll<(), Self::SinkError> {
        try_ready!(self.poll_complete());
        Ok(try!(self.inner.shutdown()))
    }
}

impl<T: Decoder> Decoder for FramedWrite2<T> {
    type Item = T::Item;
    type Error = T::Error;

    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<T::Item>, T::Error> {
        self.inner.decode(src)
    }

    fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<T::Item>, T::Error> {
        self.inner.decode_eof(src)
    }
}

impl<T: Read> Read for FramedWrite2<T> {
    fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
        self.inner.read(dst)
    }
}

impl<T: AsyncRead> AsyncRead for FramedWrite2<T> {
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
        self.inner.prepare_uninitialized_buffer(buf)
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

use beacon_node::ProductionBeaconNode;
use clap::{App, Arg, ArgMatches};
use clap_utils;
use env_logger::{Builder, Env};
use environment::EnvironmentBuilder;
use eth2_testnet_config::HARDCODED_TESTNET;
use slog::{crit, info, warn};
use std::path::PathBuf;
use std::process::exit;
use types::EthSpec;
use validator_client::ProductionValidatorClient;

pub const DEFAULT_DATA_DIR: &str = ".lighthouse";
pub const CLIENT_CONFIG_FILENAME: &str = "beacon-node.toml";
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";

fn main() {
    // Debugging output for libp2p and external crates.
    Builder::from_env(Env::default()).init();

    // Parse the CLI parameters.
    let matches = App::new("Lighthouse")
        .version(crate_version!())
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about(
            "Ethereum 2.0 client by Sigma Prime. Provides a full-featured beacon \
             node, a validator client and utilities for managing validator accounts.",
        )
        .arg(
            Arg::with_name("spec")
                .short("s")
                .long("spec")
                .value_name("TITLE")
                .help("Specifies the default eth2 spec type.")
                .takes_value(true)
                .possible_values(&["mainnet", "minimal", "interop"])
                .global(true)
                .default_value("mainnet"),
        )
        .arg(
            Arg::with_name("logfile")
                .long("logfile")
                .value_name("FILE")
                .help(
                    "File path where output will be written. Default file logging format is JSON.",
                )
                .takes_value(true),
        )
        .arg(
            Arg::with_name("log-format")
                .long("log-format")
                .value_name("FORMAT")
                .help("Specifies the format used for logging.")
                .possible_values(&["JSON"])
                .takes_value(true),
        )
        .arg(
            Arg::with_name("debug-level")
                .long("debug-level")
                .value_name("LEVEL")
                .help("The verbosity level for emitting logs.")
                .takes_value(true)
                .possible_values(&["info", "debug", "trace", "warn", "error", "crit"])
                .default_value("info"),
        )
        .arg(
            Arg::with_name("datadir")
                .long("datadir")
                .short("d")
                .value_name("DIR")
                .global(true)
                .help("Data directory for lighthouse keys and databases.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("testnet-dir")
                .short("t")
                .long("testnet-dir")
                .value_name("DIR")
                .help(
                    "Path to directory containing eth2_testnet specs. Defaults to \
                      a hard-coded Lighthouse testnet. Only effective if there is no \
                      existing database.",
                )
                .takes_value(true)
                .global(true),
        )
        .subcommand(beacon_node::cli_app())
        .subcommand(validator_client::cli_app())
        .subcommand(account_manager::cli_app())
        .get_matches();

    macro_rules! run_with_spec {
        ($env_builder: expr) => {
            run($env_builder, &matches)
        };
    }

    let result = match matches.value_of("spec") {
        Some("minimal") => run_with_spec!(EnvironmentBuilder::minimal()),
        Some("mainnet") => run_with_spec!(EnvironmentBuilder::mainnet()),
        Some("interop") => run_with_spec!(EnvironmentBuilder::interop()),
        spec => {
            // This path should be unreachable due to slog having a `default_value`
            unreachable!("Unknown spec configuration: {:?}", spec);
        }
    };

    // `std::process::exit` does not run destructors so we drop manually.
    drop(matches);

    // Return the appropriate error code.
    match result {
        Ok(()) => exit(0),
        Err(e) => {
            eprintln!("{}", e);
            drop(e);
            exit(1)
        }
    }
}

fn run<E: EthSpec>(
    environment_builder: EnvironmentBuilder<E>,
    matches: &ArgMatches,
) -> Result<(), String> {
    let debug_level = matches
        .value_of("debug-level")
        .ok_or_else(|| "Expected --debug-level flag".to_string())?;

    let log_format = matches.value_of("log-format");
    let eth2_testnet_config =
        clap_utils::parse_testnet_dir_with_hardcoded_default(matches, "testnet-dir")?;

    let mut environment = environment_builder
        .async_logger(debug_level, log_format)?
        .multi_threaded_tokio_runtime()?
        .eth2_testnet_config(eth2_testnet_config)?
        .build()?;

    let log = environment.core_context().log;

    if let Some(log_path) = matches.value_of("logfile") {
        let path = log_path
            .parse::<PathBuf>()
            .map_err(|e| format!("Failed to parse log path: {:?}", e))?;
        environment.log_to_json_file(path, debug_level, log_format)?;
    }

    if std::mem::size_of::<usize>() != 8 {
        crit!(
            log,
            "Lighthouse only supports 64bit CPUs";
            "detected" => format!("{}bit", std::mem::size_of::<usize>() * 8)
        );
        return Err("Invalid CPU architecture".into());
    }

    // Note: the current code technically allows for starting a beacon node _and_ a validator
    // client at the same time.
    //
    // Whilst this is possible, the mutual-exclusivity of `clap` sub-commands prevents it from
    // actually happening.
    //
    // Creating a command which can run both might be useful future works.

    if let Some(sub_matches) = matches.subcommand_matches("account_manager") {
        // Pass the entire `environment` to the account manager so it can run blocking operations.
        account_manager::run(sub_matches, environment)?;

        // Exit as soon as account manager returns control.
        return Ok(());
    };

    warn!(
        log,
        "Ethereum 2.0 is pre-release. This software is experimental."
    );

    if !matches.is_present("testnet-dir") {
        info!(
            log,
            "Using default testnet";
            "default" => HARDCODED_TESTNET
        )
    }

    let beacon_node = if let Some(sub_matches) = matches.subcommand_matches("beacon_node") {
        let runtime_context = environment.core_context();

        let beacon = environment
            .runtime()
            .block_on(ProductionBeaconNode::new_from_cli(
                runtime_context,
                sub_matches,
            ))
            .map_err(|e| format!("Failed to start beacon node: {}", e))?;

        Some(beacon)
    } else {
        None
    };

    let validator_client = if let Some(sub_matches) = matches.subcommand_matches("validator_client")
    {
        let runtime_context = environment.core_context();

        let mut validator = environment
            .runtime()
            .block_on(ProductionValidatorClient::new_from_cli(
                runtime_context,
                sub_matches,
            ))
            .map_err(|e| format!("Failed to init validator client: {}", e))?;

        environment.core_context().runtime_handle.enter(|| {
            validator
                .start_service()
                .map_err(|e| format!("Failed to start validator client service: {}", e))
        })?;

        Some(validator)
    } else {
        None
    };

    if beacon_node.is_none() && validator_client.is_none() {
        crit!(log, "No subcommand supplied. See --help .");
        return Err("No subcommand supplied.".into());
    }

    // Block this thread until Crtl+C is pressed.
    environment.block_until_ctrl_c()?;

    info!(log, "Shutting down..");

    drop(beacon_node);
    drop(validator_client);

    // Shutdown the environment once all tasks have completed.
    Ok(environment.shutdown_on_idle())
}
<commit_msg>Drop runtime after task completion (#1196)<commit_after>#[macro_use]
extern crate clap;

use beacon_node::ProductionBeaconNode;
use clap::{App, Arg, ArgMatches};
use clap_utils;
use env_logger::{Builder, Env};
use environment::EnvironmentBuilder;
use eth2_testnet_config::HARDCODED_TESTNET;
use slog::{crit, info, warn};
use std::path::PathBuf;
use std::process::exit;
use types::EthSpec;
use validator_client::ProductionValidatorClient;

pub const DEFAULT_DATA_DIR: &str = ".lighthouse";
pub const CLIENT_CONFIG_FILENAME: &str = "beacon-node.toml";
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";

fn main() {
    // Debugging output for libp2p and external crates.
    Builder::from_env(Env::default()).init();

    // Parse the CLI parameters.
    let matches = App::new("Lighthouse")
        .version(crate_version!())
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about(
            "Ethereum 2.0 client by Sigma Prime. Provides a full-featured beacon \
             node, a validator client and utilities for managing validator accounts.",
        )
        .arg(
            Arg::with_name("spec")
                .short("s")
                .long("spec")
                .value_name("TITLE")
                .help("Specifies the default eth2 spec type.")
                .takes_value(true)
                .possible_values(&["mainnet", "minimal", "interop"])
                .global(true)
                .default_value("mainnet"),
        )
        .arg(
            Arg::with_name("logfile")
                .long("logfile")
                .value_name("FILE")
                .help(
                    "File path where output will be written. Default file logging format is JSON.",
                )
                .takes_value(true),
        )
        .arg(
            Arg::with_name("log-format")
                .long("log-format")
                .value_name("FORMAT")
                .help("Specifies the format used for logging.")
                .possible_values(&["JSON"])
                .takes_value(true),
        )
        .arg(
            Arg::with_name("debug-level")
                .long("debug-level")
                .value_name("LEVEL")
                .help("The verbosity level for emitting logs.")
                .takes_value(true)
                .possible_values(&["info", "debug", "trace", "warn", "error", "crit"])
                .default_value("info"),
        )
        .arg(
            Arg::with_name("datadir")
                .long("datadir")
                .short("d")
                .value_name("DIR")
                .global(true)
                .help("Data directory for lighthouse keys and databases.")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("testnet-dir")
                .short("t")
                .long("testnet-dir")
                .value_name("DIR")
                .help(
                    "Path to directory containing eth2_testnet specs. Defaults to \
                      a hard-coded Lighthouse testnet. Only effective if there is no \
                      existing database.",
                )
                .takes_value(true)
                .global(true),
        )
        .subcommand(beacon_node::cli_app())
        .subcommand(validator_client::cli_app())
        .subcommand(account_manager::cli_app())
        .get_matches();

    macro_rules! run_with_spec {
        ($env_builder: expr) => {
            run($env_builder, &matches)
        };
    }

    let result = match matches.value_of("spec") {
        Some("minimal") => run_with_spec!(EnvironmentBuilder::minimal()),
        Some("mainnet") => run_with_spec!(EnvironmentBuilder::mainnet()),
        Some("interop") => run_with_spec!(EnvironmentBuilder::interop()),
        spec => {
            // This path should be unreachable due to slog having a `default_value`
            unreachable!("Unknown spec configuration: {:?}", spec);
        }
    };

    // `std::process::exit` does not run destructors so we drop manually.
    drop(matches);

    // Return the appropriate error code.
    match result {
        Ok(()) => exit(0),
        Err(e) => {
            eprintln!("{}", e);
            drop(e);
            exit(1)
        }
    }
}

fn run<E: EthSpec>(
    environment_builder: EnvironmentBuilder<E>,
    matches: &ArgMatches,
) -> Result<(), String> {
    let debug_level = matches
        .value_of("debug-level")
        .ok_or_else(|| "Expected --debug-level flag".to_string())?;

    let log_format = matches.value_of("log-format");
    let eth2_testnet_config =
        clap_utils::parse_testnet_dir_with_hardcoded_default(matches, "testnet-dir")?;

    let mut environment = environment_builder
        .async_logger(debug_level, log_format)?
        .multi_threaded_tokio_runtime()?
        .eth2_testnet_config(eth2_testnet_config)?
        .build()?;

    let log = environment.core_context().log;

    if let Some(log_path) = matches.value_of("logfile") {
        let path = log_path
            .parse::<PathBuf>()
            .map_err(|e| format!("Failed to parse log path: {:?}", e))?;
        environment.log_to_json_file(path, debug_level, log_format)?;
    }

    if std::mem::size_of::<usize>() != 8 {
        crit!(
            log,
            "Lighthouse only supports 64bit CPUs";
            "detected" => format!("{}bit", std::mem::size_of::<usize>() * 8)
        );
        return Err("Invalid CPU architecture".into());
    }

    // Note: the current code technically allows for starting a beacon node _and_ a validator
    // client at the same time.
    //
    // Whilst this is possible, the mutual-exclusivity of `clap` sub-commands prevents it from
    // actually happening.
    //
    // Creating a command which can run both might be useful future works.

    if let Some(sub_matches) = matches.subcommand_matches("account_manager") {
        // Pass the entire `environment` to the account manager so it can run blocking operations.
        account_manager::run(sub_matches, environment)?;

        // Exit as soon as account manager returns control.
        return Ok(());
    };

    warn!(
        log,
        "Ethereum 2.0 is pre-release. This software is experimental."
    );

    if !matches.is_present("testnet-dir") {
        info!(
            log,
            "Using default testnet";
            "default" => HARDCODED_TESTNET
        )
    }

    let beacon_node = if let Some(sub_matches) = matches.subcommand_matches("beacon_node") {
        let runtime_context = environment.core_context();

        let beacon = environment
            .runtime()
            .block_on(ProductionBeaconNode::new_from_cli(
                runtime_context,
                sub_matches,
            ))
            .map_err(|e| format!("Failed to start beacon node: {}", e))?;

        Some(beacon)
    } else {
        None
    };

    let validator_client = if let Some(sub_matches) = matches.subcommand_matches("validator_client")
    {
        let runtime_context = environment.core_context();

        let mut validator = environment
            .runtime()
            .block_on(ProductionValidatorClient::new_from_cli(
                runtime_context,
                sub_matches,
            ))
            .map_err(|e| format!("Failed to init validator client: {}", e))?;

        environment.core_context().runtime_handle.enter(|| {
            validator
                .start_service()
                .map_err(|e| format!("Failed to start validator client service: {}", e))
        })?;

        Some(validator)
    } else {
        None
    };

    if beacon_node.is_none() && validator_client.is_none() {
        crit!(log, "No subcommand supplied. See --help .");
        return Err("No subcommand supplied.".into());
    }

    // Block this thread until Crtl+C is pressed.
    environment.block_until_ctrl_c()?;

    info!(log, "Shutting down..");

    drop(beacon_node);
    drop(validator_client);

    // Shutdown the environment once all tasks have completed.
    // Due to a bug in tokio: https://github.com/tokio-rs/tokio/issues/2314
    // the `shutdown_on_idle()` will wait until the entire timeout. For the time-being, we shutdown as soon as all
    // threads have completed, by dropping the runtime.
    //Ok(environment.shutdown_on_idle())
    Ok(())
}
<|endoftext|>


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

use model::Model;

pub struct Classifier {
    models: HashMap<String, Model>
}

impl Classifier {
    pub fn new() -> Classifier {
        Classifier { models: HashMap::new() }
    }

    pub fn train(&mut self, text: &str, name: &str) {
        let model = Model::build_from_text(text);
        self.models.insert(name.to_string(), model);
    }

    pub fn classify(&self, text: &str) -> &String {
        let model = Model::build_from_text(text);
        let (name, _) = self.models
            .iter()
            .min_by_key(|&(_, other_model)| model.compare(other_model))
            .unwrap();
        name
    }
}
<commit_msg>Turn the model list in Classifier into a vector<commit_after>use model::Model;

pub struct Classifier {
    models: Vec<(String, Model)>
}

impl Classifier {
    pub fn new() -> Classifier {
        Classifier { models: Vec::new() }
    }

    pub fn train(&mut self, text: &str, name: &str) {
        let model = Model::build_from_text(text);
        self.models.push((name.to_string(), model));
    }

    pub fn classify(&self, text: &str) -> &String {
        let model = Model::build_from_text(text);
        let &(ref name, _) = self.models
            .iter()
            .min_by_key(|&&(_, ref other_model)| model.compare(other_model))
            .unwrap();
        name
    }
}
<|endoftext|>