<commit_before>use std::borrow;
use std::cmp::Ordering;
use std::fmt;

#[cfg(feature = "object_sorted")]
use std::collections::BTreeMap;

#[cfg(not(any(feature = "object_sorted")))]
use std::collections::HashMap;

use super::Scalar;

#[cfg(feature = "object_sorted")]
type MapImpl<K, V> = BTreeMap<K, V>;

#[cfg(not(any(feature = "object_sorted")))]
type MapImpl<K, V> = HashMap<K, V>;

/// An enum to represent different value types
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Value {
    /// A scalar value.
    Scalar(Scalar),
    /// A sequence of `Value`s.
    Array(Array),
    /// A sequence of key/`Value` pairs.
    Object(Object),
    /// Nothing.
    Nil,
}

/// Type representing a Liquid array, payload of the `Value::Array` variant
pub type Array = Vec<Value>;

/// Type representing a Liquid object, payload of the `Value::Object` variant
pub type Object = MapImpl<borrow::Cow<'static, str>, Value>;

impl Value {
    /// Create as a `Scalar`.
    pub fn scalar<T: Into<Scalar>>(value: T) -> Self {
        Value::Scalar(Scalar::new(value))
    }

    /// Create as an `Array`.
    pub fn array<I: IntoIterator<Item = Self>>(iter: I) -> Self {
        let v: Array = iter.into_iter().collect();
        Value::Array(v)
    }

    /// Create as nothing.
    pub fn nil() -> Self {
        Value::Nil
    }

    /// Interpret as a string.
    pub fn to_str(&self) -> borrow::Cow<str> {
        match *self {
            Value::Scalar(ref x) => x.to_str(),
            Value::Array(ref x) => {
                let arr: Vec<String> = x.iter().map(|v| v.to_string()).collect();
                borrow::Cow::Owned(arr.join(", "))
            }
            Value::Object(ref x) => {
                let arr: Vec<String> = x.iter().map(|(k, v)| format!("{}: {}", k, v)).collect();
                borrow::Cow::Owned(arr.join(", "))
            }
            Value::Nil => borrow::Cow::Borrowed(""),
        }
    }

    /// Extracts the scalar value if it is a scalar.
    pub fn as_scalar(&self) -> Option<&Scalar> {
        match *self {
            Value::Scalar(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the scalar value if it is a scalar.
    pub fn into_scalar(self) -> Option<Scalar> {
        match self {
            Value::Scalar(s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is a scalar
    pub fn is_scalar(&self) -> bool {
        self.as_scalar().is_some()
    }

    /// Extracts the array value if it is an array.
    pub fn as_array(&self) -> Option<&Array> {
        match *self {
            Value::Array(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the array value if it is an array.
    pub fn as_array_mut(&mut self) -> Option<&mut Array> {
        match *self {
            Value::Array(ref mut s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the array value if it is an array.
    pub fn into_array(self) -> Option<Array> {
        match self {
            Value::Array(s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is an array
    pub fn is_array(&self) -> bool {
        self.as_array().is_some()
    }

    /// Extracts the object value if it is a object.
    pub fn as_object(&self) -> Option<&Object> {
        match *self {
            Value::Object(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the object value if it is a object.
    pub fn as_object_mut(&mut self) -> Option<&mut Object> {
        match *self {
            Value::Object(ref mut s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the object value if it is a object.
    pub fn into_object(self) -> Option<Object> {
        match self {
            Value::Object(s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is an object
    pub fn is_object(&self) -> bool {
        self.as_object().is_some()
    }

    /// Extracts the nil value if it is nil
    pub fn as_nil(&self) -> Option<()> {
        match *self {
            Value::Nil => Some(()),
            _ => None,
        }
    }

    /// Tests whether this value is nil
    pub fn is_nil(&self) -> bool {
        match *self {
            Value::Nil => true,
            _ => false,
        }
    }

    /// Evaluate using Liquid "truthiness"
    pub fn is_truthy(&self) -> bool {
        // encode Ruby truthiness: all values except false and nil are true
        match *self {
            Value::Scalar(ref x) => x.is_truthy(),
            Value::Nil => false,
            _ => true,
        }
    }

    /// Whether a default constructed value.
    pub fn is_default(&self) -> bool {
        match *self {
            Value::Scalar(ref x) => x.is_default(),
            Value::Nil => true,
            Value::Array(ref x) => x.is_empty(),
            Value::Object(ref x) => x.is_empty(),
        }
    }

    /// Report the data type (generally for error reporting).
    pub fn type_name(&self) -> &'static str {
        match *self {
            Value::Scalar(ref x) => x.type_name(),
            Value::Nil => "nil",
            Value::Array(_) => "array",
            Value::Object(_) => "object",
        }
    }

    /// Access a contained `Value`.
    pub fn get<'i, I: Into<&'i Scalar>>(&self, index: I) -> Option<&Self> {
        let index: &Scalar = index.into();
        self.get_index(index)
    }

    fn get_index(&self, index: &Scalar) -> Option<&Self> {
        match *self {
            Value::Array(ref x) => {
                if let Some(index) = index.to_integer() {
                    let index = if 0 <= index {
                        index as isize
                    } else {
                        (x.len() as isize) + (index as isize)
                    };
                    x.get(index as usize)
                } else {
                    match &*index.to_str() {
                        "first" => x.get(0),
                        "last" => x.get(x.len() - 1),
                        _ => None,
                    }
                }
            }
            Value::Object(ref x) => x.get(index.to_str().as_ref()),
            _ => None,
        }
    }
}

impl Default for Value {
    fn default() -> Self {
        Self::nil()
    }
}

impl PartialEq<Value> for Value {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x == y,
            (&Value::Array(ref x), &Value::Array(ref y)) => x == y,
            (&Value::Object(ref x), &Value::Object(ref y)) => x == y,
            (&Value::Nil, &Value::Nil) => true,

            // encode Ruby truthiness: all values except false and nil are true
            (&Value::Nil, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), &Value::Nil) => {
                !b.to_bool().unwrap_or(true)
            }
            (_, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), _) => b.to_bool().unwrap_or(false),

            _ => false,
        }
    }
}

impl Eq for Value {}

impl PartialOrd<Value> for Value {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match (self, other) {
            (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x.partial_cmp(y),
            (&Value::Array(ref x), &Value::Array(ref y)) => x.iter().partial_cmp(y.iter()),
            (&Value::Object(ref x), &Value::Object(ref y)) => x.iter().partial_cmp(y.iter()),
            _ => None,
        }
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let data = self.to_str();
        write!(f, "{}", data)
    }
}

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

    #[test]
    fn test_to_string_scalar() {
        let val = Value::scalar(42f64);
        assert_eq!(&val.to_string(), "42");
    }

    #[test]
    fn test_to_string_array() {
        let val = Value::Array(vec![
            Value::scalar(3f64),
            Value::scalar("test"),
            Value::scalar(5.3),
        ]);
        assert_eq!(&val.to_string(), "3, test, 5.3");
    }

    // TODO make a test for object, remember values are in arbitrary orders in HashMaps

    #[test]
    fn test_to_string_nil() {
        assert_eq!(&Value::nil().to_string(), "");
    }

    #[test]
    fn scalar_equality() {
        assert_eq!(Value::scalar("alpha"), Value::scalar("alpha"));
        assert_eq!(Value::scalar(""), Value::scalar(""));
        assert!(Value::scalar("alpha") != Value::scalar("beta"));
        assert!(Value::scalar("beta") != Value::scalar("alpha"));
    }

    #[test]
    fn scalars_have_ruby_truthiness() {
        // all strings in ruby are true
        assert_eq!(Value::scalar(true), Value::scalar("All strings are truthy"));
        assert_eq!(Value::scalar(true), Value::scalar(""));
        assert!(Value::scalar("").is_truthy());

        assert_eq!(Value::scalar(true), Value::scalar(true));
        assert!(Value::scalar(true) != Value::scalar(false));
    }

    #[test]
    fn array_equality() {
        let a = Value::Array(vec![Value::scalar("one"), Value::scalar("two")]);
        let b = Value::Array(vec![Value::scalar("alpha"), Value::scalar("beta")]);

        assert_eq!(a, a);
        assert!(a != b);
        assert!(b != a);
    }

    #[test]
    fn arrays_have_ruby_truthiness() {
        assert_eq!(Value::scalar(true), Value::Array(Vec::new()));
        assert!(Value::Array(Vec::new()).is_truthy());
    }

    #[test]
    fn object_equality() {
        let a: Object = [
            ("alpha".into(), Value::scalar("1")),
            ("beta".into(), Value::scalar(2f64)),
        ]
            .into_iter()
            .cloned()
            .collect();
        let a = Value::Object(a);

        let b: Object = [
            ("alpha".into(), Value::scalar("1")),
            ("beta".into(), Value::scalar(2f64)),
            ("gamma".into(), Value::Array(vec![])),
        ]
            .into_iter()
            .cloned()
            .collect();
        let b = Value::Object(b);

        assert_eq!(a, a);
        assert!(a != b);
        assert!(b != a);
    }

    #[test]
    fn objects_have_ruby_truthiness() {
        assert_eq!(Value::scalar(true), Value::Object(Object::new()));
        assert!(Value::Object(Object::new()).is_truthy());
    }

    #[test]
    fn nil_equality() {
        assert_eq!(Value::Nil, Value::Nil);
    }

    #[test]
    fn nils_have_ruby_truthiness() {
        assert_eq!(Value::scalar(false), Value::Nil);
        assert!(!Value::Nil.is_truthy());

        assert_eq!(Value::scalar(false), Value::Nil);
        assert!(Value::scalar(true) != Value::Nil);
        assert!(Value::scalar("") != Value::Nil);
    }
}
<commit_msg>fix(value): Remove useless Into<commit_after>use std::borrow;
use std::cmp::Ordering;
use std::fmt;

#[cfg(feature = "object_sorted")]
use std::collections::BTreeMap;

#[cfg(not(any(feature = "object_sorted")))]
use std::collections::HashMap;

use super::Scalar;

#[cfg(feature = "object_sorted")]
type MapImpl<K, V> = BTreeMap<K, V>;

#[cfg(not(any(feature = "object_sorted")))]
type MapImpl<K, V> = HashMap<K, V>;

/// An enum to represent different value types
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Value {
    /// A scalar value.
    Scalar(Scalar),
    /// A sequence of `Value`s.
    Array(Array),
    /// A sequence of key/`Value` pairs.
    Object(Object),
    /// Nothing.
    Nil,
}

/// Type representing a Liquid array, payload of the `Value::Array` variant
pub type Array = Vec<Value>;

/// Type representing a Liquid object, payload of the `Value::Object` variant
pub type Object = MapImpl<borrow::Cow<'static, str>, Value>;

impl Value {
    /// Create as a `Scalar`.
    pub fn scalar<T: Into<Scalar>>(value: T) -> Self {
        Value::Scalar(Scalar::new(value))
    }

    /// Create as an `Array`.
    pub fn array<I: IntoIterator<Item = Self>>(iter: I) -> Self {
        let v: Array = iter.into_iter().collect();
        Value::Array(v)
    }

    /// Create as nothing.
    pub fn nil() -> Self {
        Value::Nil
    }

    /// Interpret as a string.
    pub fn to_str(&self) -> borrow::Cow<str> {
        match *self {
            Value::Scalar(ref x) => x.to_str(),
            Value::Array(ref x) => {
                let arr: Vec<String> = x.iter().map(|v| v.to_string()).collect();
                borrow::Cow::Owned(arr.join(", "))
            }
            Value::Object(ref x) => {
                let arr: Vec<String> = x.iter().map(|(k, v)| format!("{}: {}", k, v)).collect();
                borrow::Cow::Owned(arr.join(", "))
            }
            Value::Nil => borrow::Cow::Borrowed(""),
        }
    }

    /// Extracts the scalar value if it is a scalar.
    pub fn as_scalar(&self) -> Option<&Scalar> {
        match *self {
            Value::Scalar(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the scalar value if it is a scalar.
    pub fn into_scalar(self) -> Option<Scalar> {
        match self {
            Value::Scalar(s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is a scalar
    pub fn is_scalar(&self) -> bool {
        self.as_scalar().is_some()
    }

    /// Extracts the array value if it is an array.
    pub fn as_array(&self) -> Option<&Array> {
        match *self {
            Value::Array(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the array value if it is an array.
    pub fn as_array_mut(&mut self) -> Option<&mut Array> {
        match *self {
            Value::Array(ref mut s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the array value if it is an array.
    pub fn into_array(self) -> Option<Array> {
        match self {
            Value::Array(s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is an array
    pub fn is_array(&self) -> bool {
        self.as_array().is_some()
    }

    /// Extracts the object value if it is a object.
    pub fn as_object(&self) -> Option<&Object> {
        match *self {
            Value::Object(ref s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the object value if it is a object.
    pub fn as_object_mut(&mut self) -> Option<&mut Object> {
        match *self {
            Value::Object(ref mut s) => Some(s),
            _ => None,
        }
    }

    /// Extracts the object value if it is a object.
    pub fn into_object(self) -> Option<Object> {
        match self {
            Value::Object(s) => Some(s),
            _ => None,
        }
    }

    /// Tests whether this value is an object
    pub fn is_object(&self) -> bool {
        self.as_object().is_some()
    }

    /// Extracts the nil value if it is nil
    pub fn as_nil(&self) -> Option<()> {
        match *self {
            Value::Nil => Some(()),
            _ => None,
        }
    }

    /// Tests whether this value is nil
    pub fn is_nil(&self) -> bool {
        match *self {
            Value::Nil => true,
            _ => false,
        }
    }

    /// Evaluate using Liquid "truthiness"
    pub fn is_truthy(&self) -> bool {
        // encode Ruby truthiness: all values except false and nil are true
        match *self {
            Value::Scalar(ref x) => x.is_truthy(),
            Value::Nil => false,
            _ => true,
        }
    }

    /// Whether a default constructed value.
    pub fn is_default(&self) -> bool {
        match *self {
            Value::Scalar(ref x) => x.is_default(),
            Value::Nil => true,
            Value::Array(ref x) => x.is_empty(),
            Value::Object(ref x) => x.is_empty(),
        }
    }

    /// Report the data type (generally for error reporting).
    pub fn type_name(&self) -> &'static str {
        match *self {
            Value::Scalar(ref x) => x.type_name(),
            Value::Nil => "nil",
            Value::Array(_) => "array",
            Value::Object(_) => "object",
        }
    }

    /// Access a contained `Value`.
    pub fn get<'s>(&'s self, index: &Scalar) -> Option<&'s Self> {
        match *self {
            Value::Array(ref x) => {
                if let Some(index) = index.to_integer() {
                    let index = if 0 <= index {
                        index as isize
                    } else {
                        (x.len() as isize) + (index as isize)
                    };
                    x.get(index as usize)
                } else {
                    match &*index.to_str() {
                        "first" => x.get(0),
                        "last" => x.get(x.len() - 1),
                        _ => None,
                    }
                }
            }
            Value::Object(ref x) => x.get(index.to_str().as_ref()),
            _ => None,
        }
    }
}

impl Default for Value {
    fn default() -> Self {
        Self::nil()
    }
}

impl PartialEq<Value> for Value {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x == y,
            (&Value::Array(ref x), &Value::Array(ref y)) => x == y,
            (&Value::Object(ref x), &Value::Object(ref y)) => x == y,
            (&Value::Nil, &Value::Nil) => true,

            // encode Ruby truthiness: all values except false and nil are true
            (&Value::Nil, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), &Value::Nil) => {
                !b.to_bool().unwrap_or(true)
            }
            (_, &Value::Scalar(ref b)) | (&Value::Scalar(ref b), _) => b.to_bool().unwrap_or(false),

            _ => false,
        }
    }
}

impl Eq for Value {}

impl PartialOrd<Value> for Value {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match (self, other) {
            (&Value::Scalar(ref x), &Value::Scalar(ref y)) => x.partial_cmp(y),
            (&Value::Array(ref x), &Value::Array(ref y)) => x.iter().partial_cmp(y.iter()),
            (&Value::Object(ref x), &Value::Object(ref y)) => x.iter().partial_cmp(y.iter()),
            _ => None,
        }
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let data = self.to_str();
        write!(f, "{}", data)
    }
}

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

    #[test]
    fn test_to_string_scalar() {
        let val = Value::scalar(42f64);
        assert_eq!(&val.to_string(), "42");
    }

    #[test]
    fn test_to_string_array() {
        let val = Value::Array(vec![
            Value::scalar(3f64),
            Value::scalar("test"),
            Value::scalar(5.3),
        ]);
        assert_eq!(&val.to_string(), "3, test, 5.3");
    }

    // TODO make a test for object, remember values are in arbitrary orders in HashMaps

    #[test]
    fn test_to_string_nil() {
        assert_eq!(&Value::nil().to_string(), "");
    }

    #[test]
    fn scalar_equality() {
        assert_eq!(Value::scalar("alpha"), Value::scalar("alpha"));
        assert_eq!(Value::scalar(""), Value::scalar(""));
        assert!(Value::scalar("alpha") != Value::scalar("beta"));
        assert!(Value::scalar("beta") != Value::scalar("alpha"));
    }

    #[test]
    fn scalars_have_ruby_truthiness() {
        // all strings in ruby are true
        assert_eq!(Value::scalar(true), Value::scalar("All strings are truthy"));
        assert_eq!(Value::scalar(true), Value::scalar(""));
        assert!(Value::scalar("").is_truthy());

        assert_eq!(Value::scalar(true), Value::scalar(true));
        assert!(Value::scalar(true) != Value::scalar(false));
    }

    #[test]
    fn array_equality() {
        let a = Value::Array(vec![Value::scalar("one"), Value::scalar("two")]);
        let b = Value::Array(vec![Value::scalar("alpha"), Value::scalar("beta")]);

        assert_eq!(a, a);
        assert!(a != b);
        assert!(b != a);
    }

    #[test]
    fn arrays_have_ruby_truthiness() {
        assert_eq!(Value::scalar(true), Value::Array(Vec::new()));
        assert!(Value::Array(Vec::new()).is_truthy());
    }

    #[test]
    fn object_equality() {
        let a: Object = [
            ("alpha".into(), Value::scalar("1")),
            ("beta".into(), Value::scalar(2f64)),
        ]
            .into_iter()
            .cloned()
            .collect();
        let a = Value::Object(a);

        let b: Object = [
            ("alpha".into(), Value::scalar("1")),
            ("beta".into(), Value::scalar(2f64)),
            ("gamma".into(), Value::Array(vec![])),
        ]
            .into_iter()
            .cloned()
            .collect();
        let b = Value::Object(b);

        assert_eq!(a, a);
        assert!(a != b);
        assert!(b != a);
    }

    #[test]
    fn objects_have_ruby_truthiness() {
        assert_eq!(Value::scalar(true), Value::Object(Object::new()));
        assert!(Value::Object(Object::new()).is_truthy());
    }

    #[test]
    fn nil_equality() {
        assert_eq!(Value::Nil, Value::Nil);
    }

    #[test]
    fn nils_have_ruby_truthiness() {
        assert_eq!(Value::scalar(false), Value::Nil);
        assert!(!Value::Nil.is_truthy());

        assert_eq!(Value::scalar(false), Value::Nil);
        assert!(Value::scalar(true) != Value::Nil);
        assert!(Value::scalar("") != Value::Nil);
    }
}
<|endoftext|>


<commit_before>use crate::{error::{Error,
                    Result},
            manager::file_watcher::{create_file_watcher,
                                    Callbacks}};
use habitat_butterfly::member::Member;
use habitat_common::{liveliness_checker,
                     outputln,
                     types::GossipListenAddr};
use std::{fs::File,
          io::{BufRead,
               BufReader},
          net::{SocketAddr,
                ToSocketAddrs},
          path::{Path,
                 PathBuf},
          sync::{atomic::{AtomicBool,
                          Ordering},
                 Arc},
          thread::Builder as ThreadBuilder};

static LOGKEY: &str = "PW";

pub struct PeerCallbacks {
    have_events: Arc<AtomicBool>,
}

impl Callbacks for PeerCallbacks {
    fn file_appeared(&mut self, _: &Path) { self.have_events.store(true, Ordering::Relaxed); }

    fn file_modified(&mut self, _: &Path) { self.have_events.store(true, Ordering::Relaxed) }

    fn file_disappeared(&mut self, _: &Path) { self.have_events.store(true, Ordering::Relaxed) }
}

pub struct PeerWatcher {
    path:        PathBuf,
    have_events: Arc<AtomicBool>,
}

impl PeerWatcher {
    pub fn run<P>(path: P) -> Result<Self>
        where P: Into<PathBuf>
    {
        let path = path.into();
        let have_events = Self::setup_watcher(path.clone())?;

        Ok(PeerWatcher { path, have_events })
    }

    fn setup_watcher(path: PathBuf) -> Result<Arc<AtomicBool>> {
        let have_events = Arc::new(AtomicBool::new(false));
        let have_events_for_thread = Arc::clone(&have_events);

        ThreadBuilder::new().name(format!("peer-watcher-[{}]", path.display()))
                            .spawn(move || -> liveliness_checker::ThreadUnregistered {
                                // debug!("PeerWatcher({}) thread starting", abs_path.display());
                                loop {
                                    let checked_thread = liveliness_checker::mark_thread_alive();
                                    let have_events_for_loop = Arc::clone(&have_events_for_thread);
                                    if Self::file_watcher_loop_body(&path, have_events_for_loop) {
                                        break checked_thread.unregister(Ok(()));
                                    }
                                }
                            })?;
        Ok(have_events)
    }

    fn file_watcher_loop_body(path: &Path, have_events: Arc<AtomicBool>) -> bool {
        let callbacks = PeerCallbacks { have_events };
        let mut file_watcher = match create_file_watcher(&path, callbacks, true) {
            Ok(watcher) => watcher,
            Err(e) => {
                match e {
                    Error::NotifyError(err) => {
                        outputln!("PeerWatcher({}) failed to start watching the directories \
                                   ({}), {}",
                                  path.display(),
                                  err,
                                  "will try again");
                        return false;
                    }
                    _ => {
                        outputln!("PeerWatcher({}) could not create file watcher, ending thread \
                                   ({})",
                                  path.display(),
                                  e);
                        return true;
                    }
                }
            }
        };
        if let Err(err) = file_watcher.run() {
            outputln!("PeerWatcher({}) error during watching ({}), restarting",
                      path.display(),
                      err);
        }
        false
    }

    pub fn has_fs_events(&self) -> bool { self.have_events.load(Ordering::Relaxed) }

    pub fn get_members(&self) -> Result<Vec<Member>> {
        if !self.path.is_file() {
            self.have_events.store(false, Ordering::Relaxed);
            return Ok(Vec::new());
        }
        let file = File::open(&self.path).map_err(Error::Io)?;
        let reader = BufReader::new(file);
        let mut members: Vec<Member> = Vec::new();
        for line in reader.lines().flatten() {
            let peer_addr = if line.find(':').is_some() {
                line
            } else {
                format!("{}:{}", line, GossipListenAddr::DEFAULT_PORT)
            };
            let addrs: Vec<SocketAddr> = match peer_addr.to_socket_addrs() {
                Ok(addrs) => addrs.collect(),
                Err(e) => {
                    outputln!("Failed to resolve peer: {}", peer_addr);
                    return Err(Error::NameLookup(e));
                }
            };
            let addr: SocketAddr = addrs[0];
            let member = Member { address: format!("{}", addr.ip()),
                                  swim_port: addr.port(),
                                  gossip_port: addr.port(),
                                  ..Default::default() };
            members.push(member);
        }
        self.have_events.store(false, Ordering::Relaxed);
        Ok(members)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use habitat_butterfly::member::Member;
    use habitat_core::locked_env_var;
    use std::{fs::{File,
                   OpenOptions},
              io::Write,
              path::{Path,
                     PathBuf}};
    use tempfile::TempDir;

    locked_env_var!(HAB_STUDIO_HOST_ARCH, lock_env_var);

    fn peer_watcher_member_load_test(watch_dir: &Path,
                                     peer_data: &[String])
                                     -> Result<Vec<Member>> {
        let path = PathBuf::from(watch_dir).join("some_file");
        let mut file = OpenOptions::new().append(true)
                                         .create_new(true)
                                         .open(path.clone())
                                         .unwrap();
        let watcher = PeerWatcher::run(path).unwrap();
        for line in peer_data {
            writeln!(file, "{}", line).unwrap();
        }
        watcher.get_members()
    }

    #[test]
    fn no_file() {
        let tmpdir = TempDir::new().unwrap();
        let path = tmpdir.path().join("no_such_file");

        let lock = lock_env_var();
        lock.set("");
        let watcher = PeerWatcher::run(path).unwrap();
        lock.unset();

        assert!(!watcher.has_fs_events());
        assert_eq!(watcher.get_members().unwrap(), vec![]);
    }

    #[test]
    fn empty_file() {
        let tmpdir = TempDir::new().unwrap();
        let path = tmpdir.path().join("empty_file");
        File::create(&path).unwrap();

        let lock = lock_env_var();
        lock.set("");
        let watcher = PeerWatcher::run(path).unwrap();
        lock.unset();

        assert_eq!(watcher.get_members().unwrap(), vec![]);
    }

    #[test]
    fn empty_file_with_poll_watcher() {
        let tmpdir = TempDir::new().unwrap();
        let path = tmpdir.path().join("empty_file");
        File::create(&path).unwrap();

        let lock = lock_env_var();
        lock.set("aarch64-darwin");
        let watcher = PeerWatcher::run(path).unwrap();
        lock.unset();

        assert_eq!(watcher.get_members().unwrap(), vec![]);
    }

    #[test]
    fn with_file() {
        let tmpdir = TempDir::new().unwrap();

        let peer_lines = vec!["1.2.3.4:5".to_string(), "4.3.2.1".to_string()];

        let lock = lock_env_var();
        lock.set("");
        let mut members = peer_watcher_member_load_test(tmpdir.path(), &peer_lines).unwrap();
        lock.unset();

        for mut member in &mut members {
            member.id = String::new();
        }
        let member1 = Member { id: String::new(),
                               address: String::from("1.2.3.4"),
                               swim_port: 5,
                               gossip_port: 5,
                               ..Default::default() };
        let member2 = Member { id: String::new(),
                               address: String::from("4.3.2.1"),
                               swim_port: GossipListenAddr::DEFAULT_PORT,
                               gossip_port: GossipListenAddr::DEFAULT_PORT,
                               ..Default::default() };
        let expected_members = vec![member1, member2];
        assert_eq!(expected_members, members);
    }

    #[test]
    fn with_file_using_poll_watcher() {
        let tmpdir = TempDir::new().unwrap();
        let peer_lines = vec!["1.2.3.5:5".to_string(), "5.4.3.2".to_string()];
        let lock = lock_env_var();
        lock.set("aarch64-darwin");
        let mut members = peer_watcher_member_load_test(tmpdir.path(), &peer_lines).unwrap();
        lock.unset();
        for mut member in &mut members {
            member.id = String::new();
        }
        let member1 = Member { id: String::new(),
                               address: String::from("1.2.3.5"),
                               swim_port: 5,
                               gossip_port: 5,
                               ..Default::default() };
        let member2 = Member { id: String::new(),
                               address: String::from("5.4.3.2"),
                               swim_port: GossipListenAddr::DEFAULT_PORT,
                               gossip_port: GossipListenAddr::DEFAULT_PORT,
                               ..Default::default() };
        let expected_members = vec![member1, member2];
        assert_eq!(expected_members, members);
    }
}
<commit_msg>test case updates - formatting<commit_after>use crate::{error::{Error,
                    Result},
            manager::file_watcher::{create_file_watcher,
                                    Callbacks}};
use habitat_butterfly::member::Member;
use habitat_common::{liveliness_checker,
                     outputln,
                     types::GossipListenAddr};
use std::{fs::File,
          io::{BufRead,
               BufReader},
          net::{SocketAddr,
                ToSocketAddrs},
          path::{Path,
                 PathBuf},
          sync::{atomic::{AtomicBool,
                          Ordering},
                 Arc},
          thread::Builder as ThreadBuilder};

static LOGKEY: &str = "PW";

pub struct PeerCallbacks {
    have_events: Arc<AtomicBool>,
}

impl Callbacks for PeerCallbacks {
    fn file_appeared(&mut self, _: &Path) { self.have_events.store(true, Ordering::Relaxed); }

    fn file_modified(&mut self, _: &Path) { self.have_events.store(true, Ordering::Relaxed) }

    fn file_disappeared(&mut self, _: &Path) { self.have_events.store(true, Ordering::Relaxed) }
}

pub struct PeerWatcher {
    path:        PathBuf,
    have_events: Arc<AtomicBool>,
}

impl PeerWatcher {
    pub fn run<P>(path: P) -> Result<Self>
        where P: Into<PathBuf>
    {
        let path = path.into();
        let have_events = Self::setup_watcher(path.clone())?;

        Ok(PeerWatcher { path, have_events })
    }

    fn setup_watcher(path: PathBuf) -> Result<Arc<AtomicBool>> {
        let have_events = Arc::new(AtomicBool::new(false));
        let have_events_for_thread = Arc::clone(&have_events);

        ThreadBuilder::new().name(format!("peer-watcher-[{}]", path.display()))
                            .spawn(move || -> liveliness_checker::ThreadUnregistered {
                                // debug!("PeerWatcher({}) thread starting", abs_path.display());
                                loop {
                                    let checked_thread = liveliness_checker::mark_thread_alive();
                                    let have_events_for_loop = Arc::clone(&have_events_for_thread);
                                    if Self::file_watcher_loop_body(&path, have_events_for_loop) {
                                        break checked_thread.unregister(Ok(()));
                                    }
                                }
                            })?;
        Ok(have_events)
    }

    fn file_watcher_loop_body(path: &Path, have_events: Arc<AtomicBool>) -> bool {
        let callbacks = PeerCallbacks { have_events };
        let mut file_watcher = match create_file_watcher(&path, callbacks, true) {
            Ok(watcher) => watcher,
            Err(e) => {
                match e {
                    Error::NotifyError(err) => {
                        outputln!("PeerWatcher({}) failed to start watching the directories \
                                   ({}), {}",
                                  path.display(),
                                  err,
                                  "will try again");
                        return false;
                    }
                    _ => {
                        outputln!("PeerWatcher({}) could not create file watcher, ending thread \
                                   ({})",
                                  path.display(),
                                  e);
                        return true;
                    }
                }
            }
        };
        if let Err(err) = file_watcher.run() {
            outputln!("PeerWatcher({}) error during watching ({}), restarting",
                      path.display(),
                      err);
        }
        false
    }

    pub fn has_fs_events(&self) -> bool { self.have_events.load(Ordering::Relaxed) }

    pub fn get_members(&self) -> Result<Vec<Member>> {
        if !self.path.is_file() {
            self.have_events.store(false, Ordering::Relaxed);
            return Ok(Vec::new());
        }
        let file = File::open(&self.path).map_err(Error::Io)?;
        let reader = BufReader::new(file);
        let mut members: Vec<Member> = Vec::new();
        for line in reader.lines().flatten() {
            let peer_addr = if line.find(':').is_some() {
                line
            } else {
                format!("{}:{}", line, GossipListenAddr::DEFAULT_PORT)
            };
            let addrs: Vec<SocketAddr> = match peer_addr.to_socket_addrs() {
                Ok(addrs) => addrs.collect(),
                Err(e) => {
                    outputln!("Failed to resolve peer: {}", peer_addr);
                    return Err(Error::NameLookup(e));
                }
            };
            let addr: SocketAddr = addrs[0];
            let member = Member { address: format!("{}", addr.ip()),
                                  swim_port: addr.port(),
                                  gossip_port: addr.port(),
                                  ..Default::default() };
            members.push(member);
        }
        self.have_events.store(false, Ordering::Relaxed);
        Ok(members)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use habitat_butterfly::member::Member;
    use habitat_core::locked_env_var;
    use std::{fs::{File,
                   OpenOptions},
              io::Write,
              path::{Path,
                     PathBuf}};
    use tempfile::TempDir;

    locked_env_var!(HAB_STUDIO_HOST_ARCH, lock_env_var);

    fn peer_watcher_member_load_test(watch_dir: &Path,
                                     peer_data: &[String])
                                     -> Result<Vec<Member>> {
        let path = PathBuf::from(watch_dir).join("some_file");
        let mut file = OpenOptions::new().append(true)
                                         .create_new(true)
                                         .open(path.clone())
                                         .unwrap();
        let watcher = PeerWatcher::run(path).unwrap();
        for line in peer_data {
            writeln!(file, "{}", line).unwrap();
        }
        watcher.get_members()
    }

    #[test]
    fn no_file() {
        let tmpdir = TempDir::new().unwrap();
        let path = tmpdir.path().join("no_such_file");

        let lock = lock_env_var();
        lock.set("");
        let watcher = PeerWatcher::run(path).unwrap();
        lock.unset();

        assert!(!watcher.has_fs_events());
        assert_eq!(watcher.get_members().unwrap(), vec![]);
    }

    #[test]
    fn empty_file() {
        let tmpdir = TempDir::new().unwrap();
        let path = tmpdir.path().join("empty_file");
        File::create(&path).unwrap();

        let lock = lock_env_var();
        lock.set("");
        let watcher = PeerWatcher::run(path).unwrap();
        lock.unset();

        assert_eq!(watcher.get_members().unwrap(), vec![]);
    }

    #[test]
    fn empty_file_with_poll_watcher() {
        let tmpdir = TempDir::new().unwrap();
        let path = tmpdir.path().join("empty_file");
        File::create(&path).unwrap();

        let lock = lock_env_var();
        lock.set("aarch64-darwin");
        let watcher = PeerWatcher::run(path).unwrap();
        lock.unset();

        assert_eq!(watcher.get_members().unwrap(), vec![]);
    }

    #[test]
    fn with_file() {
        let tmpdir = TempDir::new().unwrap();

        let peer_lines = vec!["1.2.3.4:5".to_string(), "4.3.2.1".to_string()];

        let lock = lock_env_var();
        lock.set("");
        let mut members = peer_watcher_member_load_test(tmpdir.path(), &peer_lines).unwrap();
        lock.unset();

        for mut member in &mut members {
            member.id = String::new();
        }
        let member1 = Member { id: String::new(),
                               address: String::from("1.2.3.4"),
                               swim_port: 5,
                               gossip_port: 5,
                               ..Default::default() };
        let member2 = Member { id: String::new(),
                               address: String::from("4.3.2.1"),
                               swim_port: GossipListenAddr::DEFAULT_PORT,
                               gossip_port: GossipListenAddr::DEFAULT_PORT,
                               ..Default::default() };
        let expected_members = vec![member1, member2];
        assert_eq!(expected_members, members);
    }

    #[test]
    fn with_file_using_poll_watcher() {
        let tmpdir = TempDir::new().unwrap();
        let peer_lines = vec!["1.2.3.5:5".to_string(), "5.4.3.2".to_string()];
        let lock = lock_env_var();
        lock.set("aarch64-darwin");
        let mut members = peer_watcher_member_load_test(tmpdir.path(), &peer_lines).unwrap();
        lock.unset();
        for mut member in &mut members {
            member.id = String::new();
        }
        let member1 = Member { id: String::new(),
                               address: String::from("1.2.3.5"),
                               swim_port: 5,
                               gossip_port: 5,
                               ..Default::default() };
        let member2 = Member { id: String::new(),
                               address: String::from("5.4.3.2"),
                               swim_port: GossipListenAddr::DEFAULT_PORT,
                               gossip_port: GossipListenAddr::DEFAULT_PORT,
                               ..Default::default() };
        let expected_members = vec![member1, member2];
        assert_eq!(expected_members, members);
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::ops::{Neg, Add, Sub, Mul, Div, Rem};

//TODO: Refactor Unit into its own newtype
//TODO: Define a `.next()` method that returns the next unit from a given unit (use this in EvalContext) instead of manually incrementing the unit in create_unit
pub type Unit = usize;

#[derive(Debug, Clone, Copy, PartialOrd)]
pub struct RichNumber {
    //TODO: These should not be public as modifying them may not always force strict adherence to mathematical laws
    pub value: f64,
    pub unit: Option<Unit>,
}

impl RichNumber {
    pub fn new(value: f64, unit: Option<Unit>) -> RichNumber {
        RichNumber {
            value: value,
            unit: unit,
        }
    }

    //TODO: Rename from_unit to with_unit per Rust styleguide
    pub fn from_unit(value: f64, unit: Unit) -> RichNumber {
        RichNumber::new(value, Some(unit))
    }

    pub fn is_dimensionless(&self) -> bool {
        self.unit.is_none()
    }

    pub fn has_units(&self) -> bool {
        !self.is_dimensionless()
    }

    pub fn without_units(&self) -> RichNumber {
        RichNumber::new(self.value, None)
    }

    pub fn pow(&self, other: RichNumber) -> RichNumber {
        assert!(self.is_dimensionless() && other.is_dimensionless(),
            "Applying exponents to quantities with units is not supported yet, only raise dimensionless/scalar quantities to dimensionless/scalar exponents");

        RichNumber::from(self.value.powf(other.value))
    }

    pub fn abs(&self) -> RichNumber {
        RichNumber::new(self.value.abs(), self.unit)
    }

    pub fn floor(&self) -> RichNumber {
        RichNumber::new(self.value.floor(), self.unit)
    }

    pub fn ceil(&self) -> RichNumber {
        RichNumber::new(self.value.ceil(), self.unit)
    }

    pub fn round(&self) -> RichNumber {
        RichNumber::new(self.value.round(), self.unit)
    }

    pub fn sqrt(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::from(self.value.sqrt())
    }

    pub fn ln(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::from(self.value.ln())
    }

    pub fn log10(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::from(self.value.log10())
    }

    pub fn log2(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::from(self.value.log2())
    }

    pub fn sin(&self) -> RichNumber {
        RichNumber::from(self.value.sin())
    }

    pub fn cos(&self) -> RichNumber {
        RichNumber::from(self.value.cos())
    }

    pub fn tan(&self) -> RichNumber {
        RichNumber::from(self.value.tan())
    }

    pub fn asin(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.asin(), self.unit)
    }

    pub fn acos(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.acos(), self.unit)
    }

    pub fn atan(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.atan(), self.unit)
    }

    pub fn sinh(&self) -> RichNumber {
        RichNumber::from(self.value.sinh())
    }

    pub fn cosh(&self) -> RichNumber {
        RichNumber::from(self.value.cosh())
    }

    pub fn tanh(&self) -> RichNumber {
        RichNumber::from(self.value.tanh())
    }

    pub fn asinh(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.asinh(), self.unit)
    }

    pub fn acosh(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.acosh(), self.unit)
    }

    pub fn atanh(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.atanh(), self.unit)
    }

    /// Applies an operator to two values given the values and what the resulting unit should be
    fn apply_operator<F>(self, other: RichNumber, operator: F, unit: Option<Unit>) -> RichNumber
        where F: FnOnce(f64, f64) -> f64 {

        let value = operator(self.value, other.value);
        RichNumber::new(value, unit)
    }
}

impl From<i64> for RichNumber {
    fn from(number: i64) -> RichNumber {
        RichNumber::from(number as f64)
    }
}

impl From<f64> for RichNumber {
    fn from(number: f64) -> RichNumber {
        RichNumber::new(number, None)
    }
}

impl PartialEq for RichNumber {
    fn eq(&self, other: &RichNumber) -> bool {
        assert!(self.unit == other.unit,
            "Cannot compare values with different units");

        (self.value - other.value).abs() < 1e-10
    }
}

impl Eq for RichNumber {}

impl Ord for RichNumber {
    fn cmp(&self, other: &Self) -> Ordering {
        assert!(self.unit == other.unit,
            "Cannot compare values with different units");

        self.value.partial_cmp(&other.value).unwrap()
    }
}

impl Neg for RichNumber {
    type Output = RichNumber;

    fn neg(self) -> Self::Output {
        RichNumber::new(-self.value, self.unit)
    }
}

impl Add for RichNumber {
    type Output = RichNumber;

    fn add(self, other: RichNumber) -> Self::Output {
        assert!(self.unit == other.unit,
            "Cannot add values with different units");
        self.apply_operator(other, |a, b| a + b, self.unit)
    }
}

impl Sub for RichNumber {
    type Output = RichNumber;

    fn sub(self, other: RichNumber) -> Self::Output {
        assert!(self.unit == other.unit,
            "Cannot subtract values with different units");
        self.apply_operator(other, |a, b| a - b, self.unit)
    }
}

impl Mul for RichNumber {
    type Output = RichNumber;

    fn mul(self, other: RichNumber) -> Self::Output {
        let unit;
        if self.is_dimensionless() {
            unit = other.unit;
        }
        else if other.is_dimensionless() {
            unit = self.unit;
        }
        else {
            panic!("Multiplying units is not supported yet. Try a dimensionaless/scalar value");
        }

        self.apply_operator(other, |a, b| a * b, unit)
    }
}

impl Div for RichNumber {
    type Output = RichNumber;

    fn div(self, other: RichNumber) -> Self::Output {
        let unit;
        if other.is_dimensionless() {
            unit = self.unit;
        }
        else if self.unit == other.unit {
            unit = None;
        }
        else {
            panic!("Dividing units is not supported yet. Use two values with the same unit or multiply by a dimensionless/scalar value");
        }

        self.apply_operator(other, |a, b| a / b, unit)
    }
}

impl Rem for RichNumber {
    type Output = RichNumber;

    fn rem(self, other: RichNumber) -> Self::Output {
        let unit;
        if other.is_dimensionless() {
            unit = self.unit;
        }
        else if self.unit == other.unit {
            unit = None;
        }
        else {
            panic!("Taking the remainder of quantities with units is not supported. Use two values with the same unit or multiply by a dimensionless/scalar value");
        }

        self.apply_operator(other, |a, b| a % b, unit)
    }
}

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

    #[test]
    fn equality() {
        let a = RichNumber::from(2);
        let b = RichNumber::from(2);
        let c = RichNumber::from(3.6);

        assert_eq!(a, b);
        assert!(a != c);
    }

    #[test]
    fn basic_operations() {
        let a = RichNumber::from(2);
        let b = RichNumber::from(3.6);

        assert_eq!(a + b, RichNumber::from(5.6f64));
        assert_eq!(b + a, RichNumber::from(5.6f64));

        assert_eq!(a - b, RichNumber::from(-1.6f64));
        assert_eq!(b - a, RichNumber::from(1.6f64));

        assert_eq!(a * b, RichNumber::from(7.2f64));
        assert_eq!(b * a, RichNumber::from(7.2f64));

        assert_eq!(a / b, RichNumber::from(0.55555555555f64));
        assert_eq!(b / a, RichNumber::from(1.8f64));

        assert_eq!(a % b, RichNumber::from(2f64));
        assert_eq!(b % a, RichNumber::from(1.6f64));
    }

    #[test]
    fn ordering() {
        let a = RichNumber::from(2);
        let b = RichNumber::from(3.6666666666666);
        let c = RichNumber::from(3.6666666666667);
        let d = RichNumber::from(3.6666666666667);

        assert!(a < b);
        assert!(b < c);
        assert!(c <= d);
        assert!(d > b);
        assert!(b >= a);
    }
}

<commit_msg>Fixing ord implementation so that the operators actually use it<commit_after>use std::cmp::Ordering;
use std::ops::{Neg, Add, Sub, Mul, Div, Rem};

//TODO: Refactor Unit into its own newtype
//TODO: Define a `.next()` method that returns the next unit from a given unit (use this in EvalContext) instead of manually incrementing the unit in create_unit
pub type Unit = usize;

#[derive(Debug, Clone, Copy)]
pub struct RichNumber {
    //TODO: These should not be public as modifying them may not always force strict adherence to mathematical laws
    pub value: f64,
    pub unit: Option<Unit>,
}

impl RichNumber {
    pub fn new(value: f64, unit: Option<Unit>) -> RichNumber {
        RichNumber {
            value: value,
            unit: unit,
        }
    }

    //TODO: Rename from_unit to with_unit per Rust styleguide
    pub fn from_unit(value: f64, unit: Unit) -> RichNumber {
        RichNumber::new(value, Some(unit))
    }

    pub fn is_dimensionless(&self) -> bool {
        self.unit.is_none()
    }

    pub fn has_units(&self) -> bool {
        !self.is_dimensionless()
    }

    pub fn without_units(&self) -> RichNumber {
        RichNumber::new(self.value, None)
    }

    pub fn pow(&self, other: RichNumber) -> RichNumber {
        assert!(self.is_dimensionless() && other.is_dimensionless(),
            "Applying exponents to quantities with units is not supported yet, only raise dimensionless/scalar quantities to dimensionless/scalar exponents");

        RichNumber::from(self.value.powf(other.value))
    }

    pub fn abs(&self) -> RichNumber {
        RichNumber::new(self.value.abs(), self.unit)
    }

    pub fn floor(&self) -> RichNumber {
        RichNumber::new(self.value.floor(), self.unit)
    }

    pub fn ceil(&self) -> RichNumber {
        RichNumber::new(self.value.ceil(), self.unit)
    }

    pub fn round(&self) -> RichNumber {
        RichNumber::new(self.value.round(), self.unit)
    }

    pub fn sqrt(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::from(self.value.sqrt())
    }

    pub fn ln(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::from(self.value.ln())
    }

    pub fn log10(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::from(self.value.log10())
    }

    pub fn log2(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::from(self.value.log2())
    }

    pub fn sin(&self) -> RichNumber {
        RichNumber::from(self.value.sin())
    }

    pub fn cos(&self) -> RichNumber {
        RichNumber::from(self.value.cos())
    }

    pub fn tan(&self) -> RichNumber {
        RichNumber::from(self.value.tan())
    }

    pub fn asin(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.asin(), self.unit)
    }

    pub fn acos(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.acos(), self.unit)
    }

    pub fn atan(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.atan(), self.unit)
    }

    pub fn sinh(&self) -> RichNumber {
        RichNumber::from(self.value.sinh())
    }

    pub fn cosh(&self) -> RichNumber {
        RichNumber::from(self.value.cosh())
    }

    pub fn tanh(&self) -> RichNumber {
        RichNumber::from(self.value.tanh())
    }

    pub fn asinh(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.asinh(), self.unit)
    }

    pub fn acosh(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.acosh(), self.unit)
    }

    pub fn atanh(&self) -> RichNumber {
        assert!(self.is_dimensionless(), "Only supports dimensionless/scalar quantities");

        RichNumber::new(self.value.atanh(), self.unit)
    }

    /// Applies an operator to two values given the values and what the resulting unit should be
    fn apply_operator<F>(self, other: RichNumber, operator: F, unit: Option<Unit>) -> RichNumber
        where F: FnOnce(f64, f64) -> f64 {

        let value = operator(self.value, other.value);
        RichNumber::new(value, unit)
    }
}

impl From<i64> for RichNumber {
    fn from(number: i64) -> RichNumber {
        RichNumber::from(number as f64)
    }
}

impl From<f64> for RichNumber {
    fn from(number: f64) -> RichNumber {
        RichNumber::new(number, None)
    }
}

impl PartialEq for RichNumber {
    fn eq(&self, other: &RichNumber) -> bool {
        assert!(self.unit == other.unit,
            "Cannot compare values with different units");

        (self.value - other.value).abs() < 1e-10
    }
}

impl Eq for RichNumber {}

impl PartialOrd for RichNumber {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        assert!(self.unit == other.unit,
            "Cannot compare values with different units");

        self.value.partial_cmp(&other.value)
    }
}

impl Neg for RichNumber {
    type Output = RichNumber;

    fn neg(self) -> Self::Output {
        RichNumber::new(-self.value, self.unit)
    }
}

impl Add for RichNumber {
    type Output = RichNumber;

    fn add(self, other: RichNumber) -> Self::Output {
        assert!(self.unit == other.unit,
            "Cannot add values with different units");
        self.apply_operator(other, |a, b| a + b, self.unit)
    }
}

impl Sub for RichNumber {
    type Output = RichNumber;

    fn sub(self, other: RichNumber) -> Self::Output {
        assert!(self.unit == other.unit,
            "Cannot subtract values with different units");
        self.apply_operator(other, |a, b| a - b, self.unit)
    }
}

impl Mul for RichNumber {
    type Output = RichNumber;

    fn mul(self, other: RichNumber) -> Self::Output {
        let unit;
        if self.is_dimensionless() {
            unit = other.unit;
        }
        else if other.is_dimensionless() {
            unit = self.unit;
        }
        else {
            panic!("Multiplying units is not supported yet. Try a dimensionaless/scalar value");
        }

        self.apply_operator(other, |a, b| a * b, unit)
    }
}

impl Div for RichNumber {
    type Output = RichNumber;

    fn div(self, other: RichNumber) -> Self::Output {
        let unit;
        if other.is_dimensionless() {
            unit = self.unit;
        }
        else if self.unit == other.unit {
            unit = None;
        }
        else {
            panic!("Dividing units is not supported yet. Use two values with the same unit or multiply by a dimensionless/scalar value");
        }

        self.apply_operator(other, |a, b| a / b, unit)
    }
}

impl Rem for RichNumber {
    type Output = RichNumber;

    fn rem(self, other: RichNumber) -> Self::Output {
        let unit;
        if other.is_dimensionless() {
            unit = self.unit;
        }
        else if self.unit == other.unit {
            unit = None;
        }
        else {
            panic!("Taking the remainder of quantities with units is not supported. Use two values with the same unit or multiply by a dimensionless/scalar value");
        }

        self.apply_operator(other, |a, b| a % b, unit)
    }
}

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

    #[test]
    fn equality() {
        let a = RichNumber::from(2);
        let b = RichNumber::from(2);
        let c = RichNumber::from(3.6);

        assert_eq!(a, b);
        assert!(a != c);
    }

    #[test]
    fn basic_operations() {
        let a = RichNumber::from(2);
        let b = RichNumber::from(3.6);

        assert_eq!(a + b, RichNumber::from(5.6f64));
        assert_eq!(b + a, RichNumber::from(5.6f64));

        assert_eq!(a - b, RichNumber::from(-1.6f64));
        assert_eq!(b - a, RichNumber::from(1.6f64));

        assert_eq!(a * b, RichNumber::from(7.2f64));
        assert_eq!(b * a, RichNumber::from(7.2f64));

        assert_eq!(a / b, RichNumber::from(0.55555555555f64));
        assert_eq!(b / a, RichNumber::from(1.8f64));

        assert_eq!(a % b, RichNumber::from(2f64));
        assert_eq!(b % a, RichNumber::from(1.6f64));
    }

    #[test]
    fn ordering() {
        let a = RichNumber::from(2);
        let b = RichNumber::from(3.6666666666666);
        let c = RichNumber::from(3.6666666666667);
        let d = RichNumber::from(3.6666666666667);

        assert!(a < b);
        assert!(b < c);
        assert!(c <= d);
        assert!(d > b);
        assert!(b >= a);
    }
}

<|endoftext|>


<commit_before>#![feature(plugin)]
#![allow(unstable)]

extern crate maud;
#[plugin] #[no_link] extern crate maud_macros;

#[test]
fn literals() {
    let s = html!("du\tcks" -23 3.14 '\n' "geese").render();
    assert_eq!(s, "du\tcks-233.14\ngeese");
}

#[test]
fn escaping() {
    let s = html!("<flim&flam>").render();
    assert_eq!(s, "<flim&flam>");
}

#[test]
fn semicolons() {
    let s = html! {
        "one";
        "two";
        "three";
        ;;;;;;;;;;;;;;;;;;;;;;;;
        "four";
    }.render();
    assert_eq!(s, "onetwothreefour");
}

#[test]
fn blocks() {
    let s = html! {
        "hello"
        {
            " ducks" " geese"
        }
        " swans"
    }.render();
    assert_eq!(s, "hello ducks geese swans");
}

mod elements {
    #[test]
    fn simple() {
        let s = html! {
            p { b { "pickle" } "barrel" i { "kumquat" } }
        }.render();
        assert_eq!(s, "
picklebarrelkumquat
");
    }

    #[test]
    fn nesting() {
        let s = html!(html body div p sup "butts").render();
        assert_eq!(s, "

butts

");
    }

    #[test]
    fn empty() {
        let s = html!("pinkie" br/ "pie").render();
        assert_eq!(s, "pinkie
pie");
    }

    #[test]
    fn attributes() {
        let s = html! {
            link rel="stylesheet" href="styles.css"/
            section id="midriff" {
                p class="hotpink" "Hello!"
            }
        }.render();
        assert_eq!(s, concat!(
                r#"<link rel="stylesheet" href="styles.css">"#,
                r#"

Hello!

"#));
    }

    #[test]
    fn empty_attributes() {
        let s = html! { div readonly=! input type="checkbox" checked=! / }.render();
        assert_eq!(s, r#"
<input type="checkbox" checked>
"#);
    }
}

mod splices {
    #[test]
    fn literals() {
        let s = html! { $"<pinkie>" }.render();
        assert_eq!(s, "<pinkie>");
    }

    #[test]
    fn raw_literals() {
        let s = html! { $$"<pinkie>" }.render();
        assert_eq!(s, "<pinkie>");
    }

    #[test]
    fn blocks() {
        let s = html! {
            ${
                let mut result = 1i32;
                for i in range(2, 11) {
                    result *= i;
                }
                result
            }
        }.render();
        assert_eq!(s, "3628800");
    }

    static BEST_PONY: &'static str = "Pinkie Pie";

    #[test]
    fn statics() {
        let s = html! { $BEST_PONY }.render();
        assert_eq!(s, "Pinkie Pie");
    }

    #[test]
    fn closures() {
        let best_pony = "Pinkie Pie";
        let s = html! { $best_pony }.render();
        assert_eq!(s, "Pinkie Pie");
    }

    /// An example struct, for testing purposes only
    struct Creature {
        name: &'static str,
        /// Rating out of 10, where:
        /// * 0 is a naked mole rat with dysentery
        /// * 10 is Sweetie Belle in a milkshake
        adorableness: u8,
    }

    impl Creature {
        fn repugnance(&self) -> u8 {
            10 - self.adorableness
        }
    }

    #[test]
    fn structs() {
        let pinkie = Creature {
            name: "Pinkie Pie",
            adorableness: 9,
        };
        let s = html! {
            "Name: " $pinkie.name ". Rating: " $pinkie.repugnance()
        }.render();
        assert_eq!(s, "Name: Pinkie Pie. Rating: 1");
    }

    // FIXME: See <https://github.com/rust-lang/rust/issues/16617>
    // for why this is commented out
    /*
    #[test]
    fn nested_macro_invocation() {
        let best_pony = "Pinkie Pie";
        let s = html! { $(format!("{}", best_pony)) }.render();
        assert_eq!(s, "Pinkie Pie");
    }
    */
}
<commit_msg>Add regression test for #1<commit_after>#![feature(plugin)]
#![allow(unstable)]

extern crate maud;
#[plugin] #[no_link] extern crate maud_macros;

#[test]
fn literals() {
    let s = html!("du\tcks" -23 3.14 '\n' "geese").render();
    assert_eq!(s, "du\tcks-233.14\ngeese");
}

#[test]
fn escaping() {
    let s = html!("<flim&flam>").render();
    assert_eq!(s, "<flim&flam>");
}

#[test]
fn semicolons() {
    let s = html! {
        "one";
        "two";
        "three";
        ;;;;;;;;;;;;;;;;;;;;;;;;
        "four";
    }.render();
    assert_eq!(s, "onetwothreefour");
}

#[test]
fn blocks() {
    let s = html! {
        "hello"
        {
            " ducks" " geese"
        }
        " swans"
    }.render();
    assert_eq!(s, "hello ducks geese swans");
}

mod elements {
    #[test]
    fn simple() {
        let s = html! {
            p { b { "pickle" } "barrel" i { "kumquat" } }
        }.render();
        assert_eq!(s, "
picklebarrelkumquat
");
    }

    #[test]
    fn nesting() {
        let s = html!(html body div p sup "butts").render();
        assert_eq!(s, "

butts

");
    }

    #[test]
    fn empty() {
        let s = html!("pinkie" br/ "pie").render();
        assert_eq!(s, "pinkie
pie");
    }

    #[test]
    fn attributes() {
        let s = html! {
            link rel="stylesheet" href="styles.css"/
            section id="midriff" {
                p class="hotpink" "Hello!"
            }
        }.render();
        assert_eq!(s, concat!(
                r#"<link rel="stylesheet" href="styles.css">"#,
                r#"

Hello!

"#));
    }

    #[test]
    fn empty_attributes() {
        let s = html! { div readonly=! input type="checkbox" checked=! / }.render();
        assert_eq!(s, r#"
<input type="checkbox" checked>
"#);
    }
}

mod splices {
    #[test]
    fn literals() {
        let s = html! { $"<pinkie>" }.render();
        assert_eq!(s, "<pinkie>");
    }

    #[test]
    fn raw_literals() {
        let s = html! { $$"<pinkie>" }.render();
        assert_eq!(s, "<pinkie>");
    }

    #[test]
    fn blocks() {
        let s = html! {
            ${
                let mut result = 1i32;
                for i in range(2, 11) {
                    result *= i;
                }
                result
            }
        }.render();
        assert_eq!(s, "3628800");
    }

    static BEST_PONY: &'static str = "Pinkie Pie";

    #[test]
    fn statics() {
        let s = html! { $BEST_PONY }.render();
        assert_eq!(s, "Pinkie Pie");
    }

    #[test]
    fn closures() {
        let best_pony = "Pinkie Pie";
        let s = html! { $best_pony }.render();
        assert_eq!(s, "Pinkie Pie");
    }

    /// An example struct, for testing purposes only
    struct Creature {
        name: &'static str,
        /// Rating out of 10, where:
        /// * 0 is a naked mole rat with dysentery
        /// * 10 is Sweetie Belle in a milkshake
        adorableness: u8,
    }

    impl Creature {
        fn repugnance(&self) -> u8 {
            10 - self.adorableness
        }
    }

    #[test]
    fn structs() {
        let pinkie = Creature {
            name: "Pinkie Pie",
            adorableness: 9,
        };
        let s = html! {
            "Name: " $pinkie.name ". Rating: " $pinkie.repugnance()
        }.render();
        assert_eq!(s, "Name: Pinkie Pie. Rating: 1");
    }

    // FIXME: See <https://github.com/rust-lang/rust/issues/16617>
    // for why this is commented out
    /*
    #[test]
    fn nested_macro_invocation() {
        let best_pony = "Pinkie Pie";
        let s = html! { $(format!("{}", best_pony)) }.render();
        assert_eq!(s, "Pinkie Pie");
    }
    */
}

#[test]
fn issue_1() {
    let markup = html! { "Test" };
    let _ = markup.render();
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use cast::GTK_TOGGLEBUTTON;
use ffi;
use glib::{to_bool, to_gboolean};

pub trait ToggleButtonTrait: ::WidgetTrait + ::ContainerTrait + ::ButtonTrait {
    fn set_mode(&self, draw_indicate: bool) {
        unsafe { ffi::gtk_toggle_button_set_mode(GTK_TOGGLEBUTTON(self.unwrap_widget()), to_gboolean(draw_indicate)); }
    }

    fn get_mode(&self) -> bool {
        unsafe { to_bool(ffi::gtk_toggle_button_get_mode(GTK_TOGGLEBUTTON(self.unwrap_widget()))) }
    }

    fn toggled(&self) -> () {
        unsafe {
            ffi::gtk_toggle_button_toggled(GTK_TOGGLEBUTTON(self.unwrap_widget()))
        }
    }

    fn set_active(&self, is_active: bool) {
        unsafe { ffi::gtk_toggle_button_set_active(GTK_TOGGLEBUTTON(self.unwrap_widget()), to_gboolean(is_active)); }
    }

    fn get_active(&self) -> bool {
        unsafe { to_bool(ffi::gtk_toggle_button_get_active(GTK_TOGGLEBUTTON(self.unwrap_widget()))) }
    }

    fn set_inconsistent(&self, setting: bool) {
        unsafe { ffi::gtk_toggle_button_set_inconsistent(GTK_TOGGLEBUTTON(self.unwrap_widget()), to_gboolean(setting)); }
    }

    fn get_inconsistent(&self) -> bool {
        unsafe { to_bool(ffi::gtk_toggle_button_get_inconsistent(GTK_TOGGLEBUTTON(self.unwrap_widget()))) }
    }
}

<commit_msg>Remove legacy ToggleButtonTrait<commit_after><|endoftext|>


<commit_before>/*pub use api::x11::{Window, WindowProxy, MonitorId, get_available_monitors, get_primary_monitor};
pub use api::x11::{WaitEventsIterator, PollEventsIterator};*/

use std::collections::VecDeque;
use std::sync::Arc;

use ContextError;
use CreationError;
use CursorState;
use Event;
use GlAttributes;
use GlContext;
use MouseCursor;
use PixelFormat;
use PixelFormatRequirements;
use WindowAttributes;
use libc;

use api::wayland;
use api::x11;
use api::x11::XConnection;
use api::x11::XError;
use api::x11::XNotSupported;

#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes;

enum Backend {
    X(Arc<XConnection>),
    Wayland,
    Error(XNotSupported),
}

lazy_static!(
    static ref BACKEND: Backend = {
        // Wayland backend is not production-ready yet so we disable it
        if wayland::is_available() {
            Backend::Wayland
        } else {
            match XConnection::new(Some(x_error_callback)) {
                Ok(x) => Backend::X(Arc::new(x)),
                Err(e) => Backend::Error(e),
            }
        }
    };
);

pub enum Window {
    #[doc(hidden)]
    X(x11::Window),
    #[doc(hidden)]
    Wayland(wayland::Window)
}

#[derive(Clone)]
pub enum WindowProxy {
    #[doc(hidden)]
    X(x11::WindowProxy),
    #[doc(hidden)]
    Wayland(wayland::WindowProxy)
}

impl WindowProxy {
    #[inline]
    pub fn wakeup_event_loop(&self) {
        match self {
            &WindowProxy::X(ref wp) => wp.wakeup_event_loop(),
            &WindowProxy::Wayland(ref wp) => wp.wakeup_event_loop()
        }
    }
}

#[derive(Clone)]
pub enum MonitorId {
    #[doc(hidden)]
    X(x11::MonitorId),
    #[doc(hidden)]
    Wayland(wayland::MonitorId),
    #[doc(hidden)]
    None,
}

#[inline]
pub fn get_available_monitors() -> VecDeque<MonitorId> {
    match *BACKEND {
        Backend::Wayland => wayland::get_available_monitors()
                                .into_iter()
                                .map(MonitorId::Wayland)
                                .collect(),
        Backend::X(ref connec) => x11::get_available_monitors(connec)
                                    .into_iter()
                                    .map(MonitorId::X)
                                    .collect(),
        Backend::Error(_) => { let mut d = VecDeque::new(); d.push_back(MonitorId::None); d},
    }
}

#[inline]
pub fn get_primary_monitor() -> MonitorId {
    match *BACKEND {
        Backend::Wayland => MonitorId::Wayland(wayland::get_primary_monitor()),
        Backend::X(ref connec) => MonitorId::X(x11::get_primary_monitor(connec)),
        Backend::Error(_) => MonitorId::None,
    }
}

impl MonitorId {
    #[inline]
    pub fn get_name(&self) -> Option<String> {
        match self {
            &MonitorId::X(ref m) => m.get_name(),
            &MonitorId::Wayland(ref m) => m.get_name(),
            &MonitorId::None => None,
        }
    }

    #[inline]
    pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {
        match self {
            &MonitorId::X(ref m) => m.get_native_identifier(),
            &MonitorId::Wayland(ref m) => m.get_native_identifier(),
            &MonitorId::None => unimplemented!()        // FIXME:
        }
    }

    #[inline]
    pub fn get_dimensions(&self) -> (u32, u32) {
        match self {
            &MonitorId::X(ref m) => m.get_dimensions(),
            &MonitorId::Wayland(ref m) => m.get_dimensions(),
            &MonitorId::None => (800, 600),     // FIXME:
        }
    }
}

pub enum PollEventsIterator<'a> {
    #[doc(hidden)]
    X(x11::PollEventsIterator<'a>),
    #[doc(hidden)]
    Wayland(wayland::PollEventsIterator<'a>)
}

impl<'a> Iterator for PollEventsIterator<'a> {
    type Item = Event;

    #[inline]
    fn next(&mut self) -> Option<Event> {
        match self {
            &mut PollEventsIterator::X(ref mut it) => it.next(),
            &mut PollEventsIterator::Wayland(ref mut it) => it.next()
        }
    }
}

pub enum WaitEventsIterator<'a> {
    #[doc(hidden)]
    X(x11::WaitEventsIterator<'a>),
    #[doc(hidden)]
    Wayland(wayland::WaitEventsIterator<'a>)
}

impl<'a> Iterator for WaitEventsIterator<'a> {
    type Item = Event;

    #[inline]
    fn next(&mut self) -> Option<Event> {
        match self {
            &mut WaitEventsIterator::X(ref mut it) => it.next(),
            &mut WaitEventsIterator::Wayland(ref mut it) => it.next()
        }
    }
}

impl Window {
    #[inline]
    pub fn new(window: &WindowAttributes, pf_reqs: &PixelFormatRequirements,
               opengl: &GlAttributes<&Window>, _: &PlatformSpecificWindowBuilderAttributes)
               -> Result<Window, CreationError>
    {
        match *BACKEND {
            Backend::Wayland => {
                let opengl = opengl.clone().map_sharing(|w| match w {
                    &Window::Wayland(ref w) => w,
                    _ => panic!()       // TODO: return an error
                });

                wayland::Window::new(window, pf_reqs, &opengl).map(Window::Wayland)
            },

            Backend::X(ref connec) => {
                let opengl = opengl.clone().map_sharing(|w| match w {
                    &Window::X(ref w) => w,
                    _ => panic!()       // TODO: return an error
                });

                x11::Window::new(connec, window, pf_reqs, &opengl).map(Window::X)
            },

            Backend::Error(ref error) => Err(CreationError::NoBackendAvailable(Box::new(error.clone())))
        }
    }

    #[inline]
    pub fn set_title(&self, title: &str) {
        match self {
            &Window::X(ref w) => w.set_title(title),
            &Window::Wayland(ref w) => w.set_title(title)
        }
    }

    #[inline]
    pub fn show(&self) {
        match self {
            &Window::X(ref w) => w.show(),
            &Window::Wayland(ref w) => w.show()
        }
    }

    #[inline]
    pub fn hide(&self) {
        match self {
            &Window::X(ref w) => w.hide(),
            &Window::Wayland(ref w) => w.hide()
        }
    }

    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        match self {
            &Window::X(ref w) => w.get_position(),
            &Window::Wayland(ref w) => w.get_position()
        }
    }

    #[inline]
    pub fn set_position(&self, x: i32, y: i32) {
        match self {
            &Window::X(ref w) => w.set_position(x, y),
            &Window::Wayland(ref w) => w.set_position(x, y)
        }
    }

    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        match self {
            &Window::X(ref w) => w.get_inner_size(),
            &Window::Wayland(ref w) => w.get_inner_size()
        }
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        match self {
            &Window::X(ref w) => w.get_outer_size(),
            &Window::Wayland(ref w) => w.get_outer_size()
        }
    }

    #[inline]
    pub fn set_inner_size(&self, x: u32, y: u32) {
        match self {
            &Window::X(ref w) => w.set_inner_size(x, y),
            &Window::Wayland(ref w) => w.set_inner_size(x, y)
        }
    }

    #[inline]
    pub fn create_window_proxy(&self) -> WindowProxy {
        match self {
            &Window::X(ref w) => WindowProxy::X(w.create_window_proxy()),
            &Window::Wayland(ref w) => WindowProxy::Wayland(w.create_window_proxy())
        }
    }

    #[inline]
    pub fn poll_events(&self) -> PollEventsIterator {
        match self {
            &Window::X(ref w) => PollEventsIterator::X(w.poll_events()),
            &Window::Wayland(ref w) => PollEventsIterator::Wayland(w.poll_events())
        }
    }

    #[inline]
    pub fn wait_events(&self) -> WaitEventsIterator {
        match self {
            &Window::X(ref w) => WaitEventsIterator::X(w.wait_events()),
            &Window::Wayland(ref w) => WaitEventsIterator::Wayland(w.wait_events())
        }
    }

    #[inline]
    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
        match self {
            &mut Window::X(ref mut w) => w.set_window_resize_callback(callback),
            &mut Window::Wayland(ref mut w) => w.set_window_resize_callback(callback)
        }
    }

    #[inline]
    pub fn set_cursor(&self, cursor: MouseCursor) {
        match self {
            &Window::X(ref w) => w.set_cursor(cursor),
            &Window::Wayland(ref w) => w.set_cursor(cursor)
        }
    }

    #[inline]
    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
        match self {
            &Window::X(ref w) => w.set_cursor_state(state),
            &Window::Wayland(ref w) => w.set_cursor_state(state)
        }
    }

    #[inline]
    pub fn hidpi_factor(&self) -> f32 {
       match self {
            &Window::X(ref w) => w.hidpi_factor(),
            &Window::Wayland(ref w) => w.hidpi_factor()
        }
    }

    #[inline]
    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        match self {
            &Window::X(ref w) => w.set_cursor_position(x, y),
            &Window::Wayland(ref w) => w.set_cursor_position(x, y)
        }
    }

    #[inline]
    pub fn platform_display(&self) -> *mut libc::c_void {
        match self {
            &Window::X(ref w) => w.platform_display(),
            &Window::Wayland(ref w) => w.platform_display()
        }
    }

    #[inline]
    pub fn platform_window(&self) -> *mut libc::c_void {
        match self {
            &Window::X(ref w) => w.platform_window(),
            &Window::Wayland(ref w) => w.platform_window()
        }
    }
}

impl GlContext for Window {
    #[inline]
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        match self {
            &Window::X(ref w) => w.make_current(),
            &Window::Wayland(ref w) => w.make_current()
        }
    }

    #[inline]
    fn is_current(&self) -> bool {
        match self {
            &Window::X(ref w) => w.is_current(),
            &Window::Wayland(ref w) => w.is_current()
        }
    }

    #[inline]
    fn get_proc_address(&self, addr: &str) -> *const () {
        match self {
            &Window::X(ref w) => w.get_proc_address(addr),
            &Window::Wayland(ref w) => w.get_proc_address(addr)
        }
    }

    #[inline]
    fn swap_buffers(&self) -> Result<(), ContextError> {
        match self {
            &Window::X(ref w) => w.swap_buffers(),
            &Window::Wayland(ref w) => w.swap_buffers()
        }
    }

    #[inline]
    fn get_api(&self) -> ::Api {
        match self {
            &Window::X(ref w) => w.get_api(),
            &Window::Wayland(ref w) => w.get_api()
        }
    }

    #[inline]
    fn get_pixel_format(&self) -> PixelFormat {
        match self {
            &Window::X(ref w) => w.get_pixel_format(),
            &Window::Wayland(ref w) => w.get_pixel_format()
        }
    }
}

unsafe extern "C" fn x_error_callback(dpy: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent)
                                      -> libc::c_int
{
    use std::ffi::CStr;

    if let Backend::X(ref x) = *BACKEND {
        let mut buff: Vec<u8> = Vec::with_capacity(1024);
        (x.xlib.XGetErrorText)(dpy, (*event).error_code as i32, buff.as_mut_ptr() as *mut libc::c_char, buff.capacity() as i32);
        let description = CStr::from_ptr(buff.as_mut_ptr() as *const libc::c_char).to_string_lossy();

        let error = XError {
            description: description.into_owned(),
            error_code: (*event).error_code,
            request_code: (*event).request_code,
            minor_code: (*event).minor_code,
        };

        *x.latest_error.lock().unwrap() = Some(error);
    }

    0
}
<commit_msg>linux: Disable Wayland backend because it's unusable for Servo.<commit_after>/*pub use api::x11::{Window, WindowProxy, MonitorId, get_available_monitors, get_primary_monitor};
pub use api::x11::{WaitEventsIterator, PollEventsIterator};*/

use std::collections::VecDeque;
use std::sync::Arc;

use ContextError;
use CreationError;
use CursorState;
use Event;
use GlAttributes;
use GlContext;
use MouseCursor;
use PixelFormat;
use PixelFormatRequirements;
use WindowAttributes;
use libc;

use api::wayland;
use api::x11;
use api::x11::XConnection;
use api::x11::XError;
use api::x11::XNotSupported;

#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes;

enum Backend {
    X(Arc<XConnection>),
    Wayland,
    Error(XNotSupported),
}

lazy_static!(
    static ref BACKEND: Backend = {
        // Wayland backend is not production-ready yet so we disable it
        if false && wayland::is_available() {
            Backend::Wayland
        } else {
            match XConnection::new(Some(x_error_callback)) {
                Ok(x) => Backend::X(Arc::new(x)),
                Err(e) => Backend::Error(e),
            }
        }
    };
);

pub enum Window {
    #[doc(hidden)]
    X(x11::Window),
    #[doc(hidden)]
    Wayland(wayland::Window)
}

#[derive(Clone)]
pub enum WindowProxy {
    #[doc(hidden)]
    X(x11::WindowProxy),
    #[doc(hidden)]
    Wayland(wayland::WindowProxy)
}

impl WindowProxy {
    #[inline]
    pub fn wakeup_event_loop(&self) {
        match self {
            &WindowProxy::X(ref wp) => wp.wakeup_event_loop(),
            &WindowProxy::Wayland(ref wp) => wp.wakeup_event_loop()
        }
    }
}

#[derive(Clone)]
pub enum MonitorId {
    #[doc(hidden)]
    X(x11::MonitorId),
    #[doc(hidden)]
    Wayland(wayland::MonitorId),
    #[doc(hidden)]
    None,
}

#[inline]
pub fn get_available_monitors() -> VecDeque<MonitorId> {
    match *BACKEND {
        Backend::Wayland => wayland::get_available_monitors()
                                .into_iter()
                                .map(MonitorId::Wayland)
                                .collect(),
        Backend::X(ref connec) => x11::get_available_monitors(connec)
                                    .into_iter()
                                    .map(MonitorId::X)
                                    .collect(),
        Backend::Error(_) => { let mut d = VecDeque::new(); d.push_back(MonitorId::None); d},
    }
}

#[inline]
pub fn get_primary_monitor() -> MonitorId {
    match *BACKEND {
        Backend::Wayland => MonitorId::Wayland(wayland::get_primary_monitor()),
        Backend::X(ref connec) => MonitorId::X(x11::get_primary_monitor(connec)),
        Backend::Error(_) => MonitorId::None,
    }
}

impl MonitorId {
    #[inline]
    pub fn get_name(&self) -> Option<String> {
        match self {
            &MonitorId::X(ref m) => m.get_name(),
            &MonitorId::Wayland(ref m) => m.get_name(),
            &MonitorId::None => None,
        }
    }

    #[inline]
    pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {
        match self {
            &MonitorId::X(ref m) => m.get_native_identifier(),
            &MonitorId::Wayland(ref m) => m.get_native_identifier(),
            &MonitorId::None => unimplemented!()        // FIXME:
        }
    }

    #[inline]
    pub fn get_dimensions(&self) -> (u32, u32) {
        match self {
            &MonitorId::X(ref m) => m.get_dimensions(),
            &MonitorId::Wayland(ref m) => m.get_dimensions(),
            &MonitorId::None => (800, 600),     // FIXME:
        }
    }
}

pub enum PollEventsIterator<'a> {
    #[doc(hidden)]
    X(x11::PollEventsIterator<'a>),
    #[doc(hidden)]
    Wayland(wayland::PollEventsIterator<'a>)
}

impl<'a> Iterator for PollEventsIterator<'a> {
    type Item = Event;

    #[inline]
    fn next(&mut self) -> Option<Event> {
        match self {
            &mut PollEventsIterator::X(ref mut it) => it.next(),
            &mut PollEventsIterator::Wayland(ref mut it) => it.next()
        }
    }
}

pub enum WaitEventsIterator<'a> {
    #[doc(hidden)]
    X(x11::WaitEventsIterator<'a>),
    #[doc(hidden)]
    Wayland(wayland::WaitEventsIterator<'a>)
}

impl<'a> Iterator for WaitEventsIterator<'a> {
    type Item = Event;

    #[inline]
    fn next(&mut self) -> Option<Event> {
        match self {
            &mut WaitEventsIterator::X(ref mut it) => it.next(),
            &mut WaitEventsIterator::Wayland(ref mut it) => it.next()
        }
    }
}

impl Window {
    #[inline]
    pub fn new(window: &WindowAttributes, pf_reqs: &PixelFormatRequirements,
               opengl: &GlAttributes<&Window>, _: &PlatformSpecificWindowBuilderAttributes)
               -> Result<Window, CreationError>
    {
        match *BACKEND {
            Backend::Wayland => {
                let opengl = opengl.clone().map_sharing(|w| match w {
                    &Window::Wayland(ref w) => w,
                    _ => panic!()       // TODO: return an error
                });

                wayland::Window::new(window, pf_reqs, &opengl).map(Window::Wayland)
            },

            Backend::X(ref connec) => {
                let opengl = opengl.clone().map_sharing(|w| match w {
                    &Window::X(ref w) => w,
                    _ => panic!()       // TODO: return an error
                });

                x11::Window::new(connec, window, pf_reqs, &opengl).map(Window::X)
            },

            Backend::Error(ref error) => Err(CreationError::NoBackendAvailable(Box::new(error.clone())))
        }
    }

    #[inline]
    pub fn set_title(&self, title: &str) {
        match self {
            &Window::X(ref w) => w.set_title(title),
            &Window::Wayland(ref w) => w.set_title(title)
        }
    }

    #[inline]
    pub fn show(&self) {
        match self {
            &Window::X(ref w) => w.show(),
            &Window::Wayland(ref w) => w.show()
        }
    }

    #[inline]
    pub fn hide(&self) {
        match self {
            &Window::X(ref w) => w.hide(),
            &Window::Wayland(ref w) => w.hide()
        }
    }

    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        match self {
            &Window::X(ref w) => w.get_position(),
            &Window::Wayland(ref w) => w.get_position()
        }
    }

    #[inline]
    pub fn set_position(&self, x: i32, y: i32) {
        match self {
            &Window::X(ref w) => w.set_position(x, y),
            &Window::Wayland(ref w) => w.set_position(x, y)
        }
    }

    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        match self {
            &Window::X(ref w) => w.get_inner_size(),
            &Window::Wayland(ref w) => w.get_inner_size()
        }
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        match self {
            &Window::X(ref w) => w.get_outer_size(),
            &Window::Wayland(ref w) => w.get_outer_size()
        }
    }

    #[inline]
    pub fn set_inner_size(&self, x: u32, y: u32) {
        match self {
            &Window::X(ref w) => w.set_inner_size(x, y),
            &Window::Wayland(ref w) => w.set_inner_size(x, y)
        }
    }

    #[inline]
    pub fn create_window_proxy(&self) -> WindowProxy {
        match self {
            &Window::X(ref w) => WindowProxy::X(w.create_window_proxy()),
            &Window::Wayland(ref w) => WindowProxy::Wayland(w.create_window_proxy())
        }
    }

    #[inline]
    pub fn poll_events(&self) -> PollEventsIterator {
        match self {
            &Window::X(ref w) => PollEventsIterator::X(w.poll_events()),
            &Window::Wayland(ref w) => PollEventsIterator::Wayland(w.poll_events())
        }
    }

    #[inline]
    pub fn wait_events(&self) -> WaitEventsIterator {
        match self {
            &Window::X(ref w) => WaitEventsIterator::X(w.wait_events()),
            &Window::Wayland(ref w) => WaitEventsIterator::Wayland(w.wait_events())
        }
    }

    #[inline]
    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
        match self {
            &mut Window::X(ref mut w) => w.set_window_resize_callback(callback),
            &mut Window::Wayland(ref mut w) => w.set_window_resize_callback(callback)
        }
    }

    #[inline]
    pub fn set_cursor(&self, cursor: MouseCursor) {
        match self {
            &Window::X(ref w) => w.set_cursor(cursor),
            &Window::Wayland(ref w) => w.set_cursor(cursor)
        }
    }

    #[inline]
    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
        match self {
            &Window::X(ref w) => w.set_cursor_state(state),
            &Window::Wayland(ref w) => w.set_cursor_state(state)
        }
    }

    #[inline]
    pub fn hidpi_factor(&self) -> f32 {
       match self {
            &Window::X(ref w) => w.hidpi_factor(),
            &Window::Wayland(ref w) => w.hidpi_factor()
        }
    }

    #[inline]
    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        match self {
            &Window::X(ref w) => w.set_cursor_position(x, y),
            &Window::Wayland(ref w) => w.set_cursor_position(x, y)
        }
    }

    #[inline]
    pub fn platform_display(&self) -> *mut libc::c_void {
        match self {
            &Window::X(ref w) => w.platform_display(),
            &Window::Wayland(ref w) => w.platform_display()
        }
    }

    #[inline]
    pub fn platform_window(&self) -> *mut libc::c_void {
        match self {
            &Window::X(ref w) => w.platform_window(),
            &Window::Wayland(ref w) => w.platform_window()
        }
    }
}

impl GlContext for Window {
    #[inline]
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        match self {
            &Window::X(ref w) => w.make_current(),
            &Window::Wayland(ref w) => w.make_current()
        }
    }

    #[inline]
    fn is_current(&self) -> bool {
        match self {
            &Window::X(ref w) => w.is_current(),
            &Window::Wayland(ref w) => w.is_current()
        }
    }

    #[inline]
    fn get_proc_address(&self, addr: &str) -> *const () {
        match self {
            &Window::X(ref w) => w.get_proc_address(addr),
            &Window::Wayland(ref w) => w.get_proc_address(addr)
        }
    }

    #[inline]
    fn swap_buffers(&self) -> Result<(), ContextError> {
        match self {
            &Window::X(ref w) => w.swap_buffers(),
            &Window::Wayland(ref w) => w.swap_buffers()
        }
    }

    #[inline]
    fn get_api(&self) -> ::Api {
        match self {
            &Window::X(ref w) => w.get_api(),
            &Window::Wayland(ref w) => w.get_api()
        }
    }

    #[inline]
    fn get_pixel_format(&self) -> PixelFormat {
        match self {
            &Window::X(ref w) => w.get_pixel_format(),
            &Window::Wayland(ref w) => w.get_pixel_format()
        }
    }
}

unsafe extern "C" fn x_error_callback(dpy: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent)
                                      -> libc::c_int
{
    use std::ffi::CStr;

    if let Backend::X(ref x) = *BACKEND {
        let mut buff: Vec<u8> = Vec::with_capacity(1024);
        (x.xlib.XGetErrorText)(dpy, (*event).error_code as i32, buff.as_mut_ptr() as *mut libc::c_char, buff.capacity() as i32);
        let description = CStr::from_ptr(buff.as_mut_ptr() as *const libc::c_char).to_string_lossy();

        let error = XError {
            description: description.into_owned(),
            error_code: (*event).error_code,
            request_code: (*event).request_code,
            minor_code: (*event).minor_code,
        };

        *x.latest_error.lock().unwrap() = Some(error);
    }

    0
}
<|endoftext|>


<commit_before>/// Logs a message at the info level.
///
/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
/// contains special tags for controlling ANSI colors and styles
/// More info: https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html
///
/// # Examples
///
/// ```edition2018
/// use log::info;
///
/// # fn main() {
/// # struct Connection { port: u32, speed: f32 }
/// let conn_info = Connection { port: 40, speed: 3.20 };
///
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
///       conn_info.port, conn_info.speed);
/// # }
/// ```
#[macro_export]
macro_rules! info {
    ($($args:tt)+) => {
        log::info!("{}", paris::formatter::colorize_string(format!($($args)*)));
    };
}

/// Logs a message at the debug level.
///
/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
/// contains special tags for controlling ANSI colors and styles
/// More info: https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html
///
/// # Examples
///
/// ```edition2018
/// use log::debug;
///
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
/// # }
/// ```
#[macro_export]
macro_rules! debug {
    ($($args:tt)+) => {
        log::debug!("{}", paris::formatter::colorize_string(format!($($args)*)));
    };
}

/// Logs a message at the trace level.
///
/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
/// contains special tags for controlling ANSI colors and styles
/// More info: https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html
///
/// # Examples
///
/// ```edition2018
/// use log::trace;
///
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
/// trace!(target: "app_events", "x is {} and y is {}",
///        if pos.x >= 0.0 { "positive" } else { "negative" },
///        if pos.y >= 0.0 { "positive" } else { "negative" });
/// # }
/// ```
#[macro_export]
macro_rules! trace {
    ($($args:tt)+) => {
        log::trace!("{}", paris::formatter::colorize_string(format!($($args)*)));
    };
}

/// Logs a message at the warn level.
///
/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
/// contains special tags for controlling ANSI colors and styles
/// More info: https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html
///
/// # Examples
///
/// ```edition2018
/// use log::warn;
///
/// # fn main() {
/// let warn_description = "Invalid Input";
///
/// warn!("Warning! {}!", warn_description);
/// warn!(target: "input_events", "App received warning: {}", warn_description);
/// # }
/// ```
#[macro_export]
macro_rules! warn {
    ($($args:tt)+) => {
        log::warn!("{}", paris::formatter::colorize_string(format!($($args)*)));
    };
}

/// Logs a message at the error level.
///
/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
/// contains special tags for controlling ANSI colors and styles
/// More info: https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html
///
/// # Examples
///
/// ```edition2018
/// use log::error;
///
/// # fn main() {
/// let (err_info, port) = ("No connection", 22);
///
/// error!("Error: {} on port {}", err_info, port);
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
/// # }
/// ```
#[macro_export]
macro_rules! error {
    ($($args:tt)+) => {
        log::error!("{}", paris::formatter::colorize_string(format!($($args)*)));
    };
}
<commit_msg>paris_macros: fix `this URL is not a hyperlink` warnings<commit_after>/// Logs a message at the info level.
///
/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
/// contains special tags for controlling ANSI colors and styles
/// More info: <https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html>
///
/// # Examples
///
/// ```edition2018
/// use log::info;
///
/// # fn main() {
/// # struct Connection { port: u32, speed: f32 }
/// let conn_info = Connection { port: 40, speed: 3.20 };
///
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
///       conn_info.port, conn_info.speed);
/// # }
/// ```
#[macro_export]
macro_rules! info {
    ($($args:tt)+) => {
        log::info!("{}", paris::formatter::colorize_string(format!($($args)*)));
    };
}

/// Logs a message at the debug level.
///
/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
/// contains special tags for controlling ANSI colors and styles
/// More info: <https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html>
///
/// # Examples
///
/// ```edition2018
/// use log::debug;
///
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
/// # }
/// ```
#[macro_export]
macro_rules! debug {
    ($($args:tt)+) => {
        log::debug!("{}", paris::formatter::colorize_string(format!($($args)*)));
    };
}

/// Logs a message at the trace level.
///
/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
/// contains special tags for controlling ANSI colors and styles
/// More info: <https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html>
///
/// # Examples
///
/// ```edition2018
/// use log::trace;
///
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
/// trace!(target: "app_events", "x is {} and y is {}",
///        if pos.x >= 0.0 { "positive" } else { "negative" },
///        if pos.y >= 0.0 { "positive" } else { "negative" });
/// # }
/// ```
#[macro_export]
macro_rules! trace {
    ($($args:tt)+) => {
        log::trace!("{}", paris::formatter::colorize_string(format!($($args)*)));
    };
}

/// Logs a message at the warn level.
///
/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
/// contains special tags for controlling ANSI colors and styles
/// More info: <https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html>
///
/// # Examples
///
/// ```edition2018
/// use log::warn;
///
/// # fn main() {
/// let warn_description = "Invalid Input";
///
/// warn!("Warning! {}!", warn_description);
/// warn!(target: "input_events", "App received warning: {}", warn_description);
/// # }
/// ```
#[macro_export]
macro_rules! warn {
    ($($args:tt)+) => {
        log::warn!("{}", paris::formatter::colorize_string(format!($($args)*)));
    };
}

/// Logs a message at the error level.
///
/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
/// contains special tags for controlling ANSI colors and styles
/// More info: <https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html>
///
/// # Examples
///
/// ```edition2018
/// use log::error;
///
/// # fn main() {
/// let (err_info, port) = ("No connection", 22);
///
/// error!("Error: {} on port {}", err_info, port);
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
/// # }
/// ```
#[macro_export]
macro_rules! error {
    ($($args:tt)+) => {
        log::error!("{}", paris::formatter::colorize_string(format!($($args)*)));
    };
}
<|endoftext|>