<commit_before>use std::collections::BTreeMap;
use rustc_serialize::json::{Json, ToJson};
pub use optional::Optional;
pub use sensors::{SensorTemplate, Sensors};
pub use sensors::{TemperatureSensor, PeopleNowPresentSensor};

#[derive(Debug, Clone)]
pub struct Location {
    pub address: Optional<String>,
    pub lat: f64,
    pub lon: f64,
}

#[derive(Debug, Clone)]
pub struct Spacefed {
    pub spacenet: bool,
    pub spacesaml: bool,
    pub spacephone: bool,
}

#[derive(Debug, Clone)]
pub struct Icon {
    pub open: String,
    pub close: String,
}

#[derive(Debug, Clone)]
pub struct State {
    pub open: Option<bool>,
    pub lastchange: Optional<u64>,
    pub trigger_person: Optional<String>,
    pub message: Optional<String>,
    pub icon: Optional<Icon>,
}

#[derive(Debug, Clone)]
pub struct Event {
    pub name: String,
    pub _type: String,
    pub timestamp: u64,
    pub extra: Optional<String>,
}

#[derive(Debug, Clone)]
pub struct Contact {
    pub irc: Optional<String>,
    pub twitter: Optional<String>,
    pub foursquare: Optional<String>,
    pub email: Optional<String>,
}

#[derive(Debug, Clone)]
pub struct Feed {
    pub _type: Optional<String>,
    pub url: String,
}

#[derive(Debug, Clone)]
pub struct Feeds {
    pub blog: Optional<Feed>,
    pub wiki: Optional<Feed>,
    pub calendar: Optional<Feed>,
    pub flickr: Optional<Feed>,
}

#[derive(Debug, Clone)]
pub struct Cache {
    pub schedule: String,
}

#[derive(Debug, Clone)]
pub struct RadioShow {
    pub name: String,
    pub url: String,
    pub _type: String,
    pub start: String,
    pub end: String,
}

/// The main Space API status object.
#[derive(Debug, Clone)]
pub struct Status {

    // Hackerspace properties
    pub api: &'static str,
    pub space: String,
    pub logo: String,
    pub url: String,
    pub location: Location,
    pub contact: Contact,

    // Hackerspace features / projects
    pub spacefed: Optional<Spacefed>,
    pub projects: Optional<Vec<String>>,
    pub cam: Optional<Vec<String>>,
    pub feeds: Optional<Feeds>,
    pub events: Optional<Vec<Event>>,
    pub radio_show: Optional<Vec<RadioShow>>,

    // SpaceAPI internal usage
    pub cache: Optional<Cache>,
    pub issue_report_channels: Vec<String>,

    // Mutable data
    pub state: State,
    pub sensors: Optional<Sensors>,
}

impl Status {

    /// Create a new Status object with only the minimum amount of fields.
    pub fn new(space: String, logo: String, url: String, location: Location, contact: Contact, issue_report_channels: Vec<String>) -> Status {
        Status {
            api: "0.13",
            space: space,
            logo: logo,
            url: url,
            location: location,
            contact: contact,

            spacefed: Optional::Absent,
            projects: Optional::Absent,
            cam: Optional::Absent,
            feeds: Optional::Absent,
            events: Optional::Absent,
            radio_show: Optional::Absent,

            cache: Optional::Absent,
            issue_report_channels: issue_report_channels,

            state: State {
                open: None,
                lastchange: Optional::Absent,
                trigger_person: Optional::Absent,
                message: Optional::Absent,
                icon: Optional::Absent,
            },
            sensors: Optional::Absent,
        }
    }

}

impl ToJson for Status {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();

        d.insert("api".to_string(), self.api.to_json());
        d.insert("space".to_string(), self.space.to_json());
        d.insert("logo".to_string(), self.logo.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("location".to_string(), self.location.to_json());
        d.insert("contact".to_string(), self.contact.to_json());

        self.spacefed.as_ref().map_or((), |v| { d.insert("spacefed".to_string(), v.to_json()); } );
        self.projects.as_ref().map_or((), |v| { d.insert("projects".to_string(), v.to_json()); });
        self.cam.as_ref().map_or((), |v| { d.insert("cam".to_string(), v.to_json()); });
        self.feeds.as_ref().map_or((), |v| { d.insert("feeds".to_string(), v.to_json()); });
        self.events.as_ref().map_or((), |v| { d.insert("events".to_string(), v.to_json()); });
        self.radio_show.as_ref().map_or((), |v| { d.insert("radio_show".to_string(), v.to_json()); });

        self.cache.as_ref().map_or((), |v| { d.insert("cache".to_string(), v.to_json()); });
        d.insert("issue_report_channels".to_string(), self.issue_report_channels.to_json());

        d.insert("state".to_string(), self.state.to_json());
        self.sensors.as_ref().map_or((), |v| { d.insert("sensors".to_string(), v.to_json()); });

        Json::Object(d)
    }
}

impl ToJson for Location {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("lat".to_string(), self.lat.to_json());
        d.insert("lon".to_string(), self.lon.to_json());
        match self.address {
            Optional::Value(ref address) => {
                d.insert("address".to_string(), address.to_json());
            },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for Spacefed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("spacenet".to_string(), self.spacenet.to_json());
        d.insert("spacesaml".to_string(), self.spacesaml.to_json());
        d.insert("spacephone".to_string(), self.spacephone.to_json());
        Json::Object(d)
    }
}

impl ToJson for Icon {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        d.insert("close".to_string(), self.close.to_json());
        Json::Object(d)
    }
}

impl ToJson for State {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        self.lastchange.as_ref().map_or((), |v| { d.insert("lastchange".to_string(), v.to_json()); });
        self.trigger_person.as_ref().map_or((), |v| { d.insert("trigger_person".to_string(), v.to_json()); });
        self.message.as_ref().map_or((), |v| { d.insert("message".to_string(), v.to_json()); });
        self.icon.as_ref().map_or((), |v| { d.insert("icon".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("timestamp".to_string(), self.timestamp.to_json());
        self.extra.as_ref().map_or((), |v| { d.insert("extra".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Contact {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.irc.as_ref().map_or((), |v| { d.insert("irc".to_string(), v.to_json()); });
        self.twitter.as_ref().map_or((), |v| { d.insert("twitter".to_string(), v.to_json()); });
        self.foursquare.as_ref().map_or((), |v| { d.insert("foursquare".to_string(), v.to_json()); });
        self.email.as_ref().map_or((), |v| { d.insert("email".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("url".to_string(), self.url.to_json());
        self._type.as_ref().map_or((), |v| { d.insert("type".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feeds {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.blog.as_ref().map_or((), |v| { d.insert("blog".to_string(), v.to_json()); });
        self.wiki.as_ref().map_or((), |v| { d.insert("wiki".to_string(), v.to_json()); });
        self.calendar.as_ref().map_or((), |v| { d.insert("calendar".to_string(), v.to_json()); });
        self.flickr.as_ref().map_or((), |v| { d.insert("flickr".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Cache {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("schedule".to_string(), self.schedule.to_json());
        Json::Object(d)
    }
}

impl ToJson for RadioShow {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("start".to_string(), self.start.to_json()); d.insert("end".to_string(), self.end.to_json());
        Json::Object(d)
    }
}
<commit_msg>api: Use the Into<T> trait to pass strings to the constructor<commit_after>use std::collections::BTreeMap;
use rustc_serialize::json::{Json, ToJson};
pub use optional::Optional;
pub use sensors::{SensorTemplate, Sensors};
pub use sensors::{TemperatureSensor, PeopleNowPresentSensor};

#[derive(Debug, Clone)]
pub struct Location {
    pub address: Optional<String>,
    pub lat: f64,
    pub lon: f64,
}

#[derive(Debug, Clone)]
pub struct Spacefed {
    pub spacenet: bool,
    pub spacesaml: bool,
    pub spacephone: bool,
}

#[derive(Debug, Clone)]
pub struct Icon {
    pub open: String,
    pub close: String,
}

#[derive(Debug, Clone)]
pub struct State {
    pub open: Option<bool>,
    pub lastchange: Optional<u64>,
    pub trigger_person: Optional<String>,
    pub message: Optional<String>,
    pub icon: Optional<Icon>,
}

#[derive(Debug, Clone)]
pub struct Event {
    pub name: String,
    pub _type: String,
    pub timestamp: u64,
    pub extra: Optional<String>,
}

#[derive(Debug, Clone)]
pub struct Contact {
    pub irc: Optional<String>,
    pub twitter: Optional<String>,
    pub foursquare: Optional<String>,
    pub email: Optional<String>,
}

#[derive(Debug, Clone)]
pub struct Feed {
    pub _type: Optional<String>,
    pub url: String,
}

#[derive(Debug, Clone)]
pub struct Feeds {
    pub blog: Optional<Feed>,
    pub wiki: Optional<Feed>,
    pub calendar: Optional<Feed>,
    pub flickr: Optional<Feed>,
}

#[derive(Debug, Clone)]
pub struct Cache {
    pub schedule: String,
}

#[derive(Debug, Clone)]
pub struct RadioShow {
    pub name: String,
    pub url: String,
    pub _type: String,
    pub start: String,
    pub end: String,
}

/// The main Space API status object.
#[derive(Debug, Clone)]
pub struct Status {

    // Hackerspace properties
    pub api: &'static str,
    pub space: String,
    pub logo: String,
    pub url: String,
    pub location: Location,
    pub contact: Contact,

    // Hackerspace features / projects
    pub spacefed: Optional<Spacefed>,
    pub projects: Optional<Vec<String>>,
    pub cam: Optional<Vec<String>>,
    pub feeds: Optional<Feeds>,
    pub events: Optional<Vec<Event>>,
    pub radio_show: Optional<Vec<RadioShow>>,

    // SpaceAPI internal usage
    pub cache: Optional<Cache>,
    pub issue_report_channels: Vec<String>,

    // Mutable data
    pub state: State,
    pub sensors: Optional<Sensors>,
}

impl Status {

    /// Create a new Status object with only the minimum amount of fields.
    pub fn new<S: Into<String>>(space: S, logo: S, url: S, location: Location, contact: Contact, issue_report_channels: Vec<String>) -> Status {
        Status {
            api: "0.13",
            space: space.into(),
            logo: logo.into(),
            url: url.into(),
            location: location,
            contact: contact,

            spacefed: Optional::Absent,
            projects: Optional::Absent,
            cam: Optional::Absent,
            feeds: Optional::Absent,
            events: Optional::Absent,
            radio_show: Optional::Absent,

            cache: Optional::Absent,
            issue_report_channels: issue_report_channels,

            state: State {
                open: None,
                lastchange: Optional::Absent,
                trigger_person: Optional::Absent,
                message: Optional::Absent,
                icon: Optional::Absent,
            },
            sensors: Optional::Absent,
        }
    }

}

impl ToJson for Status {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();

        d.insert("api".to_string(), self.api.to_json());
        d.insert("space".to_string(), self.space.to_json());
        d.insert("logo".to_string(), self.logo.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("location".to_string(), self.location.to_json());
        d.insert("contact".to_string(), self.contact.to_json());

        self.spacefed.as_ref().map_or((), |v| { d.insert("spacefed".to_string(), v.to_json()); } );
        self.projects.as_ref().map_or((), |v| { d.insert("projects".to_string(), v.to_json()); });
        self.cam.as_ref().map_or((), |v| { d.insert("cam".to_string(), v.to_json()); });
        self.feeds.as_ref().map_or((), |v| { d.insert("feeds".to_string(), v.to_json()); });
        self.events.as_ref().map_or((), |v| { d.insert("events".to_string(), v.to_json()); });
        self.radio_show.as_ref().map_or((), |v| { d.insert("radio_show".to_string(), v.to_json()); });

        self.cache.as_ref().map_or((), |v| { d.insert("cache".to_string(), v.to_json()); });
        d.insert("issue_report_channels".to_string(), self.issue_report_channels.to_json());

        d.insert("state".to_string(), self.state.to_json());
        self.sensors.as_ref().map_or((), |v| { d.insert("sensors".to_string(), v.to_json()); });

        Json::Object(d)
    }
}

impl ToJson for Location {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("lat".to_string(), self.lat.to_json());
        d.insert("lon".to_string(), self.lon.to_json());
        match self.address {
            Optional::Value(ref address) => {
                d.insert("address".to_string(), address.to_json());
            },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for Spacefed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("spacenet".to_string(), self.spacenet.to_json());
        d.insert("spacesaml".to_string(), self.spacesaml.to_json());
        d.insert("spacephone".to_string(), self.spacephone.to_json());
        Json::Object(d)
    }
}

impl ToJson for Icon {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        d.insert("close".to_string(), self.close.to_json());
        Json::Object(d)
    }
}

impl ToJson for State {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("open".to_string(), self.open.to_json());
        self.lastchange.as_ref().map_or((), |v| { d.insert("lastchange".to_string(), v.to_json()); });
        self.trigger_person.as_ref().map_or((), |v| { d.insert("trigger_person".to_string(), v.to_json()); });
        self.message.as_ref().map_or((), |v| { d.insert("message".to_string(), v.to_json()); });
        self.icon.as_ref().map_or((), |v| { d.insert("icon".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Event {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("timestamp".to_string(), self.timestamp.to_json());
        self.extra.as_ref().map_or((), |v| { d.insert("extra".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Contact {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.irc.as_ref().map_or((), |v| { d.insert("irc".to_string(), v.to_json()); });
        self.twitter.as_ref().map_or((), |v| { d.insert("twitter".to_string(), v.to_json()); });
        self.foursquare.as_ref().map_or((), |v| { d.insert("foursquare".to_string(), v.to_json()); });
        self.email.as_ref().map_or((), |v| { d.insert("email".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feed {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("url".to_string(), self.url.to_json());
        self._type.as_ref().map_or((), |v| { d.insert("type".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Feeds {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.blog.as_ref().map_or((), |v| { d.insert("blog".to_string(), v.to_json()); });
        self.wiki.as_ref().map_or((), |v| { d.insert("wiki".to_string(), v.to_json()); });
        self.calendar.as_ref().map_or((), |v| { d.insert("calendar".to_string(), v.to_json()); });
        self.flickr.as_ref().map_or((), |v| { d.insert("flickr".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for Cache {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("schedule".to_string(), self.schedule.to_json());
        Json::Object(d)
    }
}

impl ToJson for RadioShow {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("name".to_string(), self.name.to_json());
        d.insert("url".to_string(), self.url.to_json());
        d.insert("type".to_string(), self._type.to_json());
        d.insert("start".to_string(), self.start.to_json()); d.insert("end".to_string(), self.end.to_json());
        Json::Object(d)
    }
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2018 Guillaume Gomez
//

extern crate sysinfo;

#[cfg(not(windows))]
use sysinfo::ProcessExt;
use sysinfo::SystemExt;

#[test]
fn test_process() {
    let mut s = sysinfo::System::new();
    assert_eq!(s.get_processes().len(), 0);
    s.refresh_processes();
    assert!(s.get_processes().len() != 0);
    #[cfg(not(windows))]
    assert!(s
        .get_processes()
        .values()
        .any(|p| p.exe().to_str().unwrap_or_else(|| "").len() != 0));
}

#[test]
fn test_process_refresh() {
    let mut s = sysinfo::System::new();
    assert_eq!(s.get_processes().len(), 0);
    s.refresh_process(sysinfo::get_current_pid().expect("failed to get current pid"));
    assert_eq!(
        s.get_process(sysinfo::get_current_pid().expect("failed to get current pid"))
            .is_some(),
        true
    );
}
<commit_msg>Tests for command line (if not windows)<commit_after>//
// Sysinfo
//
// Copyright (c) 2018 Guillaume Gomez
//

extern crate sysinfo;

#[cfg(not(windows))]
use sysinfo::ProcessExt;
use sysinfo::SystemExt;

#[test]
fn test_process() {
    let mut s = sysinfo::System::new();
    assert_eq!(s.get_processes().len(), 0);
    s.refresh_processes();
    assert!(s.get_processes().len() != 0);
    #[cfg(not(windows))]
    assert!(s
        .get_processes()
        .values()
        .any(|p| p.exe().to_str().unwrap_or_else(|| "").len() != 0));
}

#[test]
fn test_process_refresh() {
    let mut s = sysinfo::System::new();
    assert_eq!(s.get_processes().len(), 0);
    s.refresh_process(sysinfo::get_current_pid().expect("failed to get current pid"));
    assert_eq!(
        s.get_process(sysinfo::get_current_pid().expect("failed to get current pid"))
            .is_some(),
        true
    );
}

#[test]
#[cfg(windows)]
fn test_get_cmd_line() {}

#[test]
#[cfg(not(windows))]
fn test_get_cmd_line() {
    let p = std::process::Command::new("timeout")
        .arg("3")
        .arg("ping")
        .arg("localhost")
        .spawn()
        .unwrap();
    let mut s = sysinfo::System::new();
    s.refresh_processes();
    let process = s.get_process(p.id() as sysinfo::Pid).unwrap();
    assert_eq!(process.cmd(), &["timeout", "3", "ping", "localhost"]);
}
<|endoftext|>


<commit_before>//! Tests for containers.rs

#[cfg(test)]
mod tests {
    use super::super::containers::*;
    use std::rc::*;
    use rustwlc::handle::*;
    use rustwlc::types::*;

    #[cfg(test)]
    /// Sets up a root node with 10 workspaces
    fn root_setup() -> Node {
        let mut root = Container::new_root();
        let mut output = Container::new_output(&mut root, WlcView::root().as_output());
        for _ in 0..10 {
            Container::new_workspace(&mut output);
        }
        root
    }

    #[test]
    #[should_panic(expected = "Can only be one root")]
    /// Test to make sure that there can be only one root node
    fn test_one_root() {
        let _root = Container::new_root();
        // Should panic
        let _root2 = Container::new_root();
        // remove when we fix it
        panic!("Can only be one root");
    }

    #[test]
    /// Verify that root node has required properties
    fn root_validity_test() {
        let main: Node = Container::new_root();
        let root = main.borrow();
        // Make sure it starts with no children (but can have children)
        assert_eq!(root.get_children().unwrap().len(), 0);
        // This is the tippity-top of the tree
        assert!(root.get_parent().is_none());
        assert_eq!(root.get_type(), ContainerType::Root);
        // Should this be true? It makes sense, but it might cause complications
        // so we'll go with false for now
        assert!(! root.is_focused());
        // Root is parent of all nodes, including itself
        assert!(root.is_parent_of(main.clone()));
        // Root is not a child of anything, except for itself
        // NOTE Add more test when we have more container types
        assert!(root.is_child_of(main.clone()));
        assert!(root.get_position().is_none());
        assert!(root.get_dimensions().is_none());
        assert!(root.is_root());
    }

    #[test]
    fn workspace_validity_test() {
        let root = root_setup();
        assert_eq!(root.borrow().get_children().unwrap().len(), 1);
        let output = &mut root.borrow().get_children().unwrap().to_vec()[0];
        let output_copy = Rc::make_mut(&mut output.clone()).clone().into_inner();
        for container_ in output.borrow().get_children().unwrap().to_vec() {
            // Workspaces start out empty
            let mut container = container_.borrow_mut();
            assert_eq!(container.get_children().unwrap().len(), 0);
            let container_copy = Rc::make_mut(&mut container.get_parent().unwrap().clone()).clone().into_inner();
            assert_eq!(container_copy, output_copy);
            // NOTE add test for add_child
            assert_eq!(container.get_type(), ContainerType::Workspace);
            assert!(! container.is_focused());
            // NOTE add test for remove_child_at
            assert!(! container.get_visibility());
            container.set_visibility(true);
            assert!(container.get_visibility());
            container.set_visibility(false);
            assert!(! container.get_visibility());
            // NOTE Add these once they can be set properly
            //assert_eq!(container.get_dimensions().unwrap(), (0,0));
            //assert_eq!(container.get_position().unwrap(), (0,0));
            // NOTE add test for is_parent_of
            assert!(container.is_child_of(root.clone()));
            assert!(! container.is_root());
            assert_eq!(container.get_parent_by_type(ContainerType::Root).unwrap(), root);
        }
    }

    #[test]
    fn container_validity_test() {
        let root = root_setup();
        for output in root.borrow().get_children().unwrap().to_vec() {
            let mut workspace_ = &mut output.borrow().get_children().unwrap().to_vec()[0];
            let workspace_copy = Rc::make_mut(&mut workspace_.clone()).clone().into_inner();
            let container_ = Container::new_container(&mut workspace_, Layout::Horizontal);
            let mut container = container_.borrow_mut();
            // No children
            assert_eq!(container.get_children().unwrap().len(), 0);
            // Is the only child of the workspace
            let container_parent = Rc::make_mut(&mut container.get_parent().unwrap().clone()).clone().into_inner();
            assert_eq!(workspace_copy, container_parent);
            // drop our copy of container here, because otherwise it panics at
            // run time. Another way to do this is at the beginning, but this is
            // a good test of what we need to do to stay dynamic
            drop(container);
            // This new workspace will now be the outer one, the old workspace is now on the inside
            let outer_container = Container::new_container(&mut container_.clone(), Layout::Horizontal);
            container = container_.borrow_mut();
            assert_eq!(outer_container.borrow().get_children().unwrap().len(), 1);
            assert_eq!(container.get_children().unwrap().len(), 0);
            let self_as_child = outer_container.borrow().get_children().unwrap()[0].clone();
            println!("here");
            drop(container);
            assert_eq!(*self_as_child.borrow(), *outer_container.borrow());
            println!("here");
            let container = container_.borrow();
            assert_eq!(container.get_type(), ContainerType::Container);
            println!("here");
            drop(container);
            let container2 = container_.borrow();
            assert!(container2.is_parent_of(outer_container.clone()));
            drop(container2);
            let mut container = container_.borrow_mut();
            // We also need to drop our copy of the container here when checking
            // if we are a child of the container, since we have to borrow the
            // container right here again in order to check if it's the parent.
            //
            // Again, this is only an "issue" because we are borrow_mut for
            // such a long period of time
            drop(container);
            assert!(outer_container.borrow().is_child_of(container_.clone()));
            container = container_.borrow_mut();
            assert!(! container.is_focused());
            container.set_visibility(true);
            assert!(container.get_visibility());
            container.set_visibility(false);
            assert!(! container.get_visibility());
            // NOTE add these once they can be set properly
            //assert_eq!(container.get_dimensions().unwrap(), (0,0));
            //assert_eq!(container.get_position().unwrap(), (0,0));
            assert!(container.is_child_of(root.clone()));
            assert!(! container.is_root());
            assert_eq!(container.get_parent_by_type(ContainerType::Workspace).unwrap(), *workspace_);
            assert_eq!(container.get_parent_by_type(ContainerType::Root).unwrap(), root);
        }
    }

    #[test]
    fn view_validity_test() {
        let root = root_setup();
        let output = &root.borrow().get_children().unwrap().to_vec()[0];
        for mut workspace_ in output.borrow().get_children().unwrap().to_vec() {
            let mut container_ = Container::new_container(&mut workspace_, Layout::Horizontal);
            // hack to give it a size and origin point.
            let view_hack = WlcView::root();
            view_hack.set_geometry(EDGE_NONE, &Geometry { origin: Point { x: 0, y: 0}, size: Size { w: 0, h: 0}});
            let view = Container::new_view(&mut container_, view_hack);
            assert_eq!(view.borrow().get_parent().unwrap(), container_);
            // Add child test
            // The view was added as a sibling, so it's not a child of the container
            assert_eq!(container_.borrow().get_children().unwrap().len(), 0);
            view.borrow_mut().add_sibling(container_.clone()).unwrap();
            assert_eq!(container_.borrow().get_children().unwrap().len(), 1);
        }
    }

    #[test]
    #[should_panic(expect = "Cannot add child to a view")]
    fn ensure_views_cant_have_children_test() {
        let root = root_setup();
        let mut workspace = root.borrow_mut().get_children().unwrap().to_vec()[0].clone();
        let view = Container::new_view(&mut workspace, WlcView::root());
        view.borrow_mut().add_child(workspace).unwrap();
    }

    #[test]
    fn remove_container_test() {
        let root = root_setup();
        let output = &mut root.borrow().get_children().unwrap().to_vec()[0];
        let workspace = &mut output.borrow().get_children().unwrap().to_vec()[0];
        let container = Container::new_container(workspace, Layout::Horizontal);

        let container_ref = Rc::downgrade(&workspace.borrow().get_children().unwrap()[0].clone());
        // Still points to the container
        assert!(container_ref.clone().upgrade().is_some());
        // removes workspace's reference to it
        container.borrow().remove_container().unwrap();
        // We still can see it, so it's still alive
        assert!(container_ref.clone().upgrade().is_some());
        // drop our reference to it
        drop(container);
        assert!(! container_ref.clone().upgrade().is_some());
    }

    #[test]
    #[should_panic(expect = "Cannot remove root container")]
    fn ensure_root_container_unremovable_test() {
        let root = root_setup();
        root.borrow_mut().remove_container().expect("Cannot remove root container");
    }

    #[test]
    #[should_panic(expect = "Cannot remove root container")]
    fn ensure_workspace_container_unremovable_test() {
        let root = root_setup();
        let workspace = root.borrow().get_children().unwrap()[0].clone();
        workspace.borrow_mut().remove_container().expect("Cannot remove root container");
    }

    #[test]
    #[should_panic(expect = "Only workspaces can be added to the root node")]
    /// Tests to make sure only workspaces can be children of the top node
    fn root_workspace_only() {
        let root = root_setup();
        let container = &mut root.borrow().get_children().unwrap().to_vec()[0];
        Container::new_workspace(container);
    }

    #[test]
    #[should_panic(expect = "Only containers can be children of a workspace")]
    /// Tests to ensure that only containers can be the children of a workspace
    fn only_containers_for_workspace_children_test() {
        let root = root_setup();
        let output = &root.borrow().get_children().unwrap().to_vec()[0];
        let container = output.borrow().get_children().unwrap()[0].clone();
        container.borrow_mut().add_child(container.clone()).unwrap();
    }

    #[test]
    /// Tests that you can have a root with some workspaces, that the workspaces
    /// can be removed, and that you can add simple containers to the
    /// workspaces. (Does not test views)
    fn basic_tree_test() {
        let mut root = root_setup();
        assert_eq!(root.borrow().get_children().unwrap().len(), 1);
        let output = root.borrow().get_children().unwrap()[0].clone();
        assert_eq!(output.borrow().get_children().unwrap().len(), 10);
        // NOTE Enhance with adding containers to the workspaces
    }

}
<commit_msg>Remove printlns from layout tests<commit_after>//! Tests for containers.rs

#[cfg(test)]
mod tests {
    use super::super::containers::*;
    use std::rc::*;
    use rustwlc::handle::*;
    use rustwlc::types::*;

    #[cfg(test)]
    /// Sets up a root node with 10 workspaces
    fn root_setup() -> Node {
        let mut root = Container::new_root();
        let mut output = Container::new_output(&mut root, WlcView::root().as_output());
        for _ in 0..10 {
            Container::new_workspace(&mut output);
        }
        root
    }

    #[test]
    #[should_panic(expected = "Can only be one root")]
    /// Test to make sure that there can be only one root node
    fn test_one_root() {
        let _root = Container::new_root();
        // Should panic
        let _root2 = Container::new_root();
        // remove when we fix it
        panic!("Can only be one root");
    }

    #[test]
    /// Verify that root node has required properties
    fn root_validity_test() {
        let main: Node = Container::new_root();
        let root = main.borrow();
        // Make sure it starts with no children (but can have children)
        assert_eq!(root.get_children().unwrap().len(), 0);
        // This is the tippity-top of the tree
        assert!(root.get_parent().is_none());
        assert_eq!(root.get_type(), ContainerType::Root);
        // Should this be true? It makes sense, but it might cause complications
        // so we'll go with false for now
        assert!(! root.is_focused());
        // Root is parent of all nodes, including itself
        assert!(root.is_parent_of(main.clone()));
        // Root is not a child of anything, except for itself
        // NOTE Add more test when we have more container types
        assert!(root.is_child_of(main.clone()));
        assert!(root.get_position().is_none());
        assert!(root.get_dimensions().is_none());
        assert!(root.is_root());
    }

    #[test]
    fn workspace_validity_test() {
        let root = root_setup();
        assert_eq!(root.borrow().get_children().unwrap().len(), 1);
        let output = &mut root.borrow().get_children().unwrap().to_vec()[0];
        let output_copy = Rc::make_mut(&mut output.clone()).clone().into_inner();
        for container_ in output.borrow().get_children().unwrap().to_vec() {
            // Workspaces start out empty
            let mut container = container_.borrow_mut();
            assert_eq!(container.get_children().unwrap().len(), 0);
            let container_copy = Rc::make_mut(&mut container.get_parent().unwrap().clone()).clone().into_inner();
            assert_eq!(container_copy, output_copy);
            // NOTE add test for add_child
            assert_eq!(container.get_type(), ContainerType::Workspace);
            assert!(! container.is_focused());
            // NOTE add test for remove_child_at
            assert!(! container.get_visibility());
            container.set_visibility(true);
            assert!(container.get_visibility());
            container.set_visibility(false);
            assert!(! container.get_visibility());
            // NOTE Add these once they can be set properly
            //assert_eq!(container.get_dimensions().unwrap(), (0,0));
            //assert_eq!(container.get_position().unwrap(), (0,0));
            // NOTE add test for is_parent_of
            assert!(container.is_child_of(root.clone()));
            assert!(! container.is_root());
            assert_eq!(container.get_parent_by_type(ContainerType::Root).unwrap(), root);
        }
    }

    #[test]
    fn container_validity_test() {
        let root = root_setup();
        for output in root.borrow().get_children().unwrap().to_vec() {
            let mut workspace_ = &mut output.borrow().get_children().unwrap()[0];
            let workspace_copy = Rc::make_mut(&mut workspace_.clone()).clone().into_inner();
            let container_ = Container::new_container(&mut workspace_, Layout::Horizontal);
            let mut container = container_.borrow_mut();
            // No children
            assert_eq!(container.get_children().unwrap().len(), 0);
            // Is the only child of the workspace
            let container_parent = Rc::make_mut(&mut container.get_parent().unwrap().clone()).clone().into_inner();
            assert_eq!(workspace_copy, container_parent);
            // drop our copy of container here, because otherwise it panics at
            // run time. Another way to do this is at the beginning, but this is
            // a good test of what we need to do to stay dynamic
            drop(container);
            // This new workspace will now be the outer one, the old workspace is now on the inside
            let outer_container = Container::new_container(&mut container_.clone(), Layout::Horizontal);
            container = container_.borrow_mut();
            assert_eq!(outer_container.borrow().get_children().unwrap().len(), 1);
            assert_eq!(container.get_children().unwrap().len(), 0);
            let self_as_child = outer_container.borrow().get_children().unwrap()[0].clone();
            drop(container);
            assert_eq!(*self_as_child.borrow(), *outer_container.borrow());
            let container = container_.borrow();
            assert_eq!(container.get_type(), ContainerType::Container);
            drop(container);
            let container2 = container_.borrow();
            assert!(container2.is_parent_of(outer_container.clone()));
            drop(container2);
            let mut container = container_.borrow_mut();
            // We also need to drop our copy of the container here when checking
            // if we are a child of the container, since we have to borrow the
            // container right here again in order to check if it's the parent.
            //
            // Again, this is only an "issue" because we are borrow_mut for
            // such a long period of time
            drop(container);
            assert!(outer_container.borrow().is_child_of(container_.clone()));
            container = container_.borrow_mut();
            assert!(! container.is_focused());
            container.set_visibility(true);
            assert!(container.get_visibility());
            container.set_visibility(false);
            assert!(! container.get_visibility());
            // NOTE add these once they can be set properly
            //assert_eq!(container.get_dimensions().unwrap(), (0,0));
            //assert_eq!(container.get_position().unwrap(), (0,0));
            assert!(container.is_child_of(root.clone()));
            assert!(! container.is_root());
            assert_eq!(container.get_parent_by_type(ContainerType::Workspace).unwrap(), *workspace_);
            assert_eq!(container.get_parent_by_type(ContainerType::Root).unwrap(), root);
        }
    }

    #[test]
    fn view_validity_test() {
        let root = root_setup();
        let output = &root.borrow().get_children().unwrap().to_vec()[0];
        for mut workspace_ in output.borrow().get_children().unwrap().to_vec() {
            let mut container_ = Container::new_container(&mut workspace_, Layout::Horizontal);
            // hack to give it a size and origin point.
            let view_hack = WlcView::root();
            view_hack.set_geometry(EDGE_NONE, &Geometry { origin: Point { x: 0, y: 0}, size: Size { w: 0, h: 0}});
            let view = Container::new_view(&mut container_, view_hack);
            assert_eq!(view.borrow().get_parent().unwrap(), container_);
            // Add child test
            // The view was added as a sibling, so it's not a child of the container
            assert_eq!(container_.borrow().get_children().unwrap().len(), 0);
            view.borrow_mut().add_sibling(container_.clone()).unwrap();
            assert_eq!(container_.borrow().get_children().unwrap().len(), 1);
        }
    }

    #[test]
    #[should_panic(expect = "Cannot add child to a view")]
    fn ensure_views_cant_have_children_test() {
        let root = root_setup();
        let mut workspace = root.borrow_mut().get_children().unwrap().to_vec()[0].clone();
        let view = Container::new_view(&mut workspace, WlcView::root());
        view.borrow_mut().add_child(workspace).unwrap();
    }

    #[test]
    fn remove_container_test() {
        let root = root_setup();
        let output = &mut root.borrow().get_children().unwrap().to_vec()[0];
        let workspace = &mut output.borrow().get_children().unwrap().to_vec()[0];
        let container = Container::new_container(workspace, Layout::Horizontal);

        let container_ref = Rc::downgrade(&workspace.borrow().get_children().unwrap()[0].clone());
        // Still points to the container
        assert!(container_ref.clone().upgrade().is_some());
        // removes workspace's reference to it
        container.borrow().remove_container().unwrap();
        // We still can see it, so it's still alive
        assert!(container_ref.clone().upgrade().is_some());
        // drop our reference to it
        drop(container);
        assert!(! container_ref.clone().upgrade().is_some());
    }

    #[test]
    #[should_panic(expect = "Cannot remove root container")]
    fn ensure_root_container_unremovable_test() {
        let root = root_setup();
        root.borrow_mut().remove_container().expect("Cannot remove root container");
    }

    #[test]
    #[should_panic(expect = "Cannot remove root container")]
    fn ensure_workspace_container_unremovable_test() {
        let root = root_setup();
        let workspace = root.borrow().get_children().unwrap()[0].clone();
        workspace.borrow_mut().remove_container().expect("Cannot remove root container");
    }

    #[test]
    #[should_panic(expect = "Only workspaces can be added to the root node")]
    /// Tests to make sure only workspaces can be children of the top node
    fn root_workspace_only() {
        let root = root_setup();
        let container = &mut root.borrow().get_children().unwrap().to_vec()[0];
        Container::new_workspace(container);
    }

    #[test]
    #[should_panic(expect = "Only containers can be children of a workspace")]
    /// Tests to ensure that only containers can be the children of a workspace
    fn only_containers_for_workspace_children_test() {
        let root = root_setup();
        let output = &root.borrow().get_children().unwrap().to_vec()[0];
        let container = output.borrow().get_children().unwrap()[0].clone();
        container.borrow_mut().add_child(container.clone()).unwrap();
    }

    #[test]
    /// Tests that you can have a root with some workspaces, that the workspaces
    /// can be removed, and that you can add simple containers to the
    /// workspaces. (Does not test views)
    fn basic_tree_test() {
        let mut root = root_setup();
        assert_eq!(root.borrow().get_children().unwrap().len(), 1);
        let output = root.borrow().get_children().unwrap()[0].clone();
        assert_eq!(output.borrow().get_children().unwrap().len(), 10);
        // NOTE Enhance with adding containers to the workspaces
    }

}
<|endoftext|>


<commit_before>//! STUN message related components.
//!
//! > STUN is a client-server protocol.  It supports two types of
//! > transactions. One is a **request/response** transaction in which a
//! > client sends a **request** to a server, and the server returns a
//! > **response**. The second is an **indication** transaction in which either
//! > agent -- client or server -- sends an indication that generates no
//! > response. Both types of transactions include a transaction ID, which
//! > is a randomly selected 96-bit number.  For **request/response**
//! > transactions, this transaction ID allows the client to associate the
//! > response with the request that generated it; for indications, the
//! > transaction ID serves as a debugging aid.
//! >
//! > All STUN messages start with a fixed header that includes a method, a
//! > class, and the transaction ID.  The method indicates which of the
//! > various requests or indications this is; this specification defines
//! > just one method, Binding, but other methods are expected to be
//! > defined in other documents.  The class indicates whether this is a
//! > **request**, a **success response**, an **error response**, or an **indication**.
//! > Following the fixed header comes zero or more attributes, which are
//! > Type-Length-Value extensions that convey additional information for
//! > the specific message.
//! >
//! > [RFC 5389 -- 3. Overview of Operation](https://tools.ietf.org/html/rfc5389#section-3)
use rand;

use {Method, Attribute, Error};
use types::TransactionId;
use method::{Requestable, Indicatable};
use rfc5389::attributes::ErrorCode;
use types::TryAsRef;

pub use self::raw::{RawMessage, Class};

mod raw;

/// STUN message.
pub trait Message {
    /// STUN method type of this implementation.
    type Method: Method;

    /// STUN attribute type of this implementation.
    type Attribute: Attribute;

    /// Returns the class of this message.
    fn get_class(&self) -> Class;

    /// Returns the method of this message.
    fn get_method(&self) -> &Self::Method;

    /// Returns the transaction ID of this message.
    fn get_transaction_id(&self) -> &TransactionId;

    /// Returns the attributes of this message.
    fn get_attributes(&self) -> &[Self::Attribute];

    /// Returns the reference to the specified attribute
    /// if it exists in the attributes of this method.
    fn get_attribute(&self) -> Option<&A>
        where Self::Attribute: TryAsRef
    {
        self.get_attributes().iter().filter_map(|a| a.try_as_ref()).nth(0)
    }

    /// Tries to convert to `RawMessage`.
    fn try_to_raw(&self) -> Result<RawMessage, Error> {
        let mut raw = RawMessage::new(self.get_class(),
                                      self.get_method().as_u12(),
                                      self.get_transaction_id().clone(),
                                      Vec::new());
        for attr in self.get_attributes() {
            let raw_attr = track_try!(attr.try_to_raw(&raw));
            raw.push_attribute(raw_attr);
        }
        Ok(raw)
    }
}

/// Response message.
pub type Response<M, A> = Result<SuccessResponse<M, A>, ErrorResponse<M, A>>;
impl<M: Method, A: Attribute> Message for Response<M, A> {
    type Method = M;
    type Attribute = A;
    fn get_class(&self) -> Class {
        self.as_ref().map(|r| r.get_class()).unwrap_or_else(|r| r.get_class())
    }
    fn get_method(&self) -> &Self::Method {
        self.as_ref().map(|r| r.get_method()).unwrap_or_else(|r| r.get_method())
    }
    fn get_transaction_id(&self) -> &TransactionId {
        self.as_ref().map(|r| r.get_transaction_id()).unwrap_or_else(|r| r.get_transaction_id())
    }
    fn get_attributes(&self) -> &[Self::Attribute] {
        self.as_ref().map(|r| r.get_attributes()).unwrap_or_else(|r| r.get_attributes())
    }
}

/// Request message.
#[derive(Debug, Clone)]
pub struct Request<M, A> {
    method: M,
    transaction_id: TransactionId,
    attributes: Vec,
}
impl<M, A> Request<M, A>
    where M: Method,
          A: Attribute
{
    /// Makes a new request message.
    pub fn new(method: M) -> Self
        where M: Requestable
    {
        Request {
            method: method,
            transaction_id: rand::random(),
            attributes: Vec::new(),
        }
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn add_attribute<T: Into>(&mut self, attribute: T) -> &mut Self {
        self.attributes.push(attribute.into());
        self
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn with_attribute<T: Into>(mut self, attribute: T) -> Self {
        self.add_attribute(attribute);
        self
    }

    /// Returns the method of this message.
    pub fn method(&self) -> &M {
        &self.method
    }

    /// Returns the transaction ID of this message.
    pub fn transaction_id(&self) -> &TransactionId {
        &self.transaction_id
    }

    /// Returns the attributes of this message.
    pub fn attributes(&self) -> &[A] {
        &self.attributes
    }

    /// Converts into a success response message.
    pub fn into_success_response(self) -> SuccessResponse<M, A> {
        SuccessResponse::new(self.method, self.transaction_id)
    }

    /// Converts into an error response message.
    pub fn into_error_response(self) -> ErrorResponse<M, A> {
        ErrorResponse::new(self.method, self.transaction_id)
    }
}
impl<M: Method, A: Attribute> Message for Request<M, A> {
    type Method = M;
    type Attribute = A;
    fn get_class(&self) -> Class {
        Class::Request
    }
    fn get_method(&self) -> &Self::Method {
        self.method()
    }
    fn get_transaction_id(&self) -> &TransactionId {
        self.transaction_id()
    }
    fn get_attributes(&self) -> &[Self::Attribute] {
        self.attributes()
    }
}

/// Indication message.
#[derive(Debug, Clone)]
pub struct Indication<M, A> {
    method: M,
    transaction_id: TransactionId,
    attributes: Vec,
}
impl<M, A> Indication<M, A>
    where M: Method,
          A: Attribute
{
    /// Makes a new indication message.
    pub fn new(method: M) -> Self
        where M: Indicatable
    {
        Indication {
            method: method,
            transaction_id: rand::random(),
            attributes: Vec::new(),
        }
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn add_attribute<T: Into>(&mut self, attribute: T) -> &mut Self {
        self.attributes.push(attribute.into());
        self
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn with_attribute<T: Into>(mut self, attribute: T) -> Self {
        self.add_attribute(attribute);
        self
    }

    /// Returns the method of this message.
    pub fn method(&self) -> &M {
        &self.method
    }

    /// Returns the transaction ID of this message.
    pub fn transaction_id(&self) -> &TransactionId {
        &self.transaction_id
    }

    /// Returns the attributes of this message.
    pub fn attributes(&self) -> &[A] {
        &self.attributes
    }
}
impl<M: Method, A: Attribute> Message for Indication<M, A> {
    type Method = M;
    type Attribute = A;
    fn get_class(&self) -> Class {
        Class::Request
    }
    fn get_method(&self) -> &Self::Method {
        self.method()
    }
    fn get_transaction_id(&self) -> &TransactionId {
        self.transaction_id()
    }
    fn get_attributes(&self) -> &[Self::Attribute] {
        self.attributes()
    }
}

/// Success response message.
///
/// This is usually created by calling `Request::into_success_response` method.
#[derive(Debug, Clone)]
pub struct SuccessResponse<M, A> {
    method: M,
    transaction_id: TransactionId,
    attributes: Vec,
}
impl<M, A> SuccessResponse<M, A>
    where M: Method,
          A: Attribute
{
    fn new(method: M, transaction_id: TransactionId) -> Self {
        SuccessResponse {
            method: method,
            transaction_id: transaction_id,
            attributes: Vec::new(),
        }
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn add_attribute<T: Into>(&mut self, attribute: T) -> &mut Self {
        self.attributes.push(attribute.into());
        self
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn with_attribute<T: Into>(mut self, attribute: T) -> Self {
        self.add_attribute(attribute);
        self
    }

    /// Returns the method of this message.
    pub fn method(&self) -> &M {
        &self.method
    }

    /// Returns the transaction ID of this message.
    pub fn transaction_id(&self) -> &TransactionId {
        &self.transaction_id
    }

    /// Returns the attributes of this message.
    pub fn attributes(&self) -> &[A] {
        &self.attributes
    }
}
impl<M: Method, A: Attribute> Message for SuccessResponse<M, A> {
    type Method = M;
    type Attribute = A;
    fn get_class(&self) -> Class {
        Class::Request
    }
    fn get_method(&self) -> &Self::Method {
        self.method()
    }
    fn get_transaction_id(&self) -> &TransactionId {
        self.transaction_id()
    }
    fn get_attributes(&self) -> &[Self::Attribute] {
        self.attributes()
    }
}

/// Error response message.
///
/// This is usually created by calling `Request::into_error_response` method.
#[derive(Debug, Clone)]
pub struct ErrorResponse<M, A> {
    method: M,
    transaction_id: TransactionId,
    attributes: Vec,
}
impl<M, A> ErrorResponse<M, A>
    where M: Method,
          A: Attribute
{
    fn new(method: M, transaction_id: TransactionId) -> Self {
        ErrorResponse {
            method: method,
            transaction_id: transaction_id,
            attributes: Vec::new(),
        }
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn add_attribute<T: Into>(&mut self, attribute: T) -> &mut Self {
        self.attributes.push(attribute.into());
        self
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn with_attribute<T: Into>(mut self, attribute: T) -> Self {
        self.add_attribute(attribute);
        self
    }

    /// Adds the `ErrorCode` attribute to the tail of the attributes of this message.
    pub fn with_error_code<T: Into<ErrorCode>>(self, error_code: T) -> Self
        where A: From<ErrorCode>
    {
        self.with_attribute(error_code.into())
    }

    /// Returns the method of this message.
    pub fn method(&self) -> &M {
        &self.method
    }

    /// Returns the transaction ID of this message.
    pub fn transaction_id(&self) -> &TransactionId {
        &self.transaction_id
    }

    /// Returns the attributes of this message.
    pub fn attributes(&self) -> &[A] {
        &self.attributes
    }
}
impl<M: Method, A: Attribute> Message for ErrorResponse<M, A> {
    type Method = M;
    type Attribute = A;
    fn get_class(&self) -> Class {
        Class::Request
    }
    fn get_method(&self) -> &Self::Method {
        self.method()
    }
    fn get_transaction_id(&self) -> &TransactionId {
        self.transaction_id()
    }
    fn get_attributes(&self) -> &[Self::Attribute] {
        self.attributes()
    }
}
<commit_msg>Fix typo<commit_after>//! STUN message related components.
//!
//! > STUN is a client-server protocol.  It supports two types of
//! > transactions. One is a **request/response** transaction in which a
//! > client sends a **request** to a server, and the server returns a
//! > **response**. The second is an **indication** transaction in which either
//! > agent -- client or server -- sends an indication that generates no
//! > response. Both types of transactions include a transaction ID, which
//! > is a randomly selected 96-bit number.  For **request/response**
//! > transactions, this transaction ID allows the client to associate the
//! > response with the request that generated it; for indications, the
//! > transaction ID serves as a debugging aid.
//! >
//! > All STUN messages start with a fixed header that includes a method, a
//! > class, and the transaction ID.  The method indicates which of the
//! > various requests or indications this is; this specification defines
//! > just one method, Binding, but other methods are expected to be
//! > defined in other documents.  The class indicates whether this is a
//! > **request**, a **success response**, an **error response**, or an **indication**.
//! > Following the fixed header comes zero or more attributes, which are
//! > Type-Length-Value extensions that convey additional information for
//! > the specific message.
//! >
//! > [RFC 5389 -- 3. Overview of Operation](https://tools.ietf.org/html/rfc5389#section-3)
use rand;

use {Method, Attribute, Error};
use types::TransactionId;
use method::{Requestable, Indicatable};
use rfc5389::attributes::ErrorCode;
use types::TryAsRef;

pub use self::raw::{RawMessage, Class};

mod raw;

/// STUN message.
pub trait Message {
    /// STUN method type of this implementation.
    type Method: Method;

    /// STUN attribute type of this implementation.
    type Attribute: Attribute;

    /// Returns the class of this message.
    fn get_class(&self) -> Class;

    /// Returns the method of this message.
    fn get_method(&self) -> &Self::Method;

    /// Returns the transaction ID of this message.
    fn get_transaction_id(&self) -> &TransactionId;

    /// Returns the attributes of this message.
    fn get_attributes(&self) -> &[Self::Attribute];

    /// Returns the reference to the specified attribute
    /// if it exists in the attributes of this method.
    fn get_attribute(&self) -> Option<&A>
        where Self::Attribute: TryAsRef
    {
        self.get_attributes().iter().filter_map(|a| a.try_as_ref()).nth(0)
    }

    /// Tries to convert to `RawMessage`.
    fn try_to_raw(&self) -> Result<RawMessage, Error> {
        let mut raw = RawMessage::new(self.get_class(),
                                      self.get_method().as_u12(),
                                      self.get_transaction_id().clone(),
                                      Vec::new());
        for attr in self.get_attributes() {
            let raw_attr = track_try!(attr.try_to_raw(&raw));
            raw.push_attribute(raw_attr);
        }
        Ok(raw)
    }
}

/// Response message.
pub type Response<M, A> = Result<SuccessResponse<M, A>, ErrorResponse<M, A>>;
impl<M: Method, A: Attribute> Message for Response<M, A> {
    type Method = M;
    type Attribute = A;
    fn get_class(&self) -> Class {
        self.as_ref().map(|r| r.get_class()).unwrap_or_else(|r| r.get_class())
    }
    fn get_method(&self) -> &Self::Method {
        self.as_ref().map(|r| r.get_method()).unwrap_or_else(|r| r.get_method())
    }
    fn get_transaction_id(&self) -> &TransactionId {
        self.as_ref().map(|r| r.get_transaction_id()).unwrap_or_else(|r| r.get_transaction_id())
    }
    fn get_attributes(&self) -> &[Self::Attribute] {
        self.as_ref().map(|r| r.get_attributes()).unwrap_or_else(|r| r.get_attributes())
    }
}

/// Request message.
#[derive(Debug, Clone)]
pub struct Request<M, A> {
    method: M,
    transaction_id: TransactionId,
    attributes: Vec,
}
impl<M, A> Request<M, A>
    where M: Method,
          A: Attribute
{
    /// Makes a new request message.
    pub fn new(method: M) -> Self
        where M: Requestable
    {
        Request {
            method: method,
            transaction_id: rand::random(),
            attributes: Vec::new(),
        }
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn add_attribute<T: Into>(&mut self, attribute: T) -> &mut Self {
        self.attributes.push(attribute.into());
        self
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn with_attribute<T: Into>(mut self, attribute: T) -> Self {
        self.add_attribute(attribute);
        self
    }

    /// Returns the method of this message.
    pub fn method(&self) -> &M {
        &self.method
    }

    /// Returns the transaction ID of this message.
    pub fn transaction_id(&self) -> &TransactionId {
        &self.transaction_id
    }

    /// Returns the attributes of this message.
    pub fn attributes(&self) -> &[A] {
        &self.attributes
    }

    /// Converts into a success response message.
    pub fn into_success_response(self) -> SuccessResponse<M, A> {
        SuccessResponse::new(self.method, self.transaction_id)
    }

    /// Converts into an error response message.
    pub fn into_error_response(self) -> ErrorResponse<M, A> {
        ErrorResponse::new(self.method, self.transaction_id)
    }
}
impl<M: Method, A: Attribute> Message for Request<M, A> {
    type Method = M;
    type Attribute = A;
    fn get_class(&self) -> Class {
        Class::Request
    }
    fn get_method(&self) -> &Self::Method {
        self.method()
    }
    fn get_transaction_id(&self) -> &TransactionId {
        self.transaction_id()
    }
    fn get_attributes(&self) -> &[Self::Attribute] {
        self.attributes()
    }
}

/// Indication message.
#[derive(Debug, Clone)]
pub struct Indication<M, A> {
    method: M,
    transaction_id: TransactionId,
    attributes: Vec,
}
impl<M, A> Indication<M, A>
    where M: Method,
          A: Attribute
{
    /// Makes a new indication message.
    pub fn new(method: M) -> Self
        where M: Indicatable
    {
        Indication {
            method: method,
            transaction_id: rand::random(),
            attributes: Vec::new(),
        }
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn add_attribute<T: Into>(&mut self, attribute: T) -> &mut Self {
        self.attributes.push(attribute.into());
        self
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn with_attribute<T: Into>(mut self, attribute: T) -> Self {
        self.add_attribute(attribute);
        self
    }

    /// Returns the method of this message.
    pub fn method(&self) -> &M {
        &self.method
    }

    /// Returns the transaction ID of this message.
    pub fn transaction_id(&self) -> &TransactionId {
        &self.transaction_id
    }

    /// Returns the attributes of this message.
    pub fn attributes(&self) -> &[A] {
        &self.attributes
    }
}
impl<M: Method, A: Attribute> Message for Indication<M, A> {
    type Method = M;
    type Attribute = A;
    fn get_class(&self) -> Class {
        Class::Indication
    }
    fn get_method(&self) -> &Self::Method {
        self.method()
    }
    fn get_transaction_id(&self) -> &TransactionId {
        self.transaction_id()
    }
    fn get_attributes(&self) -> &[Self::Attribute] {
        self.attributes()
    }
}

/// Success response message.
///
/// This is usually created by calling `Request::into_success_response` method.
#[derive(Debug, Clone)]
pub struct SuccessResponse<M, A> {
    method: M,
    transaction_id: TransactionId,
    attributes: Vec,
}
impl<M, A> SuccessResponse<M, A>
    where M: Method,
          A: Attribute
{
    fn new(method: M, transaction_id: TransactionId) -> Self {
        SuccessResponse {
            method: method,
            transaction_id: transaction_id,
            attributes: Vec::new(),
        }
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn add_attribute<T: Into>(&mut self, attribute: T) -> &mut Self {
        self.attributes.push(attribute.into());
        self
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn with_attribute<T: Into>(mut self, attribute: T) -> Self {
        self.add_attribute(attribute);
        self
    }

    /// Returns the method of this message.
    pub fn method(&self) -> &M {
        &self.method
    }

    /// Returns the transaction ID of this message.
    pub fn transaction_id(&self) -> &TransactionId {
        &self.transaction_id
    }

    /// Returns the attributes of this message.
    pub fn attributes(&self) -> &[A] {
        &self.attributes
    }
}
impl<M: Method, A: Attribute> Message for SuccessResponse<M, A> {
    type Method = M;
    type Attribute = A;
    fn get_class(&self) -> Class {
        Class::SuccessResponse
    }
    fn get_method(&self) -> &Self::Method {
        self.method()
    }
    fn get_transaction_id(&self) -> &TransactionId {
        self.transaction_id()
    }
    fn get_attributes(&self) -> &[Self::Attribute] {
        self.attributes()
    }
}

/// Error response message.
///
/// This is usually created by calling `Request::into_error_response` method.
#[derive(Debug, Clone)]
pub struct ErrorResponse<M, A> {
    method: M,
    transaction_id: TransactionId,
    attributes: Vec,
}
impl<M, A> ErrorResponse<M, A>
    where M: Method,
          A: Attribute
{
    fn new(method: M, transaction_id: TransactionId) -> Self {
        ErrorResponse {
            method: method,
            transaction_id: transaction_id,
            attributes: Vec::new(),
        }
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn add_attribute<T: Into>(&mut self, attribute: T) -> &mut Self {
        self.attributes.push(attribute.into());
        self
    }

    /// Adds `attribute` to the tail of the attributes of this message.
    pub fn with_attribute<T: Into>(mut self, attribute: T) -> Self {
        self.add_attribute(attribute);
        self
    }

    /// Adds the `ErrorCode` attribute to the tail of the attributes of this message.
    pub fn with_error_code<T: Into<ErrorCode>>(self, error_code: T) -> Self
        where A: From<ErrorCode>
    {
        self.with_attribute(error_code.into())
    }

    /// Returns the method of this message.
    pub fn method(&self) -> &M {
        &self.method
    }

    /// Returns the transaction ID of this message.
    pub fn transaction_id(&self) -> &TransactionId {
        &self.transaction_id
    }

    /// Returns the attributes of this message.
    pub fn attributes(&self) -> &[A] {
        &self.attributes
    }
}
impl<M: Method, A: Attribute> Message for ErrorResponse<M, A> {
    type Method = M;
    type Attribute = A;
    fn get_class(&self) -> Class {
        Class::ErrorResponse
    }
    fn get_method(&self) -> &Self::Method {
        self.method()
    }
    fn get_transaction_id(&self) -> &TransactionId {
        self.transaction_id()
    }
    fn get_attributes(&self) -> &[Self::Attribute] {
        self.attributes()
    }
}
<|endoftext|>


<commit_before>use super::{Color, Event, Point, Rect, Renderer, Widget};

use std::sync::Arc;

extern crate orbital;

pub struct WindowRenderer<'a> {
    inner: &'a mut Box<orbital::Window>,
}

impl<'a> WindowRenderer<'a> {
    pub fn new(inner: &'a mut Box<orbital::Window>) -> WindowRenderer {
        WindowRenderer { inner: inner }
    }
}

impl<'a> Renderer for WindowRenderer<'a> {
    fn clear(&mut self, color: Color) {
        self.inner.set(orbital::Color { data: color.data });
    }

    fn char(&mut self, pos: Point, c: char, color: Color) {
        self.inner.char(pos.x, pos.y, c, orbital::Color { data: color.data });
    }

    fn rect(&mut self, rect: Rect, color: Color) {
        self.inner.rect(rect.x,
                        rect.y,
                        rect.width,
                        rect.height,
                        orbital::Color { data: color.data });
    }
}

impl<'a> Drop for WindowRenderer<'a> {
    fn drop(&mut self) {
        self.inner.sync();
    }
}

pub struct Window {
    inner: Box<orbital::Window>,
    pub widgets: Vec<Arc<Widget>>,
    pub widget_focus: usize,
    pub bg: Color,
}

impl Window {
    pub fn new(rect: Rect, title: &str) -> Box<Self> {
        Box::new(Window {
            inner: orbital::Window::new(rect.x, rect.y, rect.width, rect.height, title).unwrap(),
            widgets: Vec::new(),
            widget_focus: 0,
            bg: Color::rgb(237, 233, 227),
        })
    }

    pub fn draw(&mut self) {
        let mut renderer = WindowRenderer::new(&mut self.inner);
        renderer.clear(self.bg);
        for widget in self.widgets.iter() {
            widget.draw(&mut renderer);
        }
    }

    pub fn exec(&mut self) {
        self.draw();
        'event: while let Some(orbital_event) = self.inner.poll() {
            let mut events = Vec::new();

            match orbital_event.to_option() {
                orbital::EventOption::Mouse(mouse_event) => {
                    events.push(Event::Mouse {
                        point: Point::new(mouse_event.x, mouse_event.y),
                        left_button: mouse_event.left_button,
                        middle_button: mouse_event.middle_button,
                        right_button: mouse_event.right_button,
                    })
                }
                orbital::EventOption::Key(key_event) => {
                    if key_event.pressed {
                        match key_event.scancode {
                            orbital::K_BKSP => events.push(Event::Backspace),
                            orbital::K_DEL => events.push(Event::Delete),
                            orbital::K_HOME => events.push(Event::Home),
                            orbital::K_END => events.push(Event::End),
                            orbital::K_UP => events.push(Event::UpArrow),
                            orbital::K_DOWN => events.push(Event::DownArrow),
                            orbital::K_LEFT => events.push(Event::LeftArrow),
                            orbital::K_RIGHT => events.push(Event::RightArrow),
                            _ => {
                                match key_event.character {
                                    '\0' => (),
                                    '\x1B' => (),
                                    '\n' => events.push(Event::Enter),
                                    _ => events.push(Event::Text { c: key_event.character }),
                                }
                            }
                        }
                    }
                }
                orbital::EventOption::Quit(_quit_event) => break 'event,
                _ => (),
            };

            for event in events.iter() {
                for i in 0..self.widgets.len() {
                    if let Some(widget) = self.widgets.get(i) {
                        if widget.event(*event, self.widget_focus == i) {
                            self.widget_focus = i;
                        }
                    }
                }
            }

            self.draw();
        }
    }
}
<commit_msg>Use new events interator<commit_after>use super::{Color, Event, Point, Rect, Renderer, Widget};

use std::sync::Arc;

extern crate orbital;

pub struct WindowRenderer<'a> {
    inner: &'a mut Box<orbital::Window>,
}

impl<'a> WindowRenderer<'a> {
    pub fn new(inner: &'a mut Box<orbital::Window>) -> WindowRenderer {
        WindowRenderer { inner: inner }
    }
}

impl<'a> Renderer for WindowRenderer<'a> {
    fn clear(&mut self, color: Color) {
        self.inner.set(orbital::Color { data: color.data });
    }

    fn char(&mut self, pos: Point, c: char, color: Color) {
        self.inner.char(pos.x, pos.y, c, orbital::Color { data: color.data });
    }

    fn rect(&mut self, rect: Rect, color: Color) {
        self.inner.rect(rect.x,
                        rect.y,
                        rect.width,
                        rect.height,
                        orbital::Color { data: color.data });
    }
}

impl<'a> Drop for WindowRenderer<'a> {
    fn drop(&mut self) {
        self.inner.sync();
    }
}

pub struct Window {
    inner: Box<orbital::Window>,
    pub widgets: Vec<Arc<Widget>>,
    pub widget_focus: usize,
    pub bg: Color,
}

impl Window {
    pub fn new(rect: Rect, title: &str) -> Box<Self> {
        Box::new(Window {
            inner: orbital::Window::new(rect.x, rect.y, rect.width, rect.height, title).unwrap(),
            widgets: Vec::new(),
            widget_focus: 0,
            bg: Color::rgb(237, 233, 227),
        })
    }

    pub fn draw(&mut self) {
        let mut renderer = WindowRenderer::new(&mut self.inner);
        renderer.clear(self.bg);
        for widget in self.widgets.iter() {
            widget.draw(&mut renderer);
        }
    }

    pub fn exec(&mut self) {
        self.draw();
        'event: loop {
            let mut events = Vec::new();

            for orbital_event in self.inner.events() {
                match orbital_event.to_option() {
                    orbital::EventOption::Mouse(mouse_event) => {
                        events.push(Event::Mouse {
                            point: Point::new(mouse_event.x, mouse_event.y),
                            left_button: mouse_event.left_button,
                            middle_button: mouse_event.middle_button,
                            right_button: mouse_event.right_button,
                        })
                    }
                    orbital::EventOption::Key(key_event) => {
                        if key_event.pressed {
                            match key_event.scancode {
                                orbital::K_BKSP => events.push(Event::Backspace),
                                orbital::K_DEL => events.push(Event::Delete),
                                orbital::K_HOME => events.push(Event::Home),
                                orbital::K_END => events.push(Event::End),
                                orbital::K_UP => events.push(Event::UpArrow),
                                orbital::K_DOWN => events.push(Event::DownArrow),
                                orbital::K_LEFT => events.push(Event::LeftArrow),
                                orbital::K_RIGHT => events.push(Event::RightArrow),
                                _ => {
                                    match key_event.character {
                                        '\0' => (),
                                        '\x1B' => (),
                                        '\n' => events.push(Event::Enter),
                                        _ => events.push(Event::Text { c: key_event.character }),
                                    }
                                }
                            }
                        }
                    }
                    orbital::EventOption::Quit(_quit_event) => break 'event,
                    _ => (),
                };
            }

            for event in events.iter() {
                for i in 0..self.widgets.len() {
                    if let Some(widget) = self.widgets.get(i) {
                        if widget.event(*event, self.widget_focus == i) {
                            self.widget_focus = i;
                        }
                    }
                }
            }

            self.draw();
        }
    }
}
<|endoftext|>


<commit_before>use std::{fs, process, io, mem};
use libc;
use libc::{c_int, c_ulong, socklen_t};
use std::os::unix::io::{RawFd, AsRawFd, FromRawFd};
use std::io::{Write, Read};
use byteorder::{BigEndian, WriteBytesExt};

#[cfg(target_os = "linux")]
use libc::c_short;
#[cfg(target_os = "linux")]
use std::path;
#[cfg(target_os = "linux")]
const IFNAMSIZ: usize = 16;
#[cfg(target_os = "linux")]
const IFF_TUN: c_short = 0x0001;
#[cfg(target_os = "linux")]
const IFF_TAP: c_short = 0x0002;
#[cfg(target_os = "linux")]
const IFF_NO_PI: c_short = 0x1000;
#[cfg(target_os = "linux")]
const TUNSETIFF: c_ulong = 0x400454ca;

#[cfg(target_os = "macos")]
const AF_SYS_CONTROL: u16 = 2;
#[cfg(target_os = "macos")]
const AF_SYSTEM: u8 = 32;
#[cfg(target_os = "macos")]
const AF_INET: u8 = 2;
#[cfg(target_os = "macos")]
const PF_SYSTEM: c_int = AF_SYSTEM as c_int;
#[cfg(target_os = "macos")]
const SYSPROTO_CONTROL: c_int = 2;
#[cfg(target_os = "macos")]
const CTLIOCGINFO: c_ulong = 0xc0644e03;
#[cfg(target_os = "macos")]
const UTUN_CONTROL_NAME: &'static str = "com.apple.net.utun_control";

#[cfg(target_os = "linux")]
#[repr(C)]
pub struct ioctl_flags_data {
    pub ifr_name: [u8; IFNAMSIZ],
    pub ifr_flags: c_short,
}

#[cfg(target_os = "linux")]
#[repr(C)]
pub struct ioctl_ifindex_data {
    pub ifr_name: [u8; IFNAMSIZ],
    pub ifr_ifindex: c_int,
}

#[cfg(target_os = "macos")]
#[repr(C)]
pub struct ctl_info {
    pub ctl_id: u32,
    pub ctl_name: [u8; 96],
}

#[cfg(target_os = "macos")]
#[repr(C)]
pub struct sockaddr_ctl {
    pub sc_len: u8,
    pub sc_family: u8,
    pub ss_sysaddr: u16,
    pub sc_id: u32,
    pub sc_unit: u32,
    pub sc_reserved: [u32; 5],
}

pub struct Tun {
    handle: fs::File,
    if_name: String,
}

impl AsRawFd for Tun {
    fn as_raw_fd(&self) -> RawFd {
        self.handle.as_raw_fd()
    }
}

impl Tun {
    #[cfg(target_os = "linux")]
    pub fn create(name: u8) -> Tun {
        let path = path::Path::new("/dev/net/tun");
        let file = match fs::OpenOptions::new().read(true).write(true).open(&path) {
            Err(why) => panic!("Couldn't open device '{}': {:?}", path.display(), why),
            Ok(file) => file,
        };

        let mut req = ioctl_flags_data {
            ifr_name: {
                let mut buffer = [0u8; IFNAMSIZ];
                let full_name = format!("tun{}", name);
                buffer[..full_name.len()].clone_from_slice(full_name.as_bytes());
                buffer
            },
            ifr_flags: IFF_TUN | IFF_NO_PI,
        };

        let res = unsafe { libc::ioctl(file.as_raw_fd(), TUNSETIFF, &mut req) }; // TUNSETIFF
        if res < 0 {
            panic!("{}", io::Error::last_os_error());
        }

        let size = req.ifr_name.iter().position(|&r| r == 0).unwrap();
        Tun {
            handle: file,
            if_name: String::from_utf8(req.ifr_name[..size].to_vec()).unwrap(),
        }
    }

    #[cfg(target_os = "macos")]
    pub fn create(name: u8) -> Tun {
        let fd = unsafe { libc::socket(PF_SYSTEM, libc::SOCK_DGRAM, SYSPROTO_CONTROL) };
        if fd < 0 {
            panic!("{}", io::Error::last_os_error());
        }

        let mut info = ctl_info {
            ctl_id: 0,
            ctl_name: {
                let mut buffer = [0u8; 96];
                buffer[..UTUN_CONTROL_NAME.len()].clone_from_slice(UTUN_CONTROL_NAME.as_bytes());
                buffer
            },
        };

        let res = unsafe { libc::ioctl(fd, CTLIOCGINFO, &mut info) };
        if res < 0 {
            unsafe { libc::close(fd) };
            panic!("{}", io::Error::last_os_error());
        }

        let addr = sockaddr_ctl {
            sc_id: info.ctl_id,
            sc_len: mem::size_of::<sockaddr_ctl>() as u8,
            sc_family: AF_SYSTEM,
            ss_sysaddr: AF_SYS_CONTROL,
            sc_unit: name as u32 + 1,
            sc_reserved: [0; 5],
        };

        // If connect() is successful, a tun%d device will be created, where "%d"
        // is our sc_unit-1
        let res = unsafe {
            let addr_ptr = &addr as *const sockaddr_ctl;
            libc::connect(fd,
                          addr_ptr as *const libc::sockaddr,
                          mem::size_of_val(&addr) as socklen_t)
        };
        if res < 0 {
            unsafe { libc::close(fd) };
            panic!("{}", io::Error::last_os_error());
        }

        Tun {
            handle: unsafe { fs::File::from_raw_fd(fd) },
            if_name: format!("utun{}", name),
        }
    }

    pub fn up(&self, self_id: u8) {
        let mut status = if cfg!(target_os = "linux") {
            process::Command::new("ifconfig")
                .arg(self.if_name.clone())
                .arg(format!("10.10.10.{}/24", self_id))
                .status()
                .expect("ifconfig command failed to start")
        } else if cfg!(target_os = "macos") {
            process::Command::new("ifconfig")
                .arg(self.if_name.as_str())
                .arg(format!("10.10.10.{}", self_id))
                .arg("10.10.10.1")
                .status()
                .expect("ifconfig command failed to start")
        } else {
            unimplemented!()
        };

        assert!(status.success());

        status = if cfg!(target_os = "linux") {
            process::Command::new("ifconfig")
                .arg(self.if_name.clone())
                .arg("mtu")
                .arg("1480")
                .arg("up")
                .status()
                .expect("ifconfig command failed to start")
        } else if cfg!(target_os = "macos") {
            process::Command::new("ifconfig")
                .arg(self.if_name.as_str())
                .arg("mtu")
                .arg("1480")
                .arg("up")
                .status()
                .expect("ifconfig command failed to start")
        } else {
            unimplemented!()
        };

        assert!(status.success());
    }

    #[cfg(target_os = "linux")]
    pub fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.handle.write(buf)
    }

    #[cfg(target_os = "linux")]
    pub fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.handle.read(buf)
    }

    #[cfg(target_os = "macos")]
    pub fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut data = vec![];
        {
            data.write_u32::<BigEndian>(AF_INET as u32).unwrap();
            data.write_all(buf).unwrap();
        }
        match self.handle.write(&data) {
            Ok(len) => Ok(if len > 4 { len - 4 } else { 0 }),
            Err(e) => Err(e),
        }
    }

    #[cfg(target_os = "macos")]
    pub fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut data = [0u8; 1600];
        let result = self.handle.read(&mut data);
        match result {
            Ok(len) => {
                buf[..len - 4].clone_from_slice(&data[4..len]);
                Ok(if len > 4 { len - 4 } else { 0 })
            }
            Err(e) => Err(e),
        }
    }
}
<commit_msg>cleanup: macOS-only imports and variables<commit_after>use std::{fs, process, io};
use libc;
use libc::{c_int, c_ulong};
use std::os::unix::io::{RawFd, AsRawFd};
use std::io::{Write, Read};

#[cfg(target_os = "linux")]
use libc::c_short;
#[cfg(target_os = "linux")]
use std::path;
#[cfg(target_os = "linux")]
const IFNAMSIZ: usize = 16;
#[cfg(target_os = "linux")]
const IFF_TUN: c_short = 0x0001;
#[cfg(target_os = "linux")]
const IFF_NO_PI: c_short = 0x1000;
#[cfg(target_os = "linux")]
const TUNSETIFF: c_ulong = 0x400454ca;

#[cfg(target_os = "macos")]
use libc::socklen_t;
#[cfg(target_os = "macos")]
use std::mem;
#[cfg(target_os = "macos")]
use std::os::unix::io::FromRawFd;
#[cfg(target_os = "macos")]
use byteorder::{BigEndian, WriteBytesExt};
#[cfg(target_os = "macos")]
const AF_SYS_CONTROL: u16 = 2;
#[cfg(target_os = "macos")]
const AF_SYSTEM: u8 = 32;
#[cfg(target_os = "macos")]
const AF_INET: u8 = 2;
#[cfg(target_os = "macos")]
const PF_SYSTEM: c_int = AF_SYSTEM as c_int;
#[cfg(target_os = "macos")]
const SYSPROTO_CONTROL: c_int = 2;
#[cfg(target_os = "macos")]
const CTLIOCGINFO: c_ulong = 0xc0644e03;
#[cfg(target_os = "macos")]
const UTUN_CONTROL_NAME: &'static str = "com.apple.net.utun_control";

#[cfg(target_os = "linux")]
#[repr(C)]
pub struct ioctl_flags_data {
    pub ifr_name: [u8; IFNAMSIZ],
    pub ifr_flags: c_short,
}

#[cfg(target_os = "macos")]
#[repr(C)]
pub struct ctl_info {
    pub ctl_id: u32,
    pub ctl_name: [u8; 96],
}

#[cfg(target_os = "macos")]
#[repr(C)]
pub struct sockaddr_ctl {
    pub sc_len: u8,
    pub sc_family: u8,
    pub ss_sysaddr: u16,
    pub sc_id: u32,
    pub sc_unit: u32,
    pub sc_reserved: [u32; 5],
}

pub struct Tun {
    handle: fs::File,
    if_name: String,
}

impl AsRawFd for Tun {
    fn as_raw_fd(&self) -> RawFd {
        self.handle.as_raw_fd()
    }
}

impl Tun {
    #[cfg(target_os = "linux")]
    pub fn create(name: u8) -> Tun {
        let path = path::Path::new("/dev/net/tun");
        let file = match fs::OpenOptions::new().read(true).write(true).open(&path) {
            Err(why) => panic!("Couldn't open device '{}': {:?}", path.display(), why),
            Ok(file) => file,
        };

        let mut req = ioctl_flags_data {
            ifr_name: {
                let mut buffer = [0u8; IFNAMSIZ];
                let full_name = format!("tun{}", name);
                buffer[..full_name.len()].clone_from_slice(full_name.as_bytes());
                buffer
            },
            ifr_flags: IFF_TUN | IFF_NO_PI,
        };

        let res = unsafe { libc::ioctl(file.as_raw_fd(), TUNSETIFF, &mut req) }; // TUNSETIFF
        if res < 0 {
            panic!("{}", io::Error::last_os_error());
        }

        let size = req.ifr_name.iter().position(|&r| r == 0).unwrap();
        Tun {
            handle: file,
            if_name: String::from_utf8(req.ifr_name[..size].to_vec()).unwrap(),
        }
    }

    #[cfg(target_os = "macos")]
    pub fn create(name: u8) -> Tun {
        let fd = unsafe { libc::socket(PF_SYSTEM, libc::SOCK_DGRAM, SYSPROTO_CONTROL) };
        if fd < 0 {
            panic!("{}", io::Error::last_os_error());
        }

        let mut info = ctl_info {
            ctl_id: 0,
            ctl_name: {
                let mut buffer = [0u8; 96];
                buffer[..UTUN_CONTROL_NAME.len()].clone_from_slice(UTUN_CONTROL_NAME.as_bytes());
                buffer
            },
        };

        let res = unsafe { libc::ioctl(fd, CTLIOCGINFO, &mut info) };
        if res < 0 {
            unsafe { libc::close(fd) };
            panic!("{}", io::Error::last_os_error());
        }

        let addr = sockaddr_ctl {
            sc_id: info.ctl_id,
            sc_len: mem::size_of::<sockaddr_ctl>() as u8,
            sc_family: AF_SYSTEM,
            ss_sysaddr: AF_SYS_CONTROL,
            sc_unit: name as u32 + 1,
            sc_reserved: [0; 5],
        };

        // If connect() is successful, a tun%d device will be created, where "%d"
        // is our sc_unit-1
        let res = unsafe {
            let addr_ptr = &addr as *const sockaddr_ctl;
            libc::connect(fd,
                          addr_ptr as *const libc::sockaddr,
                          mem::size_of_val(&addr) as socklen_t)
        };
        if res < 0 {
            unsafe { libc::close(fd) };
            panic!("{}", io::Error::last_os_error());
        }

        Tun {
            handle: unsafe { fs::File::from_raw_fd(fd) },
            if_name: format!("utun{}", name),
        }
    }

    pub fn up(&self, self_id: u8) {
        let mut status = if cfg!(target_os = "linux") {
            process::Command::new("ifconfig")
                .arg(self.if_name.clone())
                .arg(format!("10.10.10.{}/24", self_id))
                .status()
                .expect("ifconfig command failed to start")
        } else if cfg!(target_os = "macos") {
            process::Command::new("ifconfig")
                .arg(self.if_name.as_str())
                .arg(format!("10.10.10.{}", self_id))
                .arg("10.10.10.1")
                .status()
                .expect("ifconfig command failed to start")
        } else {
            unimplemented!()
        };

        assert!(status.success());

        status = if cfg!(target_os = "linux") {
            process::Command::new("ifconfig")
                .arg(self.if_name.clone())
                .arg("mtu")
                .arg("1480")
                .arg("up")
                .status()
                .expect("ifconfig command failed to start")
        } else if cfg!(target_os = "macos") {
            process::Command::new("ifconfig")
                .arg(self.if_name.as_str())
                .arg("mtu")
                .arg("1480")
                .arg("up")
                .status()
                .expect("ifconfig command failed to start")
        } else {
            unimplemented!()
        };

        assert!(status.success());
    }

    #[cfg(target_os = "linux")]
    pub fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.handle.write(buf)
    }

    #[cfg(target_os = "linux")]
    pub fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.handle.read(buf)
    }

    #[cfg(target_os = "macos")]
    pub fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut data = vec![];
        {
            data.write_u32::<BigEndian>(AF_INET as u32).unwrap();
            data.write_all(buf).unwrap();
        }
        match self.handle.write(&data) {
            Ok(len) => Ok(if len > 4 { len - 4 } else { 0 }),
            Err(e) => Err(e),
        }
    }

    #[cfg(target_os = "macos")]
    pub fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut data = [0u8; 1600];
        let result = self.handle.read(&mut data);
        match result {
            Ok(len) => {
                buf[..len - 4].clone_from_slice(&data[4..len]);
                Ok(if len > 4 { len - 4 } else { 0 })
            }
            Err(e) => Err(e),
        }
    }
}
<|endoftext|>


<commit_before>/* Varint - Variable length integers implemented in Rust
 *
 * Copyright (c) 2014 Ryan Mendivil <ryan@nullreff.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Rustymine nor the names of its contributors may be
 *     used to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

use std::io::{IoResult, IoError};
use std::io::net::tcp::{TcpStream};

// https://developers.google.com/protocol-buffers/docs/encoding#varints
pub trait ReadVarint<T> {
    fn read_varint(&mut self) -> Result<uint, T>;
}

pub trait ToVarint {
    fn to_varint(&self) -> Vec<u8>;
}

impl ToVarint for uint {
    // Takes 7 bits at a time from a number and splits them into a list of
    // bytes. The most significant bit is set on each byte that has another
    // coming after it.
    fn to_varint(&self) -> Vec<u8> {
        let mut remaining = self.clone();
        let mut result = Vec::new();
        loop {
            let part = (remaining & 0x7F).to_u8().unwrap(); // First 7 bits
            remaining >>= 7;
            if remaining == 0 {
                result.push(part);
                break;
            } else {
                result.push(part | 0x80);
            }
        }
        result
    }
}

impl ReadVarint<IoError> for TcpStream {
    // This takes one byte at a time from a reader as long as the most significant
    // bit is 1.  Combines the remaining 7 bits together to make a number.
    fn read_varint(&mut self) -> IoResult<uint> {
        let mut result:uint = 0;

        // uint's can only take up to 4 bytes
        for i in range(0, 4) {
            match self.read_byte() {
                Ok(part) => {
                    result |= (part & 0b0111111).to_uint().unwrap() << i;
                    if (part >> 7) == 0 {
                        break;
                    }
                },
                Err(e) => return Err(e)
            }
        }
        Ok(result)
    }
}
<commit_msg>Fix varint decoding clobbering lower bits<commit_after>/* Varint - Variable length integers implemented in Rust
 *
 * Copyright (c) 2014 Ryan Mendivil <ryan@nullreff.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Rustymine nor the names of its contributors may be
 *     used to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

use std::io::{IoResult, IoError};
use std::io::net::tcp::{TcpStream};

// https://developers.google.com/protocol-buffers/docs/encoding#varints
pub trait ReadVarint<T> {
    fn read_varint(&mut self) -> Result<uint, T>;
}

pub trait ToVarint {
    fn to_varint(&self) -> Vec<u8>;
}

impl ToVarint for uint {
    // Takes 7 bits at a time from a number and splits them into a list of
    // bytes. The most significant bit is set on each byte that has another
    // coming after it.
    fn to_varint(&self) -> Vec<u8> {
        let mut remaining = self.clone();
        let mut result = Vec::new();
        loop {
            let part = (remaining & 0x7F).to_u8().unwrap(); // First 7 bits
            remaining >>= 7;
            if remaining == 0 {
                result.push(part);
                break;
            } else {
                result.push(part | 0x80);
            }
        }
        result
    }
}

impl ReadVarint<IoError> for TcpStream {
    // This takes one byte at a time from a reader as long as the most significant
    // bit is 1.  Combines the remaining 7 bits together to make a number.
    fn read_varint(&mut self) -> IoResult<uint> {
        let mut result:uint = 0;

        // uint's can only take up to 4 bytes
        for i in range(0, 4) {
            match self.read_byte() {
                Ok(part) => {
                    result |= (part & 0b0111111).to_uint().unwrap() << (i * 7);
                    if (part >> 7) == 0 {
                        break;
                    }
                },
                Err(e) => return Err(e)
            }
        }
        Ok(result)
    }
}
<|endoftext|>