<commit_before>extern crate rustc_serialize;

use std::collections::BTreeMap;

use rustc_serialize::json::{Json, ToJson};

/// An Optional value can contain Optional::Some<T> or Optional::Absent.
/// It is similar to an Option, but Optional::Absent means it will be
/// omitted when serialized.
pub enum Optional<T> {
    Value(T),
    Absent,
}

pub struct Location {
    pub address: Optional<String>,
    pub lat: f64,
    pub lon: f64,
}

pub struct Spacefed {
    pub spacenet: bool,
    pub spacesaml: bool,
    pub spacephone: bool,
}

pub struct Icon {
    pub open: String,
    pub close: String,
}

pub struct State {
    pub open: Option<bool>,
    pub lastchange: Optional<u64>,
    pub trigger_person: Optional<String>,
    pub message: Optional<String>,
    pub icon: Optional<Icon>,
}

pub struct Event {
    pub name: String,
    pub _type: String,
    pub timestamp: u64,
    pub extra: Optional<String>,
}

pub struct Contact {
    pub irc: Optional<String>,
    pub twitter: Optional<String>,
    pub foursquare: Optional<String>,
    pub email: Optional<String>,
}

pub struct Feed {
    pub _type: Optional<String>,
    pub url: String,
}

pub struct Feeds {
    pub blog: Optional<Feed>,
    pub wiki: Optional<Feed>,
    pub calendar: Optional<Feed>,
    pub flickr: Optional<Feed>,
}

pub struct Sensors {
    pub people_now_present: Optional<Vec<PeopleNowPresentSensor>>,
    pub temperature: Optional<Vec<TemperatureSensor>>,
}

pub struct PeopleNowPresentSensor {
    pub value: u32,
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
}

pub struct TemperatureSensor {
    pub value: f32,
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
}

pub struct Cache {
    pub schedule: String,
}

pub struct RadioShow {
    pub name: String,
    pub url: String,
    pub _type: String,
    pub start: String,
    pub end: String,
}

pub struct Status {

    // Hackerspace properties
    pub api: String,
    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".to_string(),
            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());

        match self.spacefed {
            Optional::Value(ref spacefed) => { d.insert("spacefed".to_string(), spacefed.to_json()); },
            Optional::Absent => (),
        };
        match self.projects {
            Optional::Value(ref projects) => { d.insert("projects".to_string(), projects.to_json()); },
            Optional::Absent => (),
        };
        match self.cam {
            Optional::Value(ref cam) => { d.insert("cam".to_string(), cam.to_json()); },
            Optional::Absent => (),
        };
        match self.feeds {
            Optional::Value(ref feeds) => { d.insert("feeds".to_string(), feeds.to_json()); },
            Optional::Absent => (),
        };
        match self.events {
            Optional::Value(ref events) => { d.insert("events".to_string(), events.to_json()); },
            Optional::Absent => (),
        };
        match self.radio_show {
            Optional::Value(ref radio_show) => { d.insert("radio_show".to_string(), radio_show.to_json()); },
            Optional::Absent => (),
        };

        match self.cache {
            Optional::Value(ref cache) => { d.insert("cache".to_string(), cache.to_json()); },
            Optional::Absent => (),
        };
        d.insert("issue_report_channels".to_string(), self.issue_report_channels.to_json());

        d.insert("state".to_string(), self.state.to_json());
        match self.sensors {
            Optional::Value(ref sensors) => { d.insert("sensors".to_string(), sensors.to_json()); },
            Optional::Absent => (),
        };

        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());
        match self.lastchange {
            Optional::Value(ref lastchange) => { d.insert("lastchange".to_string(), lastchange.to_json()); },
            Optional::Absent => (),
        };
        match self.trigger_person {
            Optional::Value(ref trigger_person) => { d.insert("trigger_person".to_string(), trigger_person.to_json()); },
            Optional::Absent => (),
        };
        match self.message {
            Optional::Value(ref message) => { d.insert("message".to_string(), message.to_json()); },
            Optional::Absent => (),
        };
        match self.icon {
            Optional::Value(ref icon) => { d.insert("icon".to_string(), icon.to_json()); },
            Optional::Absent => (),
        };
        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());
        match self.extra {
            Optional::Value(ref extra) => { d.insert("extra".to_string(), extra.to_json()); },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for Contact {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self.irc {
            Optional::Value(ref irc) => { d.insert("irc".to_string(), irc.to_json()); },
            Optional::Absent => (),
        };
        match self.twitter {
            Optional::Value(ref twitter) => { d.insert("twitter".to_string(), twitter.to_json()); },
            Optional::Absent => (),
        };
        match self.foursquare {
            Optional::Value(ref foursquare) => { d.insert("foursquare".to_string(), foursquare.to_json()); },
            Optional::Absent => (),
        };
        match self.email {
            Optional::Value(ref email) => { d.insert("email".to_string(), email.to_json()); },
            Optional::Absent => (),
        };
        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());
        match self._type {
            Optional::Value(ref _type) => { d.insert("type".to_string(), _type.to_json()); },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for Feeds {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self.blog {
            Optional::Value(ref blog) => { d.insert("blog".to_string(), blog.to_json()); },
            Optional::Absent => (),
        };
        match self.wiki {
            Optional::Value(ref wiki) => { d.insert("wiki".to_string(), wiki.to_json()); },
            Optional::Absent => (),
        };
        match self.calendar {
            Optional::Value(ref calendar) => { d.insert("calendar".to_string(), calendar.to_json()); },
            Optional::Absent => (),
        };
        match self.flickr {
            Optional::Value(ref flickr) => { d.insert("flickr".to_string(), flickr.to_json()); },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

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

impl ToJson for PeopleNowPresentSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        match self.location {
            Optional::Value(ref location) => { d.insert("location".to_string(), location.to_json()); },
            Optional::Absent => (),
        };
        match self.name {
            Optional::Value(ref name) => { d.insert("name".to_string(), name.to_json()); },
            Optional::Absent => (),
        };
        match self.names {
            Optional::Value(ref names) => { d.insert("names".to_string(), names.to_json()); },
            Optional::Absent => (),
        };
        match self.description {
            Optional::Value(ref description) => { d.insert("description".to_string(), description.to_json()); },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for TemperatureSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        d.insert("unit".to_string(), self.unit.to_json());
        d.insert("location".to_string(), self.location.to_json());
        match self.name {
            Optional::Value(ref name) => { d.insert("name".to_string(), name.to_json()); },
            Optional::Absent => (),
        };
        match self.description {
            Optional::Value(ref description) => { d.insert("description".to_string(), description.to_json()); },
            Optional::Absent => (),
        };
        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>spaceapi: Add Optional.map_or()<commit_after>extern crate rustc_serialize;

use std::collections::BTreeMap;

use rustc_serialize::json::{Json, ToJson};

/// An Optional value can contain Optional::Some<T> or Optional::Absent.
/// It is similar to an Option, but Optional::Absent means it will be
/// omitted when serialized.
pub enum Optional<T> {
    Value(T),
    Absent,
}

impl<T> Optional<T> {
    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
        match self {
            Optional::Value(v) => f(v),
            Optional::Absent => def,
        }
    }
}

pub struct Location {
    pub address: Optional<String>,
    pub lat: f64,
    pub lon: f64,
}

pub struct Spacefed {
    pub spacenet: bool,
    pub spacesaml: bool,
    pub spacephone: bool,
}

pub struct Icon {
    pub open: String,
    pub close: String,
}

pub struct State {
    pub open: Option<bool>,
    pub lastchange: Optional<u64>,
    pub trigger_person: Optional<String>,
    pub message: Optional<String>,
    pub icon: Optional<Icon>,
}

pub struct Event {
    pub name: String,
    pub _type: String,
    pub timestamp: u64,
    pub extra: Optional<String>,
}

pub struct Contact {
    pub irc: Optional<String>,
    pub twitter: Optional<String>,
    pub foursquare: Optional<String>,
    pub email: Optional<String>,
}

pub struct Feed {
    pub _type: Optional<String>,
    pub url: String,
}

pub struct Feeds {
    pub blog: Optional<Feed>,
    pub wiki: Optional<Feed>,
    pub calendar: Optional<Feed>,
    pub flickr: Optional<Feed>,
}

pub struct Sensors {
    pub people_now_present: Optional<Vec<PeopleNowPresentSensor>>,
    pub temperature: Optional<Vec<TemperatureSensor>>,
}

pub struct PeopleNowPresentSensor {
    pub value: u32,
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
}

pub struct TemperatureSensor {
    pub value: f32,
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
}

pub struct Cache {
    pub schedule: String,
}

pub struct RadioShow {
    pub name: String,
    pub url: String,
    pub _type: String,
    pub start: String,
    pub end: String,
}

pub struct Status {

    // Hackerspace properties
    pub api: String,
    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".to_string(),
            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());

        match self.spacefed {
            Optional::Value(ref spacefed) => { d.insert("spacefed".to_string(), spacefed.to_json()); },
            Optional::Absent => (),
        };
        match self.projects {
            Optional::Value(ref projects) => { d.insert("projects".to_string(), projects.to_json()); },
            Optional::Absent => (),
        };
        match self.cam {
            Optional::Value(ref cam) => { d.insert("cam".to_string(), cam.to_json()); },
            Optional::Absent => (),
        };
        match self.feeds {
            Optional::Value(ref feeds) => { d.insert("feeds".to_string(), feeds.to_json()); },
            Optional::Absent => (),
        };
        match self.events {
            Optional::Value(ref events) => { d.insert("events".to_string(), events.to_json()); },
            Optional::Absent => (),
        };
        match self.radio_show {
            Optional::Value(ref radio_show) => { d.insert("radio_show".to_string(), radio_show.to_json()); },
            Optional::Absent => (),
        };

        match self.cache {
            Optional::Value(ref cache) => { d.insert("cache".to_string(), cache.to_json()); },
            Optional::Absent => (),
        };
        d.insert("issue_report_channels".to_string(), self.issue_report_channels.to_json());

        d.insert("state".to_string(), self.state.to_json());
        match self.sensors {
            Optional::Value(ref sensors) => { d.insert("sensors".to_string(), sensors.to_json()); },
            Optional::Absent => (),
        };

        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());
        match self.lastchange {
            Optional::Value(ref lastchange) => { d.insert("lastchange".to_string(), lastchange.to_json()); },
            Optional::Absent => (),
        };
        match self.trigger_person {
            Optional::Value(ref trigger_person) => { d.insert("trigger_person".to_string(), trigger_person.to_json()); },
            Optional::Absent => (),
        };
        match self.message {
            Optional::Value(ref message) => { d.insert("message".to_string(), message.to_json()); },
            Optional::Absent => (),
        };
        match self.icon {
            Optional::Value(ref icon) => { d.insert("icon".to_string(), icon.to_json()); },
            Optional::Absent => (),
        };
        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());
        match self.extra {
            Optional::Value(ref extra) => { d.insert("extra".to_string(), extra.to_json()); },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for Contact {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self.irc {
            Optional::Value(ref irc) => { d.insert("irc".to_string(), irc.to_json()); },
            Optional::Absent => (),
        };
        match self.twitter {
            Optional::Value(ref twitter) => { d.insert("twitter".to_string(), twitter.to_json()); },
            Optional::Absent => (),
        };
        match self.foursquare {
            Optional::Value(ref foursquare) => { d.insert("foursquare".to_string(), foursquare.to_json()); },
            Optional::Absent => (),
        };
        match self.email {
            Optional::Value(ref email) => { d.insert("email".to_string(), email.to_json()); },
            Optional::Absent => (),
        };
        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());
        match self._type {
            Optional::Value(ref _type) => { d.insert("type".to_string(), _type.to_json()); },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for Feeds {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        match self.blog {
            Optional::Value(ref blog) => { d.insert("blog".to_string(), blog.to_json()); },
            Optional::Absent => (),
        };
        match self.wiki {
            Optional::Value(ref wiki) => { d.insert("wiki".to_string(), wiki.to_json()); },
            Optional::Absent => (),
        };
        match self.calendar {
            Optional::Value(ref calendar) => { d.insert("calendar".to_string(), calendar.to_json()); },
            Optional::Absent => (),
        };
        match self.flickr {
            Optional::Value(ref flickr) => { d.insert("flickr".to_string(), flickr.to_json()); },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

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

impl ToJson for PeopleNowPresentSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        match self.location {
            Optional::Value(ref location) => { d.insert("location".to_string(), location.to_json()); },
            Optional::Absent => (),
        };
        match self.name {
            Optional::Value(ref name) => { d.insert("name".to_string(), name.to_json()); },
            Optional::Absent => (),
        };
        match self.names {
            Optional::Value(ref names) => { d.insert("names".to_string(), names.to_json()); },
            Optional::Absent => (),
        };
        match self.description {
            Optional::Value(ref description) => { d.insert("description".to_string(), description.to_json()); },
            Optional::Absent => (),
        };
        Json::Object(d)
    }
}

impl ToJson for TemperatureSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        d.insert("unit".to_string(), self.unit.to_json());
        d.insert("location".to_string(), self.location.to_json());
        match self.name {
            Optional::Value(ref name) => { d.insert("name".to_string(), name.to_json()); },
            Optional::Absent => (),
        };
        match self.description {
            Optional::Value(ref description) => { d.insert("description".to_string(), description.to_json()); },
            Optional::Absent => (),
        };
        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>include!("header.rs");

fn test_lu(a: Array<f64, Ix2>) {
    println!("a = \n{:?}", &a);
    let (p, l, u) = a.clone().lu().unwrap();
    println!("P = \n{:?}", &p);
    println!("L = \n{:?}", &l);
    println!("U = \n{:?}", &u);
    println!("LU = \n{:?}", l.dot(&u));
    all_close_l2(&l.dot(&u).permutated(&p), &a, 1e-7).unwrap();
}

macro_rules! test_lu_upper {
    ($testname:ident, $testname_t:ident, $n:expr, $m:expr) => {
#[test]
fn $testname() {
    let r_dist = RealNormal::new(0., 1.);
    let mut a = Array::<f64, _>::random(($n, $m), r_dist);
    for ((i, j), val) in a.indexed_iter_mut() {
        if i > j {
            *val = 0.0;
        }
    }
    test_lu(a);
}
#[test]
fn $testname_t() {
    let r_dist = RealNormal::new(0., 1.);
    let mut a = Array::<f64, _>::random(($m, $n), r_dist).reversed_axes();
    for ((i, j), val) in a.indexed_iter_mut() {
        if i > j {
            *val = 0.0;
        }
    }
    test_lu(a);
}
}} // end test_lu_upper
test_lu_upper!(lu_square_upper, lu_square_upper_t, 3, 3);
test_lu_upper!(lu_3x4_upper, lu_3x4_upper_t, 3, 4);
test_lu_upper!(lu_4x3_upper, lu_4x3_upper_t, 4, 3);

macro_rules! test_lu_lower {
    ($testname:ident, $testname_t:ident, $n:expr, $m:expr) => {
#[test]
fn $testname() {
    let r_dist = RealNormal::new(0., 1.);
    let mut a = Array::<f64, _>::random(($n, $m), r_dist);
    for ((i, j), val) in a.indexed_iter_mut() {
        if i < j {
            *val = 0.0;
        }
    }
    test_lu(a);
}
#[test]
fn $testname_t() {
    let r_dist = RealNormal::new(0., 1.);
    let mut a = Array::<f64, _>::random(($m, $n), r_dist).reversed_axes();
    for ((i, j), val) in a.indexed_iter_mut() {
        if i < j {
            *val = 0.0;
        }
    }
    test_lu(a);
}
}} // end test_lu_lower
test_lu_lower!(lu_square_lower, lu_square_lower_t, 3, 3);
test_lu_lower!(lu_3x4_lower, lu_3x4_lower_t, 3, 4);
test_lu_lower!(lu_4x3_lower, lu_4x3_lower_t, 4, 3);

macro_rules! test_lu {
    ($testname:ident, $testname_t:ident, $n:expr, $m:expr) => {
#[test]
fn $testname() {
    let r_dist = RealNormal::new(0., 1.);
    let a = Array::<f64, _>::random(($n, $m), r_dist);
    test_lu(a);
}
#[test]
fn $testname_t() {
    let r_dist = RealNormal::new(0., 1.);
    let a = Array::<f64, _>::random(($m, $n), r_dist).reversed_axes();
    test_lu(a);
}
}} // end test_lu
test_lu!(lu_square, lu_square_t, 3, 3);
test_lu!(lu_3x4, lu_3x4_t, 3, 4);
test_lu!(lu_4x3, lu_4x3_t, 4, 3);
<commit_msg>Rewrite test for LU<commit_after>include!("header.rs");

macro_rules! impl_test {
    ($funcname:ident, $random:path, $n:expr, $m:expr, $t:expr) => {
#[test]
fn $funcname() {
    use ndarray_linalg::prelude::*;
    let a = $random($n, $m, $t);
    let ans = a.clone();
    let (p, l, u) = a.lu().unwrap();
    println!("P = \n{:?}", &p);
    println!("L = \n{:?}", &l);
    println!("U = \n{:?}", &u);
    println!("LU = \n{:?}", l.dot(&u));
    all_close_l2(&l.dot(&u).permutated(&p), &ans, 1e-7).unwrap();
}
}} // impl_test

macro_rules! impl_test_lu {
    ($modname:ident, $random:path) => {
mod $modname {
    impl_test!(lu_square, $random, 3, 3, false);
    impl_test!(lu_square_t, $random, 3, 3, true);
    impl_test!(lu_3x4, $random, 3, 4, false);
    impl_test!(lu_3x4_t, $random, 3, 4, true);
    impl_test!(lu_4x3, $random, 4, 3, false);
    impl_test!(lu_4x3_t, $random, 4, 3, true);
}
}} // impl_test_lu

impl_test_lu!(owned, super::random_owned);
impl_test_lu!(shared, super::random_shared);
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fs::File;
use std::mem;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::ptr;
use std::time::Duration;

use libc::{self, CLOCK_MONOTONIC, TFD_CLOEXEC, timerfd_create, timerfd_settime};

use {Result, errno_result};

/// A safe wrapper around a Linux timerfd (man 2 timerfd_create).
pub struct TimerFd(File);

impl TimerFd {
    /// Creates a new timerfd.  The timer is initally disarmed and must be armed by calling
    /// `reset`.
    pub fn new() -> Result<TimerFd> {
        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC) };
        if ret < 0 {
            return errno_result();
        }

        // Safe because we uniquely own the file descriptor.
        Ok(TimerFd(unsafe { File::from_raw_fd(ret) } ))
    }

    /// Sets the timer to expire after `dur`.  If `interval` is not `None` it represents
    /// the period for repeated expirations after the initial expiration.  Otherwise
    /// the timer will expire just once.  Cancels any existing duration and repeating interval.
    pub fn reset(&mut self, dur: Duration, interval: Option<Duration>) -> Result<()> {
        // Safe because we are zero-initializing a struct with only primitive member fields.
        let mut spec: libc::itimerspec = unsafe { mem::zeroed() };
        spec.it_value.tv_sec = dur.as_secs() as libc::time_t;
        spec.it_value.tv_nsec = dur.subsec_nanos() as libc::c_long;

        if let Some(int) = interval {
            spec.it_interval.tv_sec = int.as_secs() as libc::time_t;
            spec.it_interval.tv_nsec = int.subsec_nanos() as libc::c_long;
        }

        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { timerfd_settime(self.as_raw_fd(), 0, &spec, ptr::null_mut()) };
        if ret < 0 {
            return errno_result();
        }

        Ok(())
    }

    /// Waits until the timer expires.  The return value represents the number of times the timer
    /// has expired since the last time `wait` was called.  If the timer has not yet expired once
    /// this call will block until it does.
    pub fn wait(&mut self) -> Result<u64> {
        let mut count = 0u64;

        // Safe because this will only modify |buf| and we check the return value.
        let ret = unsafe {
            libc::read(self.as_raw_fd(),
                       &mut count as *mut _ as *mut libc::c_void,
                       mem::size_of_val(&count))
        };
        if ret < 0 {
            return errno_result();
        }

        // The bytes in the buffer are guaranteed to be in native byte-order so we don't need to
        // use from_le or from_be.
        Ok(count)
    }

    /// Disarms the timer.
    pub fn clear(&mut self) -> Result<()> {
        // Safe because we are zero-initializing a struct with only primitive member fields.
        let spec: libc::itimerspec = unsafe { mem::zeroed() };

        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { timerfd_settime(self.as_raw_fd(),  0, &spec, ptr::null_mut()) };
        if ret < 0 {
            return errno_result();
        }

        Ok(())
    }
}

impl AsRawFd for TimerFd {
    fn as_raw_fd(&self) -> RawFd {
        self.0.as_raw_fd()
    }
}

impl FromRawFd for TimerFd {
    unsafe fn from_raw_fd(fd: RawFd) -> Self {
        TimerFd(File::from_raw_fd(fd))
    }
}

impl IntoRawFd for TimerFd {
    fn into_raw_fd(self) -> RawFd {
        self.0.into_raw_fd()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::thread::sleep;
    use std::time::{Duration, Instant};

    #[test]
    fn one_shot() {
        let mut tfd = TimerFd::new().expect("failed to create timerfd");

        let dur = Duration::from_millis(200);
        let now = Instant::now();
        tfd.reset(dur.clone(), None).expect("failed to arm timer");

        let count = tfd.wait().expect("unable to wait for timer");

        assert_eq!(count, 1);
        assert!(now.elapsed() >= dur);
    }

    #[test]
    fn repeating() {
        let mut tfd = TimerFd::new().expect("failed to create timerfd");

        let dur = Duration::from_millis(200);
        let interval = Duration::from_millis(100);
        tfd.reset(dur.clone(), Some(interval)).expect("failed to arm timer");

        sleep(dur * 3);

        let count = tfd.wait().expect("unable to wait for timer");
        assert!(count >= 5, "count = {}", count);
    }
}
<commit_msg>sys_util: timerfd: Add ability to check if the timer is armed<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::fs::File;
use std::mem;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::ptr;
use std::time::Duration;

use libc::{self, CLOCK_MONOTONIC, TFD_CLOEXEC, timerfd_create, timerfd_gettime, timerfd_settime};

use {Result, errno_result};

/// A safe wrapper around a Linux timerfd (man 2 timerfd_create).
pub struct TimerFd(File);

impl TimerFd {
    /// Creates a new timerfd.  The timer is initally disarmed and must be armed by calling
    /// `reset`.
    pub fn new() -> Result<TimerFd> {
        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC) };
        if ret < 0 {
            return errno_result();
        }

        // Safe because we uniquely own the file descriptor.
        Ok(TimerFd(unsafe { File::from_raw_fd(ret) } ))
    }

    /// Sets the timer to expire after `dur`.  If `interval` is not `None` it represents
    /// the period for repeated expirations after the initial expiration.  Otherwise
    /// the timer will expire just once.  Cancels any existing duration and repeating interval.
    pub fn reset(&mut self, dur: Duration, interval: Option<Duration>) -> Result<()> {
        // Safe because we are zero-initializing a struct with only primitive member fields.
        let mut spec: libc::itimerspec = unsafe { mem::zeroed() };
        spec.it_value.tv_sec = dur.as_secs() as libc::time_t;
        spec.it_value.tv_nsec = dur.subsec_nanos() as libc::c_long;

        if let Some(int) = interval {
            spec.it_interval.tv_sec = int.as_secs() as libc::time_t;
            spec.it_interval.tv_nsec = int.subsec_nanos() as libc::c_long;
        }

        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { timerfd_settime(self.as_raw_fd(), 0, &spec, ptr::null_mut()) };
        if ret < 0 {
            return errno_result();
        }

        Ok(())
    }

    /// Waits until the timer expires.  The return value represents the number of times the timer
    /// has expired since the last time `wait` was called.  If the timer has not yet expired once
    /// this call will block until it does.
    pub fn wait(&mut self) -> Result<u64> {
        let mut count = 0u64;

        // Safe because this will only modify |buf| and we check the return value.
        let ret = unsafe {
            libc::read(self.as_raw_fd(),
                       &mut count as *mut _ as *mut libc::c_void,
                       mem::size_of_val(&count))
        };
        if ret < 0 {
            return errno_result();
        }

        // The bytes in the buffer are guaranteed to be in native byte-order so we don't need to
        // use from_le or from_be.
        Ok(count)
    }

    /// Returns `true` if the timer is currently armed.
    pub fn is_armed(&self) -> Result<bool> {
        // Safe because we are zero-initializing a struct with only primitive member fields.
        let mut spec: libc::itimerspec = unsafe { mem::zeroed() };

        // Safe because timerfd_gettime is trusted to only modify `spec`.
        let ret = unsafe { timerfd_gettime(self.as_raw_fd(), &mut spec) };
        if ret < 0 {
            return errno_result();
        }

        Ok(spec.it_value.tv_sec != 0 || spec.it_value.tv_nsec != 0)
    }

    /// Disarms the timer.
    pub fn clear(&mut self) -> Result<()> {
        // Safe because we are zero-initializing a struct with only primitive member fields.
        let spec: libc::itimerspec = unsafe { mem::zeroed() };

        // Safe because this doesn't modify any memory and we check the return value.
        let ret = unsafe { timerfd_settime(self.as_raw_fd(),  0, &spec, ptr::null_mut()) };
        if ret < 0 {
            return errno_result();
        }

        Ok(())
    }
}

impl AsRawFd for TimerFd {
    fn as_raw_fd(&self) -> RawFd {
        self.0.as_raw_fd()
    }
}

impl FromRawFd for TimerFd {
    unsafe fn from_raw_fd(fd: RawFd) -> Self {
        TimerFd(File::from_raw_fd(fd))
    }
}

impl IntoRawFd for TimerFd {
    fn into_raw_fd(self) -> RawFd {
        self.0.into_raw_fd()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::thread::sleep;
    use std::time::{Duration, Instant};

    #[test]
    fn one_shot() {
        let mut tfd = TimerFd::new().expect("failed to create timerfd");
        assert_eq!(tfd.is_armed().unwrap(), false);

        let dur = Duration::from_millis(200);
        let now = Instant::now();
        tfd.reset(dur.clone(), None).expect("failed to arm timer");

        assert_eq!(tfd.is_armed().unwrap(), true);

        let count = tfd.wait().expect("unable to wait for timer");

        assert_eq!(count, 1);
        assert!(now.elapsed() >= dur);
    }

    #[test]
    fn repeating() {
        let mut tfd = TimerFd::new().expect("failed to create timerfd");

        let dur = Duration::from_millis(200);
        let interval = Duration::from_millis(100);
        tfd.reset(dur.clone(), Some(interval)).expect("failed to arm timer");

        sleep(dur * 3);

        let count = tfd.wait().expect("unable to wait for timer");
        assert!(count >= 5, "count = {}", count);
    }
}
<|endoftext|>


<commit_before>use super::compact::Compact;
use super::compact_vec::CompactVec;

/// A compact storage for a `String`. So far doesn't support direct mutable operations,
/// Only conversion from and to `String`/`&str`
#[derive(Clone)]
pub struct CompactString {
    chars: CompactVec<u8>,
}

impl ::std::ops::Deref for CompactString {
    type Target = str;

    fn deref(&self) -> &str {
        unsafe { ::std::str::from_utf8_unchecked(&self.chars) }
    }
}

impl ::std::convert::From<String> for CompactString {
    fn from(string: String) -> CompactString {
        CompactString { chars: string.into_bytes().into() }
    }
}

impl Compact for CompactString {
    fn is_still_compact(&self) -> bool {
        self.chars.is_still_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.chars.dynamic_size_bytes()
    }

    unsafe fn compact(source: *mut Self, dest: *mut Self, new_dynamic_part: *mut u8) {
        Compact::compact(&mut (*source).chars, &mut (*dest).chars, new_dynamic_part)
    }

    unsafe fn decompact(source: *const Self) -> Self {
        CompactString {
            chars: Compact::decompact(&(*source).chars)
        }
    }
}<commit_msg>New & push_str for CString<commit_after>use super::compact::Compact;
use super::compact_vec::CompactVec;

/// A compact storage for a `String`. So far doesn't support direct mutable operations,
/// Only conversion from and to `String`/`&str`
#[derive(Clone, Default)]
pub struct CompactString {
    chars: CompactVec<u8>,
}

impl CompactString {
    /// Create an empty `CString`
    pub fn new() -> Self {
        Default::default()
    }

    /// Appends a given string slice onto the end of this `CString`.
    pub fn push_str(&mut self, string: &str) {
        self.chars.extend_from_copy_slice(string.as_bytes());
    }
}

impl ::std::ops::Deref for CompactString {
    type Target = str;

    fn deref(&self) -> &str {
        unsafe { ::std::str::from_utf8_unchecked(&self.chars) }
    }
}

impl ::std::convert::From<String> for CompactString {
    fn from(string: String) -> CompactString {
        CompactString { chars: string.into_bytes().into() }
    }
}

impl Compact for CompactString {
    fn is_still_compact(&self) -> bool {
        self.chars.is_still_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.chars.dynamic_size_bytes()
    }

    unsafe fn compact(source: *mut Self, dest: *mut Self, new_dynamic_part: *mut u8) {
        Compact::compact(&mut (*source).chars, &mut (*dest).chars, new_dynamic_part)
    }

    unsafe fn decompact(source: *const Self) -> Self {
        CompactString {
            chars: Compact::decompact(&(*source).chars)
        }
    }
}<|endoftext|>


<commit_before>/* automatically generated by rust-bindgen */

extern "C" {
    #[link_name = "\u{1}a"]
    pub static mut a: *mut ::std::os::raw::c_char;
}
extern "C" {
    #[link_name = "\u{1}b"]
    pub static mut b: *const ::std::os::raw::c_char;
}
extern "C" {
    #[link_name = "\u{1}c"]
    pub static mut c: *mut ::std::os::raw::c_char;
}
extern "C" {
    #[link_name = "\u{1}d"]
    pub static mut d: *const ::std::os::raw::c_char;
}
<commit_msg>Add missing line in test expectation<commit_after>/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]

extern "C" {
    #[link_name = "\u{1}a"]
    pub static mut a: *mut ::std::os::raw::c_char;
}
extern "C" {
    #[link_name = "\u{1}b"]
    pub static mut b: *const ::std::os::raw::c_char;
}
extern "C" {
    #[link_name = "\u{1}c"]
    pub static mut c: *mut ::std::os::raw::c_char;
}
extern "C" {
    #[link_name = "\u{1}d"]
    pub static mut d: *const ::std::os::raw::c_char;
}
<|endoftext|>


<commit_before>use std::convert::From;

use binding::class::{instance_variable_get, instance_variable_set, object_class};
use binding::util::call_method;
use types::Value;
use util::create_arguments;

use super::any_object::AnyObject;
use super::class::Class;

pub trait Object : From<Value> {
    fn value(&self) -> Value;

    fn class(&self) -> Class {
        let class = object_class(self.value());

        Class::from(class)
    }

    fn send(&self, method: &str, arguments: Vec<AnyObject>) -> AnyObject {
        let (argc, argv) = create_arguments(arguments);

        let result = call_method(self.value(), method, argc, argv);

        AnyObject::from(result)
    }

    fn as_any_object(&self) -> AnyObject {
        AnyObject::from(self.value())
    }

    fn instance_variable_get(&self, variable: &str) -> AnyObject {
        let result = instance_variable_get(self.value(), variable);

        AnyObject::from(result)
    }

    fn instance_variable_set<T: Object>(&mut self, variable: &str, value: T) -> AnyObject {
        let result = instance_variable_set(self.value(), variable, value.value());

        AnyObject::from(result)
    }
}
<commit_msg>Add documentation for class::traits::Object<commit_after>use std::convert::From;

use binding::class::{instance_variable_get, instance_variable_set, object_class};
use binding::util::call_method;
use types::Value;
use util::create_arguments;

use super::any_object::AnyObject;
use super::class::Class;

/// `Object`
///
/// Trait consists methods of Ruby `Object` class. Every struct like `Array`, `Hash` etc implements
/// this trait.
pub trait Object : From<Value> {
    /// Usually this function just returns a `value` of current object.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::types::Value;
    /// use ruru::traits::Object;
    ///
    /// struct Array {
    ///     value: Value
    /// }
    ///
    /// impl From<Value> for Array {
    ///     fn from(value: Value) -> Self {
    ///         Array {
    ///             value: value
    ///         }
    ///     }
    /// }
    ///
    /// impl Object for Array {
    ///     fn value(&self) -> Value {
    ///         self.value
    ///     }
    /// }
    /// ```
    fn value(&self) -> Value;

    /// Returns a `Class` struct of current object
    ///
    /// # Examples
    /// ```
    /// use ruru::{Array, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// assert_eq!(Array::new().class(), Array::new().class());
    /// ```
    fn class(&self) -> Class {
        let class = object_class(self.value());

        Class::from(class)
    }

    /// Calls a given method on an object similarly to Ruby `Object#send` method
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Array, Fixnum, RString, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let array_to_str =
    ///     array
    ///         .send("to_s", vec![])
    ///         .as_string()
    ///         .to_string();
    ///
    /// assert_eq!(array_to_str, "[1]".to_string());
    /// ```
    fn send(&self, method: &str, arguments: Vec<AnyObject>) -> AnyObject {
        let (argc, argv) = create_arguments(arguments);

        let result = call_method(self.value(), method, argc, argv);

        AnyObject::from(result)
    }

    /// Converts struct to `AnyObject`
    ///
    /// See docs for `AnyObject` class for more details.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{Array, Fixnum, VM};
    /// use ruru::traits::Object;
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let args = vec![Fixnum::new(1).as_any_object()];
    /// let index =
    ///     array
    ///         .send("find_index", args)
    ///         .as_fixnum()
    ///         .to_i64();
    ///
    /// assert_eq!(index, 0);
    /// ```
    fn as_any_object(&self) -> AnyObject {
        AnyObject::from(self.value())
    }

    /// Sets an instance variable for object
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{AnyObject, Class, Fixnum, VM};
    /// use ruru::types::Argc;
    /// use ruru::traits::Object;
    ///
    /// #[no_mangle]
    /// pub extern fn counter_initialize(_: Argc, _: *const AnyObject, mut itself: AnyObject) -> AnyObject {
    ///     itself.instance_variable_set("@state", Fixnum::new(0))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_increment(_: Argc, _: *const AnyObject, mut itself: AnyObject) -> AnyObject {
    ///     let state = itself.instance_variable_get("@state").as_fixnum().to_i64();
    ///
    ///     itself.instance_variable_set("@state", Fixnum::new(state + 1))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_state(_: Argc, _: *const AnyObject, itself: AnyObject) -> Fixnum {
    ///     itself.instance_variable_get("@state").as_fixnum()
    /// }
    ///
    /// fn main() {
    ///     # VM::init();
    ///     let counter = Class::new("Counter").define(|itself| {
    ///         itself.def("initialize", counter_initialize);
    ///         itself.def("increment!", counter_increment);
    ///         itself.def("state", counter_state);
    ///     }).new_instance(vec![]);
    ///
    ///     counter.send("increment!", vec![]);
    ///
    ///     let new_state = counter.send("state", vec![]).as_fixnum().to_i64();
    ///
    ///     assert_eq!(new_state, 1);
    /// }
    /// ```
    fn instance_variable_get(&self, variable: &str) -> AnyObject {
        let result = instance_variable_get(self.value(), variable);

        AnyObject::from(result)
    }

    /// Gets an instance variable of object
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ruru::{AnyObject, Class, Fixnum, VM};
    /// use ruru::types::Argc;
    /// use ruru::traits::Object;
    ///
    /// #[no_mangle]
    /// pub extern fn counter_initialize(_: Argc, _: *const AnyObject, mut itself: AnyObject) -> AnyObject {
    ///     itself.instance_variable_set("@state", Fixnum::new(0))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_increment(_: Argc, _: *const AnyObject, mut itself: AnyObject) -> AnyObject {
    ///     let state = itself.instance_variable_get("@state").as_fixnum().to_i64();
    ///
    ///     itself.instance_variable_set("@state", Fixnum::new(state + 1))
    /// }
    ///
    /// #[no_mangle]
    /// pub extern fn counter_state(_: Argc, _: *const AnyObject, itself: AnyObject) -> Fixnum {
    ///     itself.instance_variable_get("@state").as_fixnum()
    /// }
    ///
    /// fn main() {
    ///     # VM::init();
    ///     let counter = Class::new("Counter").define(|itself| {
    ///         itself.def("initialize", counter_initialize);
    ///         itself.def("increment!", counter_increment);
    ///         itself.def("state", counter_state);
    ///     }).new_instance(vec![]);
    ///
    ///     counter.send("increment!", vec![]);
    ///
    ///     let new_state = counter.send("state", vec![]).as_fixnum().to_i64();
    ///
    ///     assert_eq!(new_state, 1);
    /// }
    /// ```
    fn instance_variable_set<T: Object>(&mut self, variable: &str, value: T) -> AnyObject {
        let result = instance_variable_set(self.value(), variable, value.value());

        AnyObject::from(result)
    }
}
<|endoftext|>


<commit_before>/*
    Copyright 2014-2015 Zumero, LLC

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

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

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

extern crate lsm;

fn work(name: &str) -> Result<(),lsm::Error> {
    println!("file: {}", name);
    let db = try!(lsm::db::new(String::from(name), lsm::DEFAULT_SETTINGS));
    let (segments, infos) = try!(db.list_segments());
    println!("segments: {:?}", segments);
    println!("infos: {:?}", infos);
    Ok(())
}

pub fn main() {
    let args: Vec<_> = std::env::args().collect();
    work(&args[1]);
}

<commit_msg>add a merge command to diag_lsm<commit_after>/*
    Copyright 2014-2015 Zumero, LLC

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

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

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

#![feature(convert)]

extern crate lsm;

fn list_segments(name: &str) -> Result<(),lsm::Error> {
    let db = try!(lsm::db::new(String::from(name), lsm::DEFAULT_SETTINGS));
    let (segments, infos) = try!(db.list_segments());
    println!("segments: {:?}", segments);
    println!("infos: {:?}", infos);
    Ok(())
}

fn merge(name: &str, level: u32, min: usize, max: Option<usize>) -> Result<(),lsm::Error> {
    let db = try!(lsm::db::new(String::from(name), lsm::DEFAULT_SETTINGS));
    match try!(db.merge(level, min, max)) {
        Some(seg) => {
            println!("merged segment: {}", seg);
            let lck = try!(db.GetWriteLock());
            try!(lck.commitMerge(seg));
            Ok(())
        },
        None => {
            println!("no merge needed");
            Ok(())
        },
    }
}

fn result_main() -> Result<(),lsm::Error> {
    let args: Vec<_> = std::env::args().collect();
    println!("args: {:?}", args);
    if args.len() < 2 {
        return Err(lsm::Error::Misc("no command given"));
    }
    let cmd = args[1].as_str();
    if args.len() < 3 {
        return Err(lsm::Error::Misc("no filename given"));
    }
    let name = args[2].as_str();
    match cmd {
        "merge" => {
            if args.len() < 5 {
                return Err(lsm::Error::Misc("too few args"));
            }
            let level = args[3].parse::<u32>().unwrap();
            let min = args[4].parse::<usize>().unwrap();
            if args.len() == 5 {
                merge(name, level, min, None)
            } else {
                let max = args[5].parse::<usize>().unwrap();
                merge(name, level, min, Some(max))
            }
        },
        "list_segments" => {
            list_segments(name)
        },
        _ => {
            Err(lsm::Error::Misc("unknown command"))
        },
    }
}

pub fn main() {
    let r = result_main();
    if r.is_err() {
        println!("{:?}", r);
    }
}

<|endoftext|>


<commit_before>extern crate quick_xml;

use quick_xml::events::{BytesStart, Event};
use quick_xml::{Reader, Result};
use std::str::from_utf8;

#[test]
fn sample_1_short() {
    test(
        include_bytes!("documents/sample_1.xml"),
        include_bytes!("documents/sample_1_short.txt"),
        true,
    );
}

#[test]
fn sample_1_full() {
    test(
        include_bytes!("documents/sample_1.xml"),
        include_bytes!("documents/sample_1_full.txt"),
        false,
    );
}

#[test]
fn sample_2_short() {
    test(
        include_bytes!("documents/sample_2.xml"),
        include_bytes!("documents/sample_2_short.txt"),
        true,
    );
}

#[test]
fn sample_2_full() {
    test(
        include_bytes!("documents/sample_2.xml"),
        include_bytes!("documents/sample_2_full.txt"),
        false,
    );
}

#[cfg(all(not(windows), feature = "escape-html"))]
#[test]
fn html5() {
    test(
        include_bytes!("documents/html5.html"),
        include_bytes!("documents/html5.txt"),
        false,
    );
}

#[cfg(all(windows, feature = "escape-html"))]
#[test]
fn html5() {
    test(
        include_bytes!("documents/html5.html"),
        include_bytes!("documents/html5-windows.txt"),
        false,
    );
}

// #[test]
// fn sample_3_short() {
//     test(
//         include_bytes!("documents/sample_3.xml"),
//         include_bytes!("documents/sample_3_short.txt"),
//         true
//     );
// }

// #[test]
// fn sample_3_full() {
//     test(
//         include_bytes!("documents/sample_3.xml"),
//         include_bytes!("documents/sample_3_full.txt"),
//         false
//     );
// }

// #[test]
// fn sample_4_short() {
//     test(
//         include_bytes!("documents/sample_4.xml"),
//         include_bytes!("documents/sample_4_short.txt"),
//         true
//     );
// }

// #[test]
// fn sample_4_full() {
//     test(
//         include_bytes!("documents/sample_4.xml"),
//         include_bytes!("documents/sample_4_full.txt"),
//         false
//     );
//
// }

#[test]
fn sample_ns_short() {
    test(
        include_bytes!("documents/sample_ns.xml"),
        include_bytes!("documents/sample_ns_short.txt"),
        true,
    );
}

#[test]
fn eof_1() {
    test(
        br#"<?xml"#,
        br#"Error: Unexpected EOF during reading XmlDecl."#,
        true,
    );
}

#[test]
fn bad_1() {
    test(
        br#"<?xml&.,"#,
        br#"1:6 Error: Unexpected EOF during reading XmlDecl."#,
        true,
    );
}

#[test]
fn dashes_in_comments() {
    test(
        br#"<hello/>"#,
        br#"
        |Error: Unexpected token '--'
        "#,
        true,
    );

    test(
        br#"<hello/>"#,
        br#"
        |Error: Unexpected token '--'
        "#,
        true,
    );
}

#[test]
fn tabs_1() {
    test(
        b"\t\t",
        br#"
            StartElement(a)
            EmptyElement(b)
            EndElement(a)
            EndDocument
        "#,
        true,
    );
}

#[test]
fn issue_83_duplicate_attributes() {
    // Error when parsing attributes won't stop main event reader
    // as it is a lazy operation => add ending events
    test(
        br#"<hello><some-tag a='10' a="20"/></hello>"#,
        b"
            |StartElement(hello)
            |1:30 EmptyElement(some-tag, attr-error: error while parsing \
                  attribute at position 16: Duplicate attribute at position 9 and 16)
            |EndElement(hello)
            |EndDocument
        ",
        true,
    );
}

#[test]
fn issue_93_large_characters_in_entity_references() {
    test(
        r#"<hello>&𤶼;</hello>"#.as_bytes(),
        r#"
            |StartElement(hello)
            |1:10 FailedUnescape([38, 240, 164, 182, 188, 59]; Error while escaping character at range 1..5: Unrecognized escape symbol: Ok("𤶼"))
            |EndElement(hello)
            |EndDocument
        "#
        .as_bytes(),
        true,
    )
}

#[test]
fn issue_98_cdata_ending_with_right_bracket() {
    test(
        br#"<hello><![CDATA[Foo [Bar]]]></hello>"#,
        br#"
            |StartElement(hello)
            |Characters()
            |CData(Foo [Bar])
            |Characters()
            |EndElement(hello)
            |EndDocument
        "#,
        false,
    )
}

#[test]
fn issue_105_unexpected_double_dash() {
    test(
        br#"<hello>-- </hello>"#,
        br#"
            |StartElement(hello)
            |Characters(-- )
            |EndElement(hello)
            |EndDocument
        "#,
        false,
    );

    test(
        br#"<hello>--</hello>"#,
        br#"
            |StartElement(hello)
            |Characters(--)
            |EndElement(hello)
            |EndDocument
        "#,
        false,
    );

    test(
        br#"<hello>--></hello>"#,
        br#"
            |StartElement(hello)
            |Characters(-->)
            |EndElement(hello)
            |EndDocument
        "#,
        false,
    );

    test(
        br#"<hello><![CDATA[--]]></hello>"#,
        br#"
            |StartElement(hello)
            |Characters()
            |CData(--)
            |Characters()
            |EndElement(hello)
            |EndDocument
        "#,
        false,
    );
}

#[test]
fn issue_attributes_have_no_default_namespace() {
    // At the moment, the 'test' method doesn't render namespaces for attribute names.
    // This test only checks whether the default namespace got applied to the EmptyElement.
    test(
        br#"<hello xmlns="urn:foo" x="y"/>"#,
        br#"
             |EmptyElement({urn:foo}hello [x="y"])
             |EndDocument
         "#,
        true,
    );
}

#[test]
fn issue_default_namespace_on_outermost_element() {
    // Regression test
    test(
        br#"<hello xmlns="urn:foo"/>"#,
        br#"
                |EmptyElement({urn:foo}hello)
                |EndDocument
            "#,
        true,
    );
}

#[test]
fn default_namespace_applies_to_end_elem() {
    test(
        br#"<hello xmlns="urn:foo" x="y">
              <inner/>
            </hello>"#,
        br#"
            |StartElement({urn:foo}hello [x="y"])
            |EmptyElement({urn:foo}inner)
            |EndElement({urn:foo}hello)
            |EndDocument
        "#,
        true,
    );
}

fn test(input: &[u8], output: &[u8], is_short: bool) {
    let mut reader = Reader::from_reader(input);
    reader
        .trim_text(is_short)
        .check_comments(true)
        .expand_empty_elements(false);

    let mut spec_lines = SpecIter(output).enumerate();
    let mut buf = Vec::new();
    let mut ns_buffer = Vec::new();

    if !is_short {
        // discard first whitespace
        reader.read_event(&mut buf).unwrap();
    }

    loop {
        buf.clear();
        let event = reader.read_namespaced_event(&mut buf, &mut ns_buffer);
        let line = xmlrs_display(&event);
        if let Some((n, spec)) = spec_lines.next() {
            if spec.trim() == "EndDocument" {
                break;
            }
            if line.trim() != spec.trim() {
                panic!(
                    "\n-------------------\n\
                     Unexpected event at line {}:\n\
                     Expected: {}\nFound: {}\n\
                     -------------------\n",
                    n + 1,
                    spec,
                    line
                );
            }
        } else {
            if line == "EndDocument" {
                break;
            }
            panic!("Unexpected event: {}", line);
        }

        if !is_short && line.starts_with("StartDocument") {
            // advance next Characters(empty space) ...
            if let Ok(Event::Text(ref e)) = reader.read_event(&mut Vec::new()) {
                if e.iter().any(|b| match *b {
                    b' ' | b'\r' | b'\n' | b'\t' => false,
                    _ => true,
                }) {
                    panic!("Reader expects empty Text event after a StartDocument");
                }
            } else {
                panic!("Reader expects empty Text event after a StartDocument");
            }
        }
    }
}

fn namespace_name(n: &Option<&[u8]>, name: &[u8]) -> String {
    match *n {
        Some(n) => format!("{{{}}}{}", from_utf8(n).unwrap(), from_utf8(name).unwrap()),
        None => from_utf8(name).unwrap().to_owned(),
    }
}

fn make_attrs(e: &BytesStart) -> ::std::result::Result<String, String> {
    let mut atts = Vec::new();
    for a in e.attributes() {
        match a {
            Ok(a) => {
                if a.key.len() < 5 || !a.key.starts_with(b"xmlns") {
                    atts.push(format!(
                        "{}=\"{}\"",
                        from_utf8(a.key).unwrap(),
                        from_utf8(&*a.unescaped_value().unwrap()).unwrap()
                    ));
                }
            }
            Err(e) => return Err(e.to_string()),
        }
    }
    Ok(atts.join(", "))
}

fn xmlrs_display(opt_event: &Result<(Option<&[u8]>, Event)>) -> String {
    match opt_event {
        Ok((ref n, Event::Start(ref e))) => {
            let name = namespace_name(n, e.name());
            match make_attrs(e) {
                Ok(ref attrs) if attrs.is_empty() => format!("StartElement({})", &name),
                Ok(ref attrs) => format!("StartElement({} [{}])", &name, &attrs),
                Err(e) => format!("StartElement({}, attr-error: {})", &name, &e),
            }
        }
        Ok((ref n, Event::Empty(ref e))) => {
            let name = namespace_name(n, e.name());
            match make_attrs(e) {
                Ok(ref attrs) if attrs.is_empty() => format!("EmptyElement({})", &name),
                Ok(ref attrs) => format!("EmptyElement({} [{}])", &name, &attrs),
                Err(e) => format!("EmptyElement({}, attr-error: {})", &name, &e),
            }
        }
        Ok((ref n, Event::End(ref e))) => format!("EndElement({})", namespace_name(n, e.name())),
        Ok((_, Event::Comment(ref e))) => format!("Comment({})", from_utf8(e).unwrap()),
        Ok((_, Event::CData(ref e))) => format!("CData({})", from_utf8(e).unwrap()),
        Ok((_, Event::Text(ref e))) => match e.unescaped() {
            Ok(c) => match from_utf8(&*c) {
                Ok(c) => format!("Characters({})", c),
                Err(ref err) => format!("InvalidUtf8({:?}; {})", e.escaped(), err),
            },
            Err(ref err) => format!("FailedUnescape({:?}; {})", e.escaped(), err),
        },
        Ok((_, Event::Decl(ref e))) => {
            let version_cow = e.version().unwrap();
            let version = from_utf8(version_cow.as_ref()).unwrap();
            let encoding_cow = e.encoding().unwrap().unwrap();
            let encoding = from_utf8(encoding_cow.as_ref()).unwrap();
            format!("StartDocument({}, {})", version, encoding)
        }
        Ok((_, Event::Eof)) => format!("EndDocument"),
        Ok((_, Event::PI(ref e))) => format!("ProcessingInstruction(PI={})", from_utf8(e).unwrap()),
        Err(ref e) => format!("Error: {}", e),
        Ok((_, Event::DocType(ref e))) => format!("DocType({})", from_utf8(e).unwrap()),
    }
}

struct SpecIter<'a>(&'a [u8]);

impl<'a> Iterator for SpecIter<'a> {
    type Item = &'a str;
    fn next(&mut self) -> Option<&'a str> {
        let start = self
            .0
            .iter()
            .position(|b| !matches!(*b, b' ' | b'\r' | b'\n' | b'\t' | b'|' | b':' | b'0'..=b'9'))
            .unwrap_or(0);

        if let Some(p) = self.0.windows(3).position(|w| w == b")\r\n") {
            let (prev, next) = self.0.split_at(p + 1);
            self.0 = &next[1..];
            Some(from_utf8(&prev[start..]).expect("Error decoding to uft8"))
        } else if let Some(p) = self.0.windows(2).position(|w| w == b")\n") {
            let (prev, next) = self.0.split_at(p + 1);
            self.0 = next;
            Some(from_utf8(&prev[start..]).expect("Error decoding to uft8"))
        } else if self.0.is_empty() {
            None
        } else {
            let p = self.0;
            self.0 = &[];
            Some(from_utf8(&p[start..]).unwrap())
        }
    }
}
<commit_msg>Ignore failing escape-html tests<commit_after>extern crate quick_xml;

use quick_xml::events::{BytesStart, Event};
use quick_xml::{Reader, Result};
use std::str::from_utf8;

#[test]
fn sample_1_short() {
    test(
        include_bytes!("documents/sample_1.xml"),
        include_bytes!("documents/sample_1_short.txt"),
        true,
    );
}

#[test]
fn sample_1_full() {
    test(
        include_bytes!("documents/sample_1.xml"),
        include_bytes!("documents/sample_1_full.txt"),
        false,
    );
}

#[test]
fn sample_2_short() {
    test(
        include_bytes!("documents/sample_2.xml"),
        include_bytes!("documents/sample_2_short.txt"),
        true,
    );
}

#[test]
fn sample_2_full() {
    test(
        include_bytes!("documents/sample_2.xml"),
        include_bytes!("documents/sample_2_full.txt"),
        false,
    );
}

#[cfg(all(not(windows), feature = "escape-html"))]
#[test]
// FIXME: Fails with:
// ```
// Unexpected event at line 6:
// Expected: InvalidUtf8([10, 38, 110, 98, 115, 112, 59, 10]; invalid utf-8 sequence of 1 bytes from index 1)
// Found: Characters(
//
// )
// ```
#[ignore]
fn html5() {
    test(
        include_bytes!("documents/html5.html"),
        include_bytes!("documents/html5.txt"),
        false,
    );
}

#[cfg(all(windows, feature = "escape-html"))]
#[test]
// FIXME: Fails the same way as the one above
#[ignore]
fn html5() {
    test(
        include_bytes!("documents/html5.html"),
        include_bytes!("documents/html5-windows.txt"),
        false,
    );
}

// #[test]
// fn sample_3_short() {
//     test(
//         include_bytes!("documents/sample_3.xml"),
//         include_bytes!("documents/sample_3_short.txt"),
//         true
//     );
// }

// #[test]
// fn sample_3_full() {
//     test(
//         include_bytes!("documents/sample_3.xml"),
//         include_bytes!("documents/sample_3_full.txt"),
//         false
//     );
// }

// #[test]
// fn sample_4_short() {
//     test(
//         include_bytes!("documents/sample_4.xml"),
//         include_bytes!("documents/sample_4_short.txt"),
//         true
//     );
// }

// #[test]
// fn sample_4_full() {
//     test(
//         include_bytes!("documents/sample_4.xml"),
//         include_bytes!("documents/sample_4_full.txt"),
//         false
//     );
//
// }

#[test]
fn sample_ns_short() {
    test(
        include_bytes!("documents/sample_ns.xml"),
        include_bytes!("documents/sample_ns_short.txt"),
        true,
    );
}

#[test]
fn eof_1() {
    test(
        br#"<?xml"#,
        br#"Error: Unexpected EOF during reading XmlDecl."#,
        true,
    );
}

#[test]
fn bad_1() {
    test(
        br#"<?xml&.,"#,
        br#"1:6 Error: Unexpected EOF during reading XmlDecl."#,
        true,
    );
}

#[test]
fn dashes_in_comments() {
    test(
        br#"<hello/>"#,
        br#"
        |Error: Unexpected token '--'
        "#,
        true,
    );

    test(
        br#"<hello/>"#,
        br#"
        |Error: Unexpected token '--'
        "#,
        true,
    );
}

#[test]
fn tabs_1() {
    test(
        b"\t\t",
        br#"
            StartElement(a)
            EmptyElement(b)
            EndElement(a)
            EndDocument
        "#,
        true,
    );
}

#[test]
fn issue_83_duplicate_attributes() {
    // Error when parsing attributes won't stop main event reader
    // as it is a lazy operation => add ending events
    test(
        br#"<hello><some-tag a='10' a="20"/></hello>"#,
        b"
            |StartElement(hello)
            |1:30 EmptyElement(some-tag, attr-error: error while parsing \
                  attribute at position 16: Duplicate attribute at position 9 and 16)
            |EndElement(hello)
            |EndDocument
        ",
        true,
    );
}

#[test]
fn issue_93_large_characters_in_entity_references() {
    test(
        r#"<hello>&𤶼;</hello>"#.as_bytes(),
        r#"
            |StartElement(hello)
            |1:10 FailedUnescape([38, 240, 164, 182, 188, 59]; Error while escaping character at range 1..5: Unrecognized escape symbol: Ok("𤶼"))
            |EndElement(hello)
            |EndDocument
        "#
        .as_bytes(),
        true,
    )
}

#[test]
fn issue_98_cdata_ending_with_right_bracket() {
    test(
        br#"<hello><![CDATA[Foo [Bar]]]></hello>"#,
        br#"
            |StartElement(hello)
            |Characters()
            |CData(Foo [Bar])
            |Characters()
            |EndElement(hello)
            |EndDocument
        "#,
        false,
    )
}

#[test]
fn issue_105_unexpected_double_dash() {
    test(
        br#"<hello>-- </hello>"#,
        br#"
            |StartElement(hello)
            |Characters(-- )
            |EndElement(hello)
            |EndDocument
        "#,
        false,
    );

    test(
        br#"<hello>--</hello>"#,
        br#"
            |StartElement(hello)
            |Characters(--)
            |EndElement(hello)
            |EndDocument
        "#,
        false,
    );

    test(
        br#"<hello>--></hello>"#,
        br#"
            |StartElement(hello)
            |Characters(-->)
            |EndElement(hello)
            |EndDocument
        "#,
        false,
    );

    test(
        br#"<hello><![CDATA[--]]></hello>"#,
        br#"
            |StartElement(hello)
            |Characters()
            |CData(--)
            |Characters()
            |EndElement(hello)
            |EndDocument
        "#,
        false,
    );
}

#[test]
fn issue_attributes_have_no_default_namespace() {
    // At the moment, the 'test' method doesn't render namespaces for attribute names.
    // This test only checks whether the default namespace got applied to the EmptyElement.
    test(
        br#"<hello xmlns="urn:foo" x="y"/>"#,
        br#"
             |EmptyElement({urn:foo}hello [x="y"])
             |EndDocument
         "#,
        true,
    );
}

#[test]
fn issue_default_namespace_on_outermost_element() {
    // Regression test
    test(
        br#"<hello xmlns="urn:foo"/>"#,
        br#"
                |EmptyElement({urn:foo}hello)
                |EndDocument
            "#,
        true,
    );
}

#[test]
fn default_namespace_applies_to_end_elem() {
    test(
        br#"<hello xmlns="urn:foo" x="y">
              <inner/>
            </hello>"#,
        br#"
            |StartElement({urn:foo}hello [x="y"])
            |EmptyElement({urn:foo}inner)
            |EndElement({urn:foo}hello)
            |EndDocument
        "#,
        true,
    );
}

fn test(input: &[u8], output: &[u8], is_short: bool) {
    let mut reader = Reader::from_reader(input);
    reader
        .trim_text(is_short)
        .check_comments(true)
        .expand_empty_elements(false);

    let mut spec_lines = SpecIter(output).enumerate();
    let mut buf = Vec::new();
    let mut ns_buffer = Vec::new();

    if !is_short {
        // discard first whitespace
        reader.read_event(&mut buf).unwrap();
    }

    loop {
        buf.clear();
        let event = reader.read_namespaced_event(&mut buf, &mut ns_buffer);
        let line = xmlrs_display(&event);
        if let Some((n, spec)) = spec_lines.next() {
            if spec.trim() == "EndDocument" {
                break;
            }
            if line.trim() != spec.trim() {
                panic!(
                    "\n-------------------\n\
                     Unexpected event at line {}:\n\
                     Expected: {}\nFound: {}\n\
                     -------------------\n",
                    n + 1,
                    spec,
                    line
                );
            }
        } else {
            if line == "EndDocument" {
                break;
            }
            panic!("Unexpected event: {}", line);
        }

        if !is_short && line.starts_with("StartDocument") {
            // advance next Characters(empty space) ...
            if let Ok(Event::Text(ref e)) = reader.read_event(&mut Vec::new()) {
                if e.iter().any(|b| match *b {
                    b' ' | b'\r' | b'\n' | b'\t' => false,
                    _ => true,
                }) {
                    panic!("Reader expects empty Text event after a StartDocument");
                }
            } else {
                panic!("Reader expects empty Text event after a StartDocument");
            }
        }
    }
}

fn namespace_name(n: &Option<&[u8]>, name: &[u8]) -> String {
    match *n {
        Some(n) => format!("{{{}}}{}", from_utf8(n).unwrap(), from_utf8(name).unwrap()),
        None => from_utf8(name).unwrap().to_owned(),
    }
}

fn make_attrs(e: &BytesStart) -> ::std::result::Result<String, String> {
    let mut atts = Vec::new();
    for a in e.attributes() {
        match a {
            Ok(a) => {
                if a.key.len() < 5 || !a.key.starts_with(b"xmlns") {
                    atts.push(format!(
                        "{}=\"{}\"",
                        from_utf8(a.key).unwrap(),
                        from_utf8(&*a.unescaped_value().unwrap()).unwrap()
                    ));
                }
            }
            Err(e) => return Err(e.to_string()),
        }
    }
    Ok(atts.join(", "))
}

fn xmlrs_display(opt_event: &Result<(Option<&[u8]>, Event)>) -> String {
    match opt_event {
        Ok((ref n, Event::Start(ref e))) => {
            let name = namespace_name(n, e.name());
            match make_attrs(e) {
                Ok(ref attrs) if attrs.is_empty() => format!("StartElement({})", &name),
                Ok(ref attrs) => format!("StartElement({} [{}])", &name, &attrs),
                Err(e) => format!("StartElement({}, attr-error: {})", &name, &e),
            }
        }
        Ok((ref n, Event::Empty(ref e))) => {
            let name = namespace_name(n, e.name());
            match make_attrs(e) {
                Ok(ref attrs) if attrs.is_empty() => format!("EmptyElement({})", &name),
                Ok(ref attrs) => format!("EmptyElement({} [{}])", &name, &attrs),
                Err(e) => format!("EmptyElement({}, attr-error: {})", &name, &e),
            }
        }
        Ok((ref n, Event::End(ref e))) => format!("EndElement({})", namespace_name(n, e.name())),
        Ok((_, Event::Comment(ref e))) => format!("Comment({})", from_utf8(e).unwrap()),
        Ok((_, Event::CData(ref e))) => format!("CData({})", from_utf8(e).unwrap()),
        Ok((_, Event::Text(ref e))) => match e.unescaped() {
            Ok(c) => match from_utf8(&*c) {
                Ok(c) => format!("Characters({})", c),
                Err(ref err) => format!("InvalidUtf8({:?}; {})", e.escaped(), err),
            },
            Err(ref err) => format!("FailedUnescape({:?}; {})", e.escaped(), err),
        },
        Ok((_, Event::Decl(ref e))) => {
            let version_cow = e.version().unwrap();
            let version = from_utf8(version_cow.as_ref()).unwrap();
            let encoding_cow = e.encoding().unwrap().unwrap();
            let encoding = from_utf8(encoding_cow.as_ref()).unwrap();
            format!("StartDocument({}, {})", version, encoding)
        }
        Ok((_, Event::Eof)) => format!("EndDocument"),
        Ok((_, Event::PI(ref e))) => format!("ProcessingInstruction(PI={})", from_utf8(e).unwrap()),
        Err(ref e) => format!("Error: {}", e),
        Ok((_, Event::DocType(ref e))) => format!("DocType({})", from_utf8(e).unwrap()),
    }
}

struct SpecIter<'a>(&'a [u8]);

impl<'a> Iterator for SpecIter<'a> {
    type Item = &'a str;
    fn next(&mut self) -> Option<&'a str> {
        let start = self
            .0
            .iter()
            .position(|b| !matches!(*b, b' ' | b'\r' | b'\n' | b'\t' | b'|' | b':' | b'0'..=b'9'))
            .unwrap_or(0);

        if let Some(p) = self.0.windows(3).position(|w| w == b")\r\n") {
            let (prev, next) = self.0.split_at(p + 1);
            self.0 = &next[1..];
            Some(from_utf8(&prev[start..]).expect("Error decoding to uft8"))
        } else if let Some(p) = self.0.windows(2).position(|w| w == b")\n") {
            let (prev, next) = self.0.split_at(p + 1);
            self.0 = next;
            Some(from_utf8(&prev[start..]).expect("Error decoding to uft8"))
        } else if self.0.is_empty() {
            None
        } else {
            let p = self.0;
            self.0 = &[];
            Some(from_utf8(&p[start..]).unwrap())
        }
    }
}
<|endoftext|>


<commit_before>+ foo
- Bar!

+ hello
- Hi there!

+ back
- Try again

+ *
- {topic=dummy} {@unknown}
<commit_msg>Changed<commit_after>+ foo
- Bar?

+ hello
- Hi there!

+ back
- Try again

+ *
- {topic=dummy} {@unknown}
<|endoftext|>


<commit_before><commit_msg>Remove reference comment in decode()<commit_after><|endoftext|>


<commit_before><commit_msg>Add wrapping arithmetic to certain instructions<commit_after><|endoftext|>


<commit_before>//! Implements DMA (Direct Memory Access). DMA can be set up by the CPU and either immediately
//! stops the CPU and performs the transfer. HDMA can be set up to perform one transfer per H-Blank
//! per channel.
//!
//! HDMA needs to be coordinated with the PPU: HDMA needs to be initialized when a new frame starts
//! and transfers data after every scanline.

use snes::Peripherals;

/// The configuration of a DMA channel
#[derive(Clone, Copy)]
pub struct DmaChannel {
    /// $43x0 - DMA parameters
    /// ```
    /// da-ssttt
    /// d: Direction (0: A->B, 1: B->A)
    /// a: Use indirect HDMA table
    /// s: A-bus address increment (00: +1, 01/11: 0, 10: -1)
    /// t: See `TransferMode`
    /// ```
    params: u8,
    /// $43x2/$43x3 - Bus A address
    a_addr: u16,
    /// $43x4 - Bus A bank
    a_addr_bank: u8,
    /// $43x1 - The bus B ("PPU bus") address to access
    b_addr: u8,
    /// $43x5/43x6 - DMA size/HDMA indirect address
    ///
    /// DMA transfer size in bytes. A size of 0 will result in a transfer of 65536 Bytes. This is a
    /// hard limit: If the transfer mode would transfer more bytes, the transfer is stopped before.
    /// This value is decremented during DMA and will end up at 0 when DMA is complete.
    dma_size: u16,
    /// $43x7 - HDMA indirect address bank
    hdma_indirect_bank: u8,
}

use self::TransferMode::*;

/// Describes how a single DMA unit (max. 4 Bytes) is transferred
#[derive(Clone, Copy, Debug)]
pub enum TransferMode {
    /// Just writes a single byte
    OneOnce,
    /// Read one Byte and writes it twice
    OneTwice,
    /// Reads two bytes and writes them to the destination
    TwoOnce,
    /// Does `OneTwice` two times: Reads a byte, writes it twice, reads another byte, writes it
    /// twice.
    TwoTwice,
    /// Reads two Bytes, A and B. Writes A, B, A, B.
    TwoTwiceAlternate,
    /// Reads and writes 4 Bytes.
    FourOnce,
}

impl DmaChannel {
    pub fn new() -> DmaChannel {
        DmaChannel {
            params: 0xff,
            a_addr: 0xffff,
            a_addr_bank: 0xff,
            b_addr: 0xff,
            dma_size: 0xffff,
            hdma_indirect_bank: 0xff,
        }
    }

    /// Load from `$43xN`, where `x` is the number of this DMA channel, and `N` is passed as
    /// `addr`.
    pub fn load(&self, reg: u8) -> u8 {
        match reg {
            0x0 => self.params,
            0x1 => self.b_addr,
            0x2 => self.a_addr as u8,
            0x3 => (self.a_addr >> 8) as u8,
            0x4 => self.a_addr_bank,
            0x5 => self.dma_size as u8,
            0x6 => (self.dma_size >> 8) as u8,
            0x7 => self.hdma_indirect_bank,
            _ => panic!("invalid DMA channel register ${:02X}", reg),
        }
    }

    pub fn store(&mut self, reg: u8, val: u8) {
        match reg {
            0x0 => self.params = val,
            0x1 => self.b_addr = val,
            0x2 => self.a_addr = (self.a_addr & 0xff00) | val as u16,
            0x3 => self.a_addr = (self.a_addr & 0x00ff) | ((val as u16) << 8),
            0x4 => self.a_addr_bank = val,
            0x5 => self.dma_size = (self.dma_size & 0xff00) | val as u16,
            0x6 => self.dma_size = (self.dma_size & 0x00ff) | ((val as u16) << 8),
            0x7 => self.hdma_indirect_bank = val,
            _ => panic!("invalid DMA channel register ${:02X}", reg),
        }
    }

    /// Returns `true` if this channel is configured to read from address bus B and write to bus A.
    /// If this returns `false`, the opposite transfer direction is configured.
    fn write_to_a(&self) -> bool { self.params & 0x80 != 0 }

    /// Returns the address increment step for the A bus address. Can be `-1`, `0` or `1`.
    fn a_addr_increment(&self) -> i8 {
        match (self.params >> 3) & 0b11 {
            0b00 => 1,
            0b10 => -1,
            _ => 0,
        }
    }

    /// Returns the transfer size in bytes. Note that this limits the number of bytes, even if the
    /// transfer mode would transfer more bytes.
    fn transfer_size(&self) -> u32 {
        if self.dma_size == 0xffff { 65536 } else { self.dma_size as u32 }
    }

    fn transfer_mode(&self) -> TransferMode {
        match self.params & 0b111 {
            0 => OneOnce,
            1 => TwoOnce,
            2|6 => OneTwice,
            3|7 => TwoTwice,
            4 => FourOnce,
            5 => TwoTwiceAlternate,
            _ => panic!("invalid DMA transfer mode: ${:02X}", self.params & 0b111),
        }
    }
}

/// Performs all DMA transactions enabled by the given bitmask. Returns the number of master cycles
/// spent.
pub fn do_dma(p: &mut Peripherals, channels: u8) -> u32 {
    use std::cell::Cell;

    if channels == 0 { return 0 }

    // FIXME: "Now, after the pause, wait 2-8 master cycles to reach a whole multiple of 8 master
    // cycles since reset."
    // (Since this is pretty unpredictable behaviour, nothing should rely on it - I hope)

    let mut dma_cy = 8; // 8 cycles overhead for any DMA transaction

    for i in 0..8 {
        if channels & (1 << i) != 0 {
            dma_cy += 8;    // 8 cycles per active channel

            let chan = p.dma[i];
            let write_to_a = chan.write_to_a();
            let mode = chan.transfer_mode();
            let bytes = Cell::new(chan.transfer_size());
            let a_addr_inc = chan.a_addr_increment();

            let src_bank = if write_to_a { 0 } else { chan.a_addr_bank };
            let mut src_addr = if write_to_a {
                0x2100 + chan.b_addr as u16
            } else {
                chan.a_addr
            };
            let dest_bank = if write_to_a { chan.a_addr_bank } else { 0 };
            let mut dest_addr = if write_to_a {
                chan.a_addr
            } else {
                0x2100 + chan.b_addr as u16
            };

            trace!("DMA on channel {} with {} bytes in mode {:?}, inc {} ({}), \
                from ${:02X}:{:04X} to ${:02X}:{:04X}",
                i, bytes.get(), mode, a_addr_inc, if write_to_a {"B->A"} else {"A->B"}, src_bank,
                src_addr, dest_bank, dest_addr);

            let mut read_byte = |p: &mut Peripherals| {
                let byte = p.load(src_bank, src_addr);
                if !write_to_a {
                    // adjust `src_addr`
                    src_addr = (src_addr as i32 + a_addr_inc as i32) as u16;
                }
                byte
            };
            let mut write_byte = |p: &mut Peripherals, byte| {
                if bytes.get() == 0 { return }
                p.store(dest_bank, dest_addr, byte);
                bytes.set(bytes.get() - 1);
                if write_to_a {
                    // adjust `dest_addr`
                    dest_addr = (dest_addr as i32 + a_addr_inc as i32) as u16;
                }
            };

            dma_cy += bytes.get() * 8;  // 8 master cycles per byte
            while bytes.get() > 0 {
                match mode {
                    /// Just reads and writes a single byte
                    OneOnce => {
                        let b = read_byte(p);
                        write_byte(p, b);
                    }
                    /// Read one Byte and writes it twice
                    OneTwice => {
                        let b = read_byte(p);
                        write_byte(p, b);
                        write_byte(p, b);
                    }
                    /// Reads two bytes and writes them to the destination
                    TwoOnce => {
                        let b = read_byte(p);
                        write_byte(p, b);
                        let b = read_byte(p);
                        write_byte(p, b);
                    }
                    /// Does `OneTwice` two times: Reads a byte, writes it twice, reads another byte,
                    /// writes it twice.
                    TwoTwice => {
                        let b = read_byte(p);
                        write_byte(p, b);
                        write_byte(p, b);
                        let b = read_byte(p);
                        write_byte(p, b);
                        write_byte(p, b);
                    }
                    /// Reads two Bytes, A and B. Writes A, B, A, B.
                    TwoTwiceAlternate => {
                        let a = read_byte(p);
                        let b = read_byte(p);
                        write_byte(p, a);
                        write_byte(p, b);
                        write_byte(p, a);
                        write_byte(p, b);
                    }
                    /// Reads and writes 4 Bytes.
                    FourOnce => {
                        let b = read_byte(p);
                        write_byte(p, b);
                        let b = read_byte(p);
                        write_byte(p, b);
                        let b = read_byte(p);
                        write_byte(p, b);
                        let b = read_byte(p);
                        write_byte(p, b);
                    }
                }
            }

            p.dma[i].dma_size = 0;
        }
    }

    trace!("DMA completed after {} master clock cycles", dma_cy);

    dma_cy
}
<commit_msg>Factor out DMA transaction code<commit_after>//! Implements DMA (Direct Memory Access). DMA can be set up by the CPU and either immediately
//! stops the CPU and performs the transfer. HDMA can be set up to perform one transfer per H-Blank
//! per channel.
//!
//! HDMA needs to be coordinated with the PPU: HDMA needs to be initialized when a new frame starts
//! and transfers data after every scanline.

use snes::Peripherals;

/// The configuration of a DMA channel
#[derive(Clone, Copy)]
pub struct DmaChannel {
    /// $43x0 - DMA parameters
    /// ```
    /// da-ssttt
    /// d: Direction (0: A->B, 1: B->A)
    /// a: Use indirect HDMA table
    /// s: A-bus address increment (00: +1, 01/11: 0, 10: -1)
    /// t: See `TransferMode`
    /// ```
    params: u8,
    /// $43x2/$43x3 - Bus A address
    a_addr: u16,
    /// $43x4 - Bus A bank
    a_addr_bank: u8,
    /// $43x1 - The bus B ("PPU bus") address to access
    b_addr: u8,
    /// $43x5/43x6 - DMA size/HDMA indirect address
    ///
    /// DMA transfer size in bytes. A size of 0 will result in a transfer of 65536 Bytes. This is a
    /// hard limit: If the transfer mode would transfer more bytes, the transfer is stopped before.
    /// This value is decremented during DMA and will end up at 0 when DMA is complete.
    dma_size: u16,
    /// $43x7 - HDMA indirect address bank
    hdma_indirect_bank: u8,
}

use self::TransferMode::*;

/// Describes how a single DMA unit (max. 4 Bytes) is transferred
#[derive(Clone, Copy, Debug)]
pub enum TransferMode {
    /// Just writes a single byte
    OneOnce,
    /// Read one Byte and writes it twice
    OneTwice,
    /// Reads two bytes and writes them to the destination
    TwoOnce,
    /// Does `OneTwice` two times: Reads a byte, writes it twice, reads another byte, writes it
    /// twice.
    TwoTwice,
    /// Reads two Bytes, A and B. Writes A, B, A, B.
    TwoTwiceAlternate,
    /// Reads and writes 4 Bytes.
    FourOnce,
}

impl DmaChannel {
    pub fn new() -> DmaChannel {
        DmaChannel {
            params: 0xff,
            a_addr: 0xffff,
            a_addr_bank: 0xff,
            b_addr: 0xff,
            dma_size: 0xffff,
            hdma_indirect_bank: 0xff,
        }
    }

    /// Load from `$43xN`, where `x` is the number of this DMA channel, and `N` is passed as
    /// `addr`.
    pub fn load(&self, reg: u8) -> u8 {
        match reg {
            0x0 => self.params,
            0x1 => self.b_addr,
            0x2 => self.a_addr as u8,
            0x3 => (self.a_addr >> 8) as u8,
            0x4 => self.a_addr_bank,
            0x5 => self.dma_size as u8,
            0x6 => (self.dma_size >> 8) as u8,
            0x7 => self.hdma_indirect_bank,
            _ => panic!("invalid DMA channel register ${:02X}", reg),
        }
    }

    pub fn store(&mut self, reg: u8, val: u8) {
        match reg {
            0x0 => self.params = val,
            0x1 => self.b_addr = val,
            0x2 => self.a_addr = (self.a_addr & 0xff00) | val as u16,
            0x3 => self.a_addr = (self.a_addr & 0x00ff) | ((val as u16) << 8),
            0x4 => self.a_addr_bank = val,
            0x5 => self.dma_size = (self.dma_size & 0xff00) | val as u16,
            0x6 => self.dma_size = (self.dma_size & 0x00ff) | ((val as u16) << 8),
            0x7 => self.hdma_indirect_bank = val,
            _ => panic!("invalid DMA channel register ${:02X}", reg),
        }
    }

    /// Returns `true` if this channel is configured to read from address bus B and write to bus A.
    /// If this returns `false`, the opposite transfer direction is configured.
    fn write_to_a(&self) -> bool { self.params & 0x80 != 0 }

    /// Returns the address increment step for the A bus address. Can be `-1`, `0` or `1`.
    fn a_addr_increment(&self) -> i8 {
        match (self.params >> 3) & 0b11 {
            0b00 => 1,
            0b10 => -1,
            _ => 0,
        }
    }

    /// Returns the transfer size in bytes. Note that this limits the number of bytes, even if the
    /// transfer mode would transfer more bytes.
    fn transfer_size(&self) -> u32 {
        if self.dma_size == 0xffff { 65536 } else { self.dma_size as u32 }
    }

    fn transfer_mode(&self) -> TransferMode {
        match self.params & 0b111 {
            0 => OneOnce,
            1 => TwoOnce,
            2|6 => OneTwice,
            3|7 => TwoTwice,
            4 => FourOnce,
            5 => TwoTwiceAlternate,
            _ => panic!("invalid DMA transfer mode: ${:02X}", self.params & 0b111),
        }
    }
}

/// Perform a single DMA transaction according to `mode`. Reads and writes up to 4 bytes using the
/// given read/write functions.
fn dma_transaction<R, W>(p: &mut Peripherals,
                         mode: TransferMode,
                         read_byte: &mut R,
                         write_byte: &mut W)
                         where R: FnMut(&mut Peripherals) -> u8, W: FnMut(&mut Peripherals, u8) {
    match mode {
        /// Just reads and writes a single byte
        OneOnce => {
            let b = read_byte(p);
            write_byte(p, b);
        }
        /// Read one Byte and writes it twice
        OneTwice => {
            let b = read_byte(p);
            write_byte(p, b);
            write_byte(p, b);
        }
        /// Reads two bytes and writes them to the destination
        TwoOnce => {
            let b = read_byte(p);
            write_byte(p, b);
            let b = read_byte(p);
            write_byte(p, b);
        }
        /// Does `OneTwice` two times: Reads a byte, writes it twice, reads another byte,
        /// writes it twice.
        TwoTwice => {
            let b = read_byte(p);
            write_byte(p, b);
            write_byte(p, b);
            let b = read_byte(p);
            write_byte(p, b);
            write_byte(p, b);
        }
        /// Reads two Bytes, A and B. Writes A, B, A, B.
        TwoTwiceAlternate => {
            let a = read_byte(p);
            let b = read_byte(p);
            write_byte(p, a);
            write_byte(p, b);
            write_byte(p, a);
            write_byte(p, b);
        }
        /// Reads and writes 4 Bytes.
        FourOnce => {
            let b = read_byte(p);
            write_byte(p, b);
            let b = read_byte(p);
            write_byte(p, b);
            let b = read_byte(p);
            write_byte(p, b);
            let b = read_byte(p);
            write_byte(p, b);
        }
    }
}

/// Performs all DMA transactions enabled by the given bitmask. Returns the number of master cycles
/// spent.
pub fn do_dma(p: &mut Peripherals, channels: u8) -> u32 {
    use std::cell::Cell;

    if channels == 0 { return 0 }

    // FIXME: "Now, after the pause, wait 2-8 master cycles to reach a whole multiple of 8 master
    // cycles since reset."
    // (Since this is pretty unpredictable behaviour, nothing should rely on it - I hope)

    let mut dma_cy = 8; // 8 cycles overhead for any DMA transaction

    for i in 0..8 {
        if channels & (1 << i) != 0 {
            dma_cy += 8;    // 8 cycles per active channel

            let chan = p.dma[i];
            let write_to_a = chan.write_to_a();
            let mode = chan.transfer_mode();
            let bytes = Cell::new(chan.transfer_size());
            let a_addr_inc = chan.a_addr_increment();

            let src_bank = if write_to_a { 0 } else { chan.a_addr_bank };
            let mut src_addr = if write_to_a {
                0x2100 + chan.b_addr as u16
            } else {
                chan.a_addr
            };
            let dest_bank = if write_to_a { chan.a_addr_bank } else { 0 };
            let mut dest_addr = if write_to_a {
                chan.a_addr
            } else {
                0x2100 + chan.b_addr as u16
            };

            trace!("DMA on channel {} with {} bytes in mode {:?}, inc {} ({}), \
                from ${:02X}:{:04X} to ${:02X}:{:04X}",
                i, bytes.get(), mode, a_addr_inc, if write_to_a {"B->A"} else {"A->B"}, src_bank,
                src_addr, dest_bank, dest_addr);

            let mut read_byte = |p: &mut Peripherals| {
                let byte = p.load(src_bank, src_addr);
                if !write_to_a {
                    // adjust `src_addr`
                    src_addr = (src_addr as i32 + a_addr_inc as i32) as u16;
                }
                byte
            };
            let mut write_byte = |p: &mut Peripherals, byte| {
                if bytes.get() == 0 { return }
                p.store(dest_bank, dest_addr, byte);
                bytes.set(bytes.get() - 1);
                if write_to_a {
                    // adjust `dest_addr`
                    dest_addr = (dest_addr as i32 + a_addr_inc as i32) as u16;
                }
            };

            dma_cy += bytes.get() * 8;  // 8 master cycles per byte
            while bytes.get() > 0 {
                dma_transaction(p, mode, &mut read_byte, &mut write_byte);
            }

            p.dma[i].dma_size = 0;
        }
    }

    trace!("DMA completed after {} master clock cycles", dma_cy);

    dma_cy
}
<|endoftext|>


<commit_before><commit_msg>make op and typeahead public<commit_after><|endoftext|>


<commit_before><commit_msg>some changes<commit_after><|endoftext|>


<commit_before><commit_msg>Update to rust master<commit_after><|endoftext|>


<commit_before><commit_msg>Replace time with std::time<commit_after><|endoftext|>


<commit_before><commit_msg>Read strings and blobs<commit_after><|endoftext|>