<commit_before>use crate::Graph;
use crate::Operation;
use crate::OperationDescription;
use crate::Result;
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::collections::HashSet;
use std::ops::Deref;
use std::ops::DerefMut;
use std::rc::Rc;

/// Joins left and right using the separator.  If either left or right is the
/// empty string, the separator is left out.
fn join(sep: &str, left: &str, right: &str) -> String {
    match (left, right) {
        ("", _) => right.to_string(),
        (_, "") => left.to_string(),
        _ => format!("{}{}{}", left, sep, right),
    }
}

// TODO: Include other with_* functions
/// A `Scope` object represents a set of related TensorFlow ops that have the
/// same properties such as a common name prefix.
///
/// A Scope object is a container for TensorFlow Op properties. Op constructors
/// get a Scope object as a mandatory first argument and the constructed op
/// acquires the properties in the object.
///
/// A simple example:
///
/// ```
/// # use tensorflow::Scope;
/// # use tensorflow::Tensor;
/// # use tensorflow::ops;
/// let mut root = Scope::new_root_scope();
/// let c1 = ops::constant(Tensor::new(&[1, 2]).with_values(&[1, 1])?, &mut root)?;
/// let c2 = ops::constant(Tensor::new(&[2, 1]).with_values(&[41, 1])?, &mut root)?;
/// let m = ops::mat_mul(c1, c2, &mut root)?;
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
///
/// # Scope hierarchy
///
/// The Scope class provides various `with_*` functions that create a new scope.
/// The new scope typically has one property changed while other properties are
/// inherited from the parent scope.
/// `new_sub_scope(name)` method appends `name` to the prefix of names for ops
/// created within the scope, and `with_op_name()` changes the suffix which
/// otherwise defaults to the type of the op.
///
/// Name examples:
///
/// ```
/// # use tensorflow::DataType;
/// # use tensorflow::Scope;
/// # use tensorflow::Shape;
/// # use tensorflow::Tensor;
/// # use tensorflow::Variable;
/// # use tensorflow::ops;
/// let mut root = Scope::new_root_scope();
/// let mut linear = root.new_sub_scope("linear");
/// let w = Variable::builder()
///   .const_initial_value(
///     Tensor::new(&[2, 2])
///       .with_values(&[0.0f32, 0.0, 0.0, 0.0])?)
///   .build(&mut linear.with_op_name("W"))?;
/// assert_eq!(w.name(), "linear/W");
/// let b = Variable::builder()
///   .const_initial_value(
///     Tensor::new(&[2])
///       .with_values(&[0.0f32, 0.0])?)
///   .build(&mut linear.with_op_name("b"))?;
/// assert_eq!(b.name(), "linear/b");
/// let x = ops::constant(
///   Tensor::new(&[2, 2])
///     .with_values(&[1.0f32, 2.0, 3.0, 4.0])?,
///    &mut linear)?;
/// assert_eq!(x.name()?, "linear/Const");
/// let m = ops::mat_mul(x, w.output().clone(), &mut linear)?;
/// assert_eq!(m.name()?, "linear/MatMul");
/// let r = ops::bias_add(m, b.output().clone(), &mut linear)?;
/// assert_eq!(r.name()?, "linear/BiasAdd");
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
///
/// # Scope lifetime
///
/// A new scope is created by calling `Scope::new_root_scope`. This creates some
/// resources that are shared by all the child scopes that inherit from this
/// scope, directly or transitively. For instance, a new scope creates a new
/// Graph object to which operations are added when the new scope or its
/// children are used by an Op constructor.
#[derive(Debug)]
pub struct Scope {
    graph: Rc<RefCell<Graph>>,
    name: String,
    children_names: Rc<RefCell<HashSet<String>>>,
    op_name: String,
    op_names: Rc<RefCell<HashMap<String, i32>>>,
    device: String,
    control_deps: Vec<Operation>,
    kernel_label: String,
}

impl Scope {
    /// Return a new scope.
    /// This creates a new graph and all operations constructed in this graph
    /// should use the returned object as the "root" scope.
    pub fn new_root_scope() -> Scope {
        Scope {
            graph: Rc::new(RefCell::new(Graph::new())),
            name: "".to_string(),
            children_names: Rc::new(RefCell::new(HashSet::new())),
            op_name: "".to_string(),
            op_names: Rc::new(RefCell::new(HashMap::new())),
            device: "".to_string(),
            control_deps: Vec::new(),
            kernel_label: "".to_string(),
        }
    }

    /// Adds a suffix if necessary to create a unique subscope name.
    fn uniquify(&self, name: &str) -> String {
        let refcell: &RefCell<_> = self.children_names.borrow();
        let mut set = refcell.borrow_mut();
        if set.insert(name.to_string()) {
            return name.to_string();
        }
        let mut i = 1;
        loop {
            let unique_name = format!("{}_{}", &name, i);
            if set.insert(unique_name.clone()) {
                return unique_name;
            }
            i += 1;
        }
    }

    /// Return a new scope. Ops created with this scope will have
    /// `name/child_scope_name` as the prefix. The actual name will be unique
    /// in the current scope. All other properties are inherited from the current
    /// scope. If `child_scope_name` is empty, the `/` is elided.
    pub fn new_sub_scope(&self, name: &str) -> Scope {
        let self_name: &str = &self.name;
        let (new_name, copy_names) = match (self_name, name) {
            (_, "") => (self.name.clone(), true),
            ("", _) => (self.uniquify(name), false),
            _ => (format!("{}/{}", self.name, self.uniquify(name)), false),
        };
        Scope {
            graph: self.graph.clone(),
            name: new_name,
            children_names: Rc::new(RefCell::new(HashSet::new())),
            op_name: self.op_name.clone(),
            op_names: if copy_names {
                self.op_names.clone()
            } else {
                Rc::new(RefCell::new(HashMap::new()))
            },
            device: self.device.clone(),
            control_deps: self.control_deps.clone(),
            kernel_label: "".to_string(),
        }
    }

    /// Return a new scope. All ops created within the returned scope will have
    /// names of the form `scope_name/name[_suffix]`
    pub fn with_op_name(&self, name: &str) -> Scope {
        Scope {
            graph: self.graph.clone(),
            name: self.name.clone(),
            children_names: self.children_names.clone(),
            op_name: name.to_string(),
            op_names: self.op_names.clone(),
            device: self.device.clone(),
            control_deps: self.control_deps.clone(),
            kernel_label: "".to_string(),
        }
    }

    /// Return a unique name, using default_name if an op name has not been
    /// specified.
    pub fn get_unique_name_for_op(&self, default_name: &str) -> String {
        let name = if self.op_name == "" {
            default_name
        } else {
            &self.op_name
        };
        let map: &RefCell<_> = self.op_names.borrow();
        let mut map = map.borrow_mut();
        let mut name_string = name.to_string();
        loop {
            match map.entry(name_string.clone()) {
                Entry::Vacant(e) => {
                    e.insert(0);
                    return join("/", &self.name, &name_string);
                }
                Entry::Occupied(mut e) => {
                    *e.get_mut() += 1;
                    name_string = format!("{}_{}", name, *e.get());
                }
            }
        }
    }

    /// Return a new scope. All ops created within the returned scope will have
    /// their device field set to `device`.
    pub fn with_device(&self, device: &str) -> Scope {
        Scope {
            graph: self.graph.clone(),
            name: self.name.clone(),
            children_names: self.children_names.clone(),
            op_name: self.op_name.clone(),
            op_names: self.op_names.clone(),
            device: device.to_string(),
            control_deps: self.control_deps.clone(),
            kernel_label: "".to_string(),
        }
    }

    /// Return a new scope. All ops created within the returned scope will have
    /// as control dependencies the union of operations in `control_deps`
    /// and the control dependencies of the current scope.
    pub fn with_control_dependencies(&self, control_deps: &[Operation]) -> Scope {
        Scope {
            graph: self.graph.clone(),
            name: self.name.clone(),
            children_names: self.children_names.clone(),
            op_name: self.op_name.clone(),
            op_names: self.op_names.clone(),
            device: self.device.clone(),
            control_deps: self
                .control_deps
                .iter()
                .chain(control_deps.iter())
                .cloned()
                .collect(),
            kernel_label: "".to_string(),
        }
    }

    /// Return a new scope. All ops created within the returned scope will have
    /// no control dependencies on other operations.
    pub fn with_no_control_dependencies(&self) -> Scope {
        Scope {
            graph: self.graph.clone(),
            name: self.name.clone(),
            children_names: self.children_names.clone(),
            op_name: self.op_name.clone(),
            op_names: self.op_names.clone(),
            device: self.device.clone(),
            control_deps: vec![],
            kernel_label: "".to_string(),
        }
    }

    /// Return a new scope. All ops created with the new scope will have
    /// kernel_label as the value for their '_kernel' attribute.
    pub fn with_kernel_label(&self, kernel_label: &str) -> Scope {
        Scope {
            graph: self.graph.clone(),
            name: self.name.clone(),
            children_names: self.children_names.clone(),
            op_name: self.op_name.clone(),
            op_names: self.op_names.clone(),
            device: self.device.clone(),
            control_deps: self.control_deps.clone(),
            kernel_label: kernel_label.to_string(),
        }
    }

    pub(crate) fn new_operation<F: FnOnce(&mut OperationDescription) -> Result<()>>(
        &mut self,
        op_type: &str,
        f: F,
    ) -> Result<Operation> {
        let name = self.get_unique_name_for_op(op_type);
        let r: &RefCell<Graph> = self.graph.borrow();
        let mut graph = r.borrow_mut();
        let mut nd = graph.new_operation(op_type, &name)?;
        nd.set_device(&self.device)?;
        for control_dep in &self.control_deps {
            nd.add_control_input(control_dep);
        }
        if !self.kernel_label.is_empty() {
            nd.set_attr_string("_kernel", &self.kernel_label)?;
        }
        f(&mut nd)?;
        Ok(nd.finish()?)
    }

    /// Returns the graph being built by the scope.
    pub fn graph(&self) -> impl Deref<Target = Graph> + '_ {
        let r: &RefCell<Graph> = self.graph.borrow();
        r.borrow()
    }

    /// Returns the graph being built by the scope.
    pub fn graph_mut(&mut self) -> impl DerefMut<Target = Graph> + '_ {
        let r: &RefCell<Graph> = self.graph.borrow();
        r.borrow_mut()
    }
}

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

    #[test]
    fn smoke() {
        let mut scope = Scope::new_root_scope();
        let mut graph = scope.graph_mut();
        let mut c = graph.new_operation("Const", "Const").unwrap();
        c.set_attr_tensor("value", 3.0f32.into()).unwrap();
        c.set_attr_type("dtype", DataType::Float).unwrap();
        c.finish().unwrap();
    }

    #[test]
    fn uniquification() {
        let scope = Scope::new_root_scope();
        assert_eq!(&scope.new_sub_scope("foo").name, "foo");
        assert_eq!(&scope.new_sub_scope("foo").name, "foo_1");
        let foo_1 = scope.new_sub_scope("foo");
        assert_eq!(&foo_1.name, "foo_2");
        assert_eq!(&foo_1.new_sub_scope("bar").name, "foo_2/bar");
        assert_eq!(&foo_1.new_sub_scope("bar").name, "foo_2/bar_1");
        assert_eq!(&foo_1.new_sub_scope("bar").name, "foo_2/bar_2");
    }

    #[test]
    fn get_unique_name_for_op() {
        let scope = Scope::new_root_scope();
        assert_eq!(scope.get_unique_name_for_op("Add"), "Add");
        assert_eq!(scope.get_unique_name_for_op("Add"), "Add_1");
        let foo = scope.new_sub_scope("foo");
        assert_eq!(foo.get_unique_name_for_op("Add"), "foo/Add");
        assert_eq!(foo.get_unique_name_for_op("Add"), "foo/Add_1");
        let bar = foo.with_op_name("bar");
        assert_eq!(bar.get_unique_name_for_op("Add"), "foo/bar");
        assert_eq!(bar.get_unique_name_for_op("Add"), "foo/bar_1");
    }

    #[test]
    fn device() {
        assert_eq!(
            Scope::new_root_scope()
                .with_device("foo")
                .new_operation("NoOp", |_| Ok(()))
                .unwrap()
                .device()
                .unwrap(),
            "foo"
        );
    }

    #[test]
    fn kernel_label() {
        assert_eq!(
            Scope::new_root_scope()
                .with_kernel_label("foo")
                .new_operation("NoOp", |_| Ok(()))
                .unwrap()
                .get_attr_string("_kernel")
                .unwrap(),
            "foo"
        );
    }

    #[test]
    fn control_dependencies() {
        let mut scope = Scope::new_root_scope();
        let dep = scope.new_operation("NoOp", |_| Ok(())).unwrap();
        let dep_clone = dep.clone();
        let mut scope2 = scope.with_control_dependencies(&[dep]);
        assert_eq!(
            scope2
                .new_operation("NoOp", |_| Ok(()))
                .unwrap()
                .control_inputs()
                .iter()
                .map(|n| n.name().unwrap())
                .collect::<Vec<_>>(),
            vec![dep_clone.name().unwrap()]
        );
        let mut scope3 = scope2.with_no_control_dependencies();
        assert_eq!(
            scope3
                .new_operation("NoOp", |_| Ok(()))
                .unwrap()
                .control_inputs()
                .len(),
            0
        );
    }
}
<commit_msg>Fix kernel_label in other withs<commit_after>use crate::Graph;
use crate::Operation;
use crate::OperationDescription;
use crate::Result;
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::collections::HashSet;
use std::ops::Deref;
use std::ops::DerefMut;
use std::rc::Rc;

/// Joins left and right using the separator.  If either left or right is the
/// empty string, the separator is left out.
fn join(sep: &str, left: &str, right: &str) -> String {
    match (left, right) {
        ("", _) => right.to_string(),
        (_, "") => left.to_string(),
        _ => format!("{}{}{}", left, sep, right),
    }
}

// TODO: Include other with_* functions
/// A `Scope` object represents a set of related TensorFlow ops that have the
/// same properties such as a common name prefix.
///
/// A Scope object is a container for TensorFlow Op properties. Op constructors
/// get a Scope object as a mandatory first argument and the constructed op
/// acquires the properties in the object.
///
/// A simple example:
///
/// ```
/// # use tensorflow::Scope;
/// # use tensorflow::Tensor;
/// # use tensorflow::ops;
/// let mut root = Scope::new_root_scope();
/// let c1 = ops::constant(Tensor::new(&[1, 2]).with_values(&[1, 1])?, &mut root)?;
/// let c2 = ops::constant(Tensor::new(&[2, 1]).with_values(&[41, 1])?, &mut root)?;
/// let m = ops::mat_mul(c1, c2, &mut root)?;
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
///
/// # Scope hierarchy
///
/// The Scope class provides various `with_*` functions that create a new scope.
/// The new scope typically has one property changed while other properties are
/// inherited from the parent scope.
/// `new_sub_scope(name)` method appends `name` to the prefix of names for ops
/// created within the scope, and `with_op_name()` changes the suffix which
/// otherwise defaults to the type of the op.
///
/// Name examples:
///
/// ```
/// # use tensorflow::DataType;
/// # use tensorflow::Scope;
/// # use tensorflow::Shape;
/// # use tensorflow::Tensor;
/// # use tensorflow::Variable;
/// # use tensorflow::ops;
/// let mut root = Scope::new_root_scope();
/// let mut linear = root.new_sub_scope("linear");
/// let w = Variable::builder()
///   .const_initial_value(
///     Tensor::new(&[2, 2])
///       .with_values(&[0.0f32, 0.0, 0.0, 0.0])?)
///   .build(&mut linear.with_op_name("W"))?;
/// assert_eq!(w.name(), "linear/W");
/// let b = Variable::builder()
///   .const_initial_value(
///     Tensor::new(&[2])
///       .with_values(&[0.0f32, 0.0])?)
///   .build(&mut linear.with_op_name("b"))?;
/// assert_eq!(b.name(), "linear/b");
/// let x = ops::constant(
///   Tensor::new(&[2, 2])
///     .with_values(&[1.0f32, 2.0, 3.0, 4.0])?,
///    &mut linear)?;
/// assert_eq!(x.name()?, "linear/Const");
/// let m = ops::mat_mul(x, w.output().clone(), &mut linear)?;
/// assert_eq!(m.name()?, "linear/MatMul");
/// let r = ops::bias_add(m, b.output().clone(), &mut linear)?;
/// assert_eq!(r.name()?, "linear/BiasAdd");
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
///
/// # Scope lifetime
///
/// A new scope is created by calling `Scope::new_root_scope`. This creates some
/// resources that are shared by all the child scopes that inherit from this
/// scope, directly or transitively. For instance, a new scope creates a new
/// Graph object to which operations are added when the new scope or its
/// children are used by an Op constructor.
#[derive(Debug)]
pub struct Scope {
    graph: Rc<RefCell<Graph>>,
    name: String,
    children_names: Rc<RefCell<HashSet<String>>>,
    op_name: String,
    op_names: Rc<RefCell<HashMap<String, i32>>>,
    device: String,
    control_deps: Vec<Operation>,
    kernel_label: String,
}

impl Scope {
    /// Return a new scope.
    /// This creates a new graph and all operations constructed in this graph
    /// should use the returned object as the "root" scope.
    pub fn new_root_scope() -> Scope {
        Scope {
            graph: Rc::new(RefCell::new(Graph::new())),
            name: "".to_string(),
            children_names: Rc::new(RefCell::new(HashSet::new())),
            op_name: "".to_string(),
            op_names: Rc::new(RefCell::new(HashMap::new())),
            device: "".to_string(),
            control_deps: Vec::new(),
            kernel_label: "".to_string(),
        }
    }

    /// Adds a suffix if necessary to create a unique subscope name.
    fn uniquify(&self, name: &str) -> String {
        let refcell: &RefCell<_> = self.children_names.borrow();
        let mut set = refcell.borrow_mut();
        if set.insert(name.to_string()) {
            return name.to_string();
        }
        let mut i = 1;
        loop {
            let unique_name = format!("{}_{}", &name, i);
            if set.insert(unique_name.clone()) {
                return unique_name;
            }
            i += 1;
        }
    }

    /// Return a new scope. Ops created with this scope will have
    /// `name/child_scope_name` as the prefix. The actual name will be unique
    /// in the current scope. All other properties are inherited from the current
    /// scope. If `child_scope_name` is empty, the `/` is elided.
    pub fn new_sub_scope(&self, name: &str) -> Scope {
        let self_name: &str = &self.name;
        let (new_name, copy_names) = match (self_name, name) {
            (_, "") => (self.name.clone(), true),
            ("", _) => (self.uniquify(name), false),
            _ => (format!("{}/{}", self.name, self.uniquify(name)), false),
        };
        Scope {
            graph: self.graph.clone(),
            name: new_name,
            children_names: Rc::new(RefCell::new(HashSet::new())),
            op_name: self.op_name.clone(),
            op_names: if copy_names {
                self.op_names.clone()
            } else {
                Rc::new(RefCell::new(HashMap::new()))
            },
            device: self.device.clone(),
            control_deps: self.control_deps.clone(),
            kernel_label: self.kernel_label.clone(),
        }
    }

    /// Return a new scope. All ops created within the returned scope will have
    /// names of the form `scope_name/name[_suffix]`
    pub fn with_op_name(&self, name: &str) -> Scope {
        Scope {
            graph: self.graph.clone(),
            name: self.name.clone(),
            children_names: self.children_names.clone(),
            op_name: name.to_string(),
            op_names: self.op_names.clone(),
            device: self.device.clone(),
            control_deps: self.control_deps.clone(),
            kernel_label: self.kernel_label.clone(),
        }
    }

    /// Return a unique name, using default_name if an op name has not been
    /// specified.
    pub fn get_unique_name_for_op(&self, default_name: &str) -> String {
        let name = if self.op_name == "" {
            default_name
        } else {
            &self.op_name
        };
        let map: &RefCell<_> = self.op_names.borrow();
        let mut map = map.borrow_mut();
        let mut name_string = name.to_string();
        loop {
            match map.entry(name_string.clone()) {
                Entry::Vacant(e) => {
                    e.insert(0);
                    return join("/", &self.name, &name_string);
                }
                Entry::Occupied(mut e) => {
                    *e.get_mut() += 1;
                    name_string = format!("{}_{}", name, *e.get());
                }
            }
        }
    }

    /// Return a new scope. All ops created within the returned scope will have
    /// their device field set to `device`.
    pub fn with_device(&self, device: &str) -> Scope {
        Scope {
            graph: self.graph.clone(),
            name: self.name.clone(),
            children_names: self.children_names.clone(),
            op_name: self.op_name.clone(),
            op_names: self.op_names.clone(),
            device: device.to_string(),
            control_deps: self.control_deps.clone(),
            kernel_label: self.kernel_label.clone(),
        }
    }

    /// Return a new scope. All ops created within the returned scope will have
    /// as control dependencies the union of operations in `control_deps`
    /// and the control dependencies of the current scope.
    pub fn with_control_dependencies(&self, control_deps: &[Operation]) -> Scope {
        Scope {
            graph: self.graph.clone(),
            name: self.name.clone(),
            children_names: self.children_names.clone(),
            op_name: self.op_name.clone(),
            op_names: self.op_names.clone(),
            device: self.device.clone(),
            control_deps: self
                .control_deps
                .iter()
                .chain(control_deps.iter())
                .cloned()
                .collect(),
            kernel_label: self.kernel_label.clone(),
        }
    }

    /// Return a new scope. All ops created within the returned scope will have
    /// no control dependencies on other operations.
    pub fn with_no_control_dependencies(&self) -> Scope {
        Scope {
            graph: self.graph.clone(),
            name: self.name.clone(),
            children_names: self.children_names.clone(),
            op_name: self.op_name.clone(),
            op_names: self.op_names.clone(),
            device: self.device.clone(),
            control_deps: vec![],
            kernel_label: self.kernel_label.clone(),
        }
    }

    /// Return a new scope. All ops created with the new scope will have
    /// kernel_label as the value for their '_kernel' attribute.
    pub fn with_kernel_label(&self, kernel_label: &str) -> Scope {
        Scope {
            graph: self.graph.clone(),
            name: self.name.clone(),
            children_names: self.children_names.clone(),
            op_name: self.op_name.clone(),
            op_names: self.op_names.clone(),
            device: self.device.clone(),
            control_deps: self.control_deps.clone(),
            kernel_label: kernel_label.to_string(),
        }
    }

    pub(crate) fn new_operation<F: FnOnce(&mut OperationDescription) -> Result<()>>(
        &mut self,
        op_type: &str,
        f: F,
    ) -> Result<Operation> {
        let name = self.get_unique_name_for_op(op_type);
        let r: &RefCell<Graph> = self.graph.borrow();
        let mut graph = r.borrow_mut();
        let mut nd = graph.new_operation(op_type, &name)?;
        nd.set_device(&self.device)?;
        for control_dep in &self.control_deps {
            nd.add_control_input(control_dep);
        }
        if !self.kernel_label.is_empty() {
            nd.set_attr_string("_kernel", &self.kernel_label)?;
        }
        f(&mut nd)?;
        Ok(nd.finish()?)
    }

    /// Returns the graph being built by the scope.
    pub fn graph(&self) -> impl Deref<Target = Graph> + '_ {
        let r: &RefCell<Graph> = self.graph.borrow();
        r.borrow()
    }

    /// Returns the graph being built by the scope.
    pub fn graph_mut(&mut self) -> impl DerefMut<Target = Graph> + '_ {
        let r: &RefCell<Graph> = self.graph.borrow();
        r.borrow_mut()
    }
}

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

    #[test]
    fn smoke() {
        let mut scope = Scope::new_root_scope();
        let mut graph = scope.graph_mut();
        let mut c = graph.new_operation("Const", "Const").unwrap();
        c.set_attr_tensor("value", 3.0f32.into()).unwrap();
        c.set_attr_type("dtype", DataType::Float).unwrap();
        c.finish().unwrap();
    }

    #[test]
    fn uniquification() {
        let scope = Scope::new_root_scope();
        assert_eq!(&scope.new_sub_scope("foo").name, "foo");
        assert_eq!(&scope.new_sub_scope("foo").name, "foo_1");
        let foo_1 = scope.new_sub_scope("foo");
        assert_eq!(&foo_1.name, "foo_2");
        assert_eq!(&foo_1.new_sub_scope("bar").name, "foo_2/bar");
        assert_eq!(&foo_1.new_sub_scope("bar").name, "foo_2/bar_1");
        assert_eq!(&foo_1.new_sub_scope("bar").name, "foo_2/bar_2");
    }

    #[test]
    fn get_unique_name_for_op() {
        let scope = Scope::new_root_scope();
        assert_eq!(scope.get_unique_name_for_op("Add"), "Add");
        assert_eq!(scope.get_unique_name_for_op("Add"), "Add_1");
        let foo = scope.new_sub_scope("foo");
        assert_eq!(foo.get_unique_name_for_op("Add"), "foo/Add");
        assert_eq!(foo.get_unique_name_for_op("Add"), "foo/Add_1");
        let bar = foo.with_op_name("bar");
        assert_eq!(bar.get_unique_name_for_op("Add"), "foo/bar");
        assert_eq!(bar.get_unique_name_for_op("Add"), "foo/bar_1");
    }

    #[test]
    fn device() {
        assert_eq!(
            Scope::new_root_scope()
                .with_device("foo")
                .new_operation("NoOp", |_| Ok(()))
                .unwrap()
                .device()
                .unwrap(),
            "foo"
        );
    }

    #[test]
    fn kernel_label() {
        assert_eq!(
            Scope::new_root_scope()
                .with_kernel_label("foo")
                .new_operation("NoOp", |_| Ok(()))
                .unwrap()
                .get_attr_string("_kernel")
                .unwrap(),
            "foo"
        );
    }

    #[test]
    fn control_dependencies() {
        let mut scope = Scope::new_root_scope();
        let dep = scope.new_operation("NoOp", |_| Ok(())).unwrap();
        let dep_clone = dep.clone();
        let mut scope2 = scope.with_control_dependencies(&[dep]);
        assert_eq!(
            scope2
                .new_operation("NoOp", |_| Ok(()))
                .unwrap()
                .control_inputs()
                .iter()
                .map(|n| n.name().unwrap())
                .collect::<Vec<_>>(),
            vec![dep_clone.name().unwrap()]
        );
        let mut scope3 = scope2.with_no_control_dependencies();
        assert_eq!(
            scope3
                .new_operation("NoOp", |_| Ok(()))
                .unwrap()
                .control_inputs()
                .len(),
            0
        );
    }
}
<|endoftext|>


<commit_before>use slack_hook::{Attachment, AttachmentBuilder, PayloadBuilder, Slack, SlackLink};
use slack_hook::SlackTextContent::{Text, Link};

use taste::TastingResult;

pub struct SlackNotifier {
    conn: Slack,
    channel: String,
    github_repo: String,
}

impl SlackNotifier {
    pub fn new(hook_url: &str, channel: &str, repo_url: &str) -> SlackNotifier {
        SlackNotifier {
            conn: Slack::new(hook_url).unwrap(),
            channel: String::from(channel),
            github_repo: String::from(repo_url),
        }
    }

    pub fn notify(&self, res: TastingResult) -> Result<(), String> {
        let payload = PayloadBuilder::new()
            .text(vec![Text("I've tasted ".into()),
                       Link(SlackLink::new(&format!("{}/commit/{}",
                                                    self.github_repo,
                                                    res.commit_id),
                                           &res.commit_id)),
                       Text("and liked it:".into())]
                .as_slice())
            .attachments(vec![result_to_attachment(&res)])
            .channel(self.channel.clone())
            .username("taster")
            .icon_emoji(":tea:")
            .build()
            .unwrap();

        match self.conn.send(&payload) {
            Ok(_) => Ok(()),
            Err(e) => Err(format!("{:?}", e)),
        }
    }
}

fn result_to_attachment(res: &TastingResult) -> Attachment {
    let color = if !res.build || !res.bench {
        "danger"
    } else {
        "good"
    };

    let title = if !res.build {
        "Build failure!"
    } else if !res.bench {
        "Benchmark failure!"
    } else {
        "Performance results:"
    };

    AttachmentBuilder::new("It tasted nice.")
        .color(color)
        .title(title)
        .build()
        .unwrap()
}
<commit_msg>Express a taste<commit_after>use slack_hook::{Attachment, AttachmentBuilder, PayloadBuilder, Slack, SlackLink};
use slack_hook::SlackTextContent::{Text, Link};

use taste::TastingResult;

pub struct SlackNotifier {
    conn: Slack,
    channel: String,
    github_repo: String,
}

impl SlackNotifier {
    pub fn new(hook_url: &str, channel: &str, repo_url: &str) -> SlackNotifier {
        SlackNotifier {
            conn: Slack::new(hook_url).unwrap(),
            channel: String::from(channel),
            github_repo: String::from(repo_url),
        }
    }

    pub fn notify(&self, res: TastingResult) -> Result<(), String> {
        let payload = PayloadBuilder::new()
            .text(vec![Text("I've tasted ".into()),
                       Link(SlackLink::new(&format!("{}/commit/{}",
                                                    self.github_repo,
                                                    res.commit_id),
                                           &res.commit_id)),
                       Text("and liked it:".into())]
                .as_slice())
            .attachments(vec![result_to_attachment(&res)])
            .channel(self.channel.clone())
            .username("taster")
            .icon_emoji(":tea:")
            .build()
            .unwrap();

        match self.conn.send(&payload) {
            Ok(_) => Ok(()),
            Err(e) => Err(format!("{:?}", e)),
        }
    }
}

fn result_to_attachment(res: &TastingResult) -> Attachment {
    let color = if !res.build || !res.bench {
        "danger"
    } else {
        "good"
    };

    let title = if !res.build {
        "Build failure!"
    } else if !res.bench {
        "Benchmark failure!"
    } else {
        "Performance results:"
    };

    let taste = if !res.build || !res.bench {
        "was inedible"
    } else {
        "tasted nice"
    };

    AttachmentBuilder::new(format!("It {}.", taste))
        .color(color)
        .title(title)
        .build()
        .unwrap()
}
<|endoftext|>


<commit_before>
use color::Color;
use serialize::{
    json,
    Encodable,
    Decodable
};
use std::io::File;
use std::str;
use ui_context::UiContext;

/// A data holder for style-related data.
#[deriving(Show, Clone, Encodable, Decodable)]
pub struct Theme {
    pub name: String,
    pub background_color: Color,
    pub shape_color: Color,
    pub frame_color: Color,
    pub frame_width: f64,
    pub label_color: Color,
    pub font_size_large: u32,
    pub font_size_medium: u32,
    pub font_size_small: u32,
    //TODO: Add unique theme-ing for each widget.
    //i.e. maybe_slider: Option<SliderTheme>, etc
}

impl Theme {

    /// The default theme if not loading from file.
    pub fn default() -> Theme {
        Theme {
            name: "Demo Theme".to_string(),
            background_color: Color::new(0.0, 0.0, 0.0, 1.0),
            shape_color: Color::new(1.0, 1.0, 1.0, 1.0),
            frame_color: Color::new(0.0, 0.0, 0.0, 1.0),
            frame_width: 1.0,
            label_color: Color::new(0.0, 0.0, 0.0, 1.0),
            font_size_large: 32,
            font_size_medium: 24,
            font_size_small: 18,
        }
    }

    /// Load a theme from file.
    pub fn load(path: &str) -> Theme {
        let contents = match File::open(&Path::new(path)).read_to_end() {
            Ok(buf) => buf,
            Err(e) => panic!("Failed to load Theme correctly: {}", e),
        };
        let contents_str = match str::from_utf8(contents.as_slice()) {
            Some(string) => string,
            None => panic!("Failed to load Theme!"),
        };
        let json_object = json::from_str(contents_str);
        let mut decoder = json::Decoder::new(json_object.unwrap());
        let theme: Theme = match Decodable::decode(&mut decoder) {
            Ok(lib) => lib,
            Err(e) => panic!("Failed to load Theme correctly: {}", e),
        };
        theme
    }

    /// Save a theme to file.
    pub fn save(&self, path: &str) {
        let json_string = json::Encoder::buffer_encode(self);
        let mut file = File::create(&Path::new(path));
        match file.write(json_string.as_slice()) {
            Ok(()) => (),
            Err(e) => panic!("Theme failed to save correctly: {}", e),
        }
    }

}

/// A trait to make it easier to generically access the UIC on different widget contexts.
pub trait Themeable {
    /// Return a reference to the UiContext.
    fn get_theme(&self) -> &UiContext;
    /// Return a reference to the UiContext.
    fn get_theme_mut(&mut self) -> &mut UiContext;
}

<commit_msg>Theme.save returns a Result now, fixes #142<commit_after>
use color::Color;
use serialize::{
    json,
    Encodable,
    Decodable
};
use std::io::File;
use std::str;
use ui_context::UiContext;

/// A data holder for style-related data.
#[deriving(Show, Clone, Encodable, Decodable)]
pub struct Theme {
    pub name: String,
    pub background_color: Color,
    pub shape_color: Color,
    pub frame_color: Color,
    pub frame_width: f64,
    pub label_color: Color,
    pub font_size_large: u32,
    pub font_size_medium: u32,
    pub font_size_small: u32,
    //TODO: Add unique theme-ing for each widget.
    //i.e. maybe_slider: Option<SliderTheme>, etc
}

impl Theme {

    /// The default theme if not loading from file.
    pub fn default() -> Theme {
        Theme {
            name: "Demo Theme".to_string(),
            background_color: Color::new(0.0, 0.0, 0.0, 1.0),
            shape_color: Color::new(1.0, 1.0, 1.0, 1.0),
            frame_color: Color::new(0.0, 0.0, 0.0, 1.0),
            frame_width: 1.0,
            label_color: Color::new(0.0, 0.0, 0.0, 1.0),
            font_size_large: 32,
            font_size_medium: 24,
            font_size_small: 18,
        }
    }

    /// Load a theme from file.
    pub fn load(path: &str) -> Theme {
        let contents = match File::open(&Path::new(path)).read_to_end() {
            Ok(buf) => buf,
            Err(e) => panic!("Failed to load Theme correctly: {}", e),
        };
        let contents_str = match str::from_utf8(contents.as_slice()) {
            Some(string) => string,
            None => panic!("Failed to load Theme!"),
        };
        let json_object = json::from_str(contents_str);
        let mut decoder = json::Decoder::new(json_object.unwrap());
        let theme: Theme = match Decodable::decode(&mut decoder) {
            Ok(lib) => lib,
            Err(e) => panic!("Failed to load Theme correctly: {}", e),
        };
        theme
    }

    /// Save a theme to file.
    pub fn save(&self, path: &str) -> Result<(), String> {
        let json_string = json::Encoder::buffer_encode(self);
        let mut file = File::create(&Path::new(path));
        match file.write(json_string.as_slice()) {
            Ok(()) => Ok(()),
            Err(e) => Err(format!("Theme failed to save correctly: {}", e)),
        }
    }

}

/// A trait to make it easier to generically access the UIC on different widget contexts.
pub trait Themeable {
    /// Return a reference to the UiContext.
    fn get_theme(&self) -> &UiContext;
    /// Return a reference to the UiContext.
    fn get_theme_mut(&mut self) -> &mut UiContext;
}

<|endoftext|>


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

//! Various types used throughout the server crate

use std::sync::{Arc, Mutex};
use std::collections::LinkedList;

use socket::Socket;

pub trait EventHandler {
    fn on_data_received(&self, sender: Socket, sockets: SocketList, buffer: Vec<u8>);
    fn on_socket_closed(&self, id: u32);
}

/// Thread LinkedList<Socket>
pub type SocketList = Arc<Mutex<LinkedList<Socket>>>;

/// Thread safe EventHandler
pub type SafeHandler = Arc<Mutex<EventHandler + Send + Sync + 'static>>;

/// FnOnce signature for EventHandler on_data_received fn
pub type EventHandlerFn = Arc<Mutex<(FnMut() + Send + Sync + 'static)>>;
<commit_msg>EventHandler changed to gain mutable reference to self<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

//! Various types used throughout the server crate

use std::sync::{Arc, Mutex};
use std::collections::LinkedList;

use socket::Socket;

pub trait EventHandler {
    fn on_data_received(&mut self, sender: Socket, sockets: SocketList, buffer: Vec<u8>);
    fn on_socket_closed(&mut self, id: u32);
}

/// Thread LinkedList<Socket>
pub type SocketList = Arc<Mutex<LinkedList<Socket>>>;

/// Thread safe EventHandler
pub type SafeHandler = Arc<Mutex<EventHandler + Send + Sync + 'static>>;

/// FnOnce signature for EventHandler on_data_received fn
pub type EventHandlerFn = Arc<Mutex<(FnMut() + Send + Sync + 'static)>>;
<|endoftext|>


<commit_before>//! Types for Gerber code generation.
//!
//! All types are stateless, meaning that they contain all information in order
//! to render themselves. This means for example that each `Coordinates`
//! instance contains a reference to the coordinate format to be used.

use std::convert::{From, Into};

use ::{CoordinateFormat, CoordinateNumber};

/// Coordinates are part of an operation.
///
/// Coordinates are modal. If an X is omitted, the X coordinate of the
/// current point is used. Similar for Y.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Coordinates {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl Coordinates {
    pub fn new<T, U>(x: T, y: U, format: CoordinateFormat) -> Self
            where T: Into<CoordinateNumber>, U: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: None, y: Some(y.into()), format: format }
    }
}

/// Coordinate offsets can be used for interpolate operations in circular
/// interpolation mode.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CoordinateOffset {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl CoordinateOffset {
    pub fn new<T, U>(x: T, y: U, format: CoordinateFormat) -> Self
            where T: Into<CoordinateNumber>, U: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: None, y: Some(y.into()), format: format }
    }
}

// Root type

#[derive(Debug, Clone, PartialEq)]
pub enum Command {
    FunctionCode(FunctionCode),
    ExtendedCode(ExtendedCode),
}

impl From<FunctionCode> for Command {
    fn from(val: FunctionCode) -> Self {
        Command::FunctionCode(val)
    }
}

impl From<ExtendedCode> for Command {
    fn from(val: ExtendedCode) -> Self {
        Command::ExtendedCode(val)
    }
}

// Main categories

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FunctionCode {
    DCode(DCode),
    GCode(GCode),
    MCode(MCode),
}

#[derive(Debug, Clone, PartialEq)]
pub enum ExtendedCode {
    /// FS
    CoordinateFormat(CoordinateFormat),
    /// MO
    Unit(Unit),
    /// AD
    ApertureDefinition(ApertureDefinition),
    /// AM
    ApertureMacro(::macros::ApertureMacro),
    /// LP
    LoadPolarity(Polarity),
    /// SR
    StepAndRepeat(StepAndRepeat),
    /// TF
    FileAttribute(::attributes::FileAttribute),
    /// TA
    ApertureAttribute(::attributes::ApertureAttribute),
    /// TD
    DeleteAttribute(String),
}

// Function codes

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DCode {
    Operation(Operation),
    SelectAperture(i32),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GCode {
    InterpolationMode(InterpolationMode),
    RegionMode(bool),
    QuadrantMode(QuadrantMode),
    Comment(String),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MCode {
    EndOfFile,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operation {
    /// D01 Command
    Interpolate(Coordinates, Option<CoordinateOffset>),
    /// D02 Command
    Move(Coordinates),
    /// D03 Command
    Flash(Coordinates),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InterpolationMode {
    Linear,
    ClockwiseCircular,
    CounterclockwiseCircular,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum QuadrantMode {
    Single,
    Multi,
}

// Extended codes

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Unit {
    Inches,
    Millimeters,
}

#[derive(Debug, Clone, PartialEq)]
pub struct ApertureDefinition {
    pub code: i32,
    pub aperture: Aperture,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Aperture {
    Circle(Circle),
    Rectangle(Rectangular),
    Obround(Rectangular),
    Polygon(Polygon),
    Other(String),
}

#[derive(Debug, Clone, PartialEq)]
pub struct Circle {
    pub diameter: f64,
    pub hole_diameter: Option<f64>,
}

impl Circle {
    pub fn new(diameter: f64) -> Self {
        Circle {
            diameter: diameter,
            hole_diameter: None,
        }
    }

    pub fn with_hole(diameter: f64, hole_diameter: f64) -> Self {
        Circle {
            diameter: diameter,
            hole_diameter: Some(hole_diameter),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Rectangular {
    pub x: f64,
    pub y: f64,
    pub hole_diameter: Option<f64>,
}

impl Rectangular {
    pub fn new(x: f64, y: f64) -> Self {
        Rectangular {
            x: x,
            y: y,
            hole_diameter: None,
        }
    }

    pub fn with_hole(x: f64, y: f64, hole_diameter: f64) -> Self {
        Rectangular {
            x: x,
            y: y,
            hole_diameter: Some(hole_diameter),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Polygon {
    pub diameter: f64,
    pub vertices: u8, // 3--12
    pub rotation: Option<f64>,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Polarity {
    Clear,
    Dark,
}

#[derive(Debug, Clone, PartialEq)]
pub enum StepAndRepeat {
    Open { repeat_x: u32, repeat_y: u32, distance_x: f64, distance_y: f64 },
    Close,
}

#[cfg(test)]
mod test {
    extern crate conv;

    use ::{CoordinateNumber, CoordinateFormat};
    use super::*;

    #[test]
    fn test_debug() {
        //! The debug representation should work properly.
        let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment("test".to_string())));
        let debug = format!("{:?}", c);
        assert_eq!(debug, "FunctionCode(GCode(Comment(\"test\")))");
    }

    #[test]
    fn test_coordinates_into() {
        let cf = CoordinateFormat::new(2, 4);
        let c1 = Coordinates::new(CoordinateNumber::from(1), CoordinateNumber::from(2), cf);
        let c2 = Coordinates::new(1, 2, cf);
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_coordinates_into_mixed() {
        let cf = CoordinateFormat::new(2, 4);
        let c1 = Coordinates::new(CoordinateNumber::from(1), 2, cf);
        let c2 = Coordinates::new(1, 2, cf);
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_circle_new() {
        let c1 = Circle::new(3.0);
        let c2 = Circle { diameter: 3.0, hole_diameter: None };
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_circle_with_hole() {
        let c1 = Circle::with_hole(3.0, 1.0);
        let c2 = Circle { diameter: 3.0, hole_diameter: Some(1.0) };
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_rectangular_new() {
        let r1 = Rectangular::new(2.0, 3.0);
        let r2 = Rectangular { x: 2.0, y: 3.0, hole_diameter: None };
        assert_eq!(r1, r2);
    }

    #[test]
    fn test_rectangular_with_hole() {
        let r1 = Rectangular::with_hole(3.0, 2.0, 1.0);
        let r2 = Rectangular { x: 3.0, y: 2.0, hole_diameter: Some(1.0) };
        assert_eq!(r1, r2);
    }

    #[test]
    fn test_command_from_function_code() {
        let comment = FunctionCode::GCode(GCode::Comment("hello".into()));
        let c1: Command = Command::FunctionCode(comment.clone());
        let c2: Command = comment.into();
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_command_from_extended_code() {
        let delete_attr = ExtendedCode::DeleteAttribute("hello".into());
        let c1: Command = Command::ExtendedCode(delete_attr.clone());
        let c2: Command = delete_attr.into();
        assert_eq!(c1, c2);
    }

}
<commit_msg>Impl From<> for Command, FunctionCode and ExtendedCode<commit_after>//! Types for Gerber code generation.
//!
//! All types are stateless, meaning that they contain all information in order
//! to render themselves. This means for example that each `Coordinates`
//! instance contains a reference to the coordinate format to be used.

use std::convert::{From, Into};

use ::{CoordinateFormat, CoordinateNumber};

/// Coordinates are part of an operation.
///
/// Coordinates are modal. If an X is omitted, the X coordinate of the
/// current point is used. Similar for Y.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Coordinates {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl Coordinates {
    pub fn new<T, U>(x: T, y: U, format: CoordinateFormat) -> Self
            where T: Into<CoordinateNumber>, U: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        Coordinates { x: None, y: Some(y.into()), format: format }
    }
}

/// Coordinate offsets can be used for interpolate operations in circular
/// interpolation mode.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CoordinateOffset {
    pub x: Option<CoordinateNumber>,
    pub y: Option<CoordinateNumber>,
    pub format: CoordinateFormat,
}

impl CoordinateOffset {
    pub fn new<T, U>(x: T, y: U, format: CoordinateFormat) -> Self
            where T: Into<CoordinateNumber>, U: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: Some(y.into()), format: format }
    }

    pub fn at_x<T>(x: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: Some(x.into()), y: None, format: format }
    }

    pub fn at_y<T>(y: T, format: CoordinateFormat) -> Self where T: Into<CoordinateNumber> {
        CoordinateOffset { x: None, y: Some(y.into()), format: format }
    }
}

// Helper macros

macro_rules! impl_from {
    ($from:ty, $for:ty, $variant:expr) => {
        impl From<$from> for $for {
            fn from(val: $from) -> Self {
                $variant(val)
            }
        }
    }
}

// Root type

#[derive(Debug, Clone, PartialEq)]
pub enum Command {
    FunctionCode(FunctionCode),
    ExtendedCode(ExtendedCode),
}

impl_from!(FunctionCode, Command, Command::FunctionCode);
impl_from!(ExtendedCode, Command, Command::ExtendedCode);

// Main categories

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FunctionCode {
    DCode(DCode),
    GCode(GCode),
    MCode(MCode),
}

impl_from!(DCode, FunctionCode, FunctionCode::DCode);
impl_from!(GCode, FunctionCode, FunctionCode::GCode);
impl_from!(MCode, FunctionCode, FunctionCode::MCode);

#[derive(Debug, Clone, PartialEq)]
pub enum ExtendedCode {
    /// FS
    CoordinateFormat(CoordinateFormat),
    /// MO
    Unit(Unit),
    /// AD
    ApertureDefinition(ApertureDefinition),
    /// AM
    ApertureMacro(::macros::ApertureMacro),
    /// LP
    LoadPolarity(Polarity),
    /// SR
    StepAndRepeat(StepAndRepeat),
    /// TF
    FileAttribute(::attributes::FileAttribute),
    /// TA
    ApertureAttribute(::attributes::ApertureAttribute),
    /// TD
    DeleteAttribute(String),
}

impl_from!(CoordinateFormat, ExtendedCode, ExtendedCode::CoordinateFormat);
impl_from!(Unit, ExtendedCode, ExtendedCode::Unit);
impl_from!(ApertureDefinition, ExtendedCode, ExtendedCode::ApertureDefinition);
impl_from!(::macros::ApertureMacro, ExtendedCode, ExtendedCode::ApertureMacro);
impl_from!(Polarity, ExtendedCode, ExtendedCode::LoadPolarity);
impl_from!(StepAndRepeat, ExtendedCode, ExtendedCode::StepAndRepeat);
impl_from!(::attributes::FileAttribute, ExtendedCode, ExtendedCode::FileAttribute);
impl_from!(::attributes::ApertureAttribute, ExtendedCode, ExtendedCode::ApertureAttribute);

// Function codes

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DCode {
    Operation(Operation),
    SelectAperture(i32),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GCode {
    InterpolationMode(InterpolationMode),
    RegionMode(bool),
    QuadrantMode(QuadrantMode),
    Comment(String),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MCode {
    EndOfFile,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Operation {
    /// D01 Command
    Interpolate(Coordinates, Option<CoordinateOffset>),
    /// D02 Command
    Move(Coordinates),
    /// D03 Command
    Flash(Coordinates),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InterpolationMode {
    Linear,
    ClockwiseCircular,
    CounterclockwiseCircular,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum QuadrantMode {
    Single,
    Multi,
}

// Extended codes

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Unit {
    Inches,
    Millimeters,
}

#[derive(Debug, Clone, PartialEq)]
pub struct ApertureDefinition {
    pub code: i32,
    pub aperture: Aperture,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Aperture {
    Circle(Circle),
    Rectangle(Rectangular),
    Obround(Rectangular),
    Polygon(Polygon),
    Other(String),
}

#[derive(Debug, Clone, PartialEq)]
pub struct Circle {
    pub diameter: f64,
    pub hole_diameter: Option<f64>,
}

impl Circle {
    pub fn new(diameter: f64) -> Self {
        Circle {
            diameter: diameter,
            hole_diameter: None,
        }
    }

    pub fn with_hole(diameter: f64, hole_diameter: f64) -> Self {
        Circle {
            diameter: diameter,
            hole_diameter: Some(hole_diameter),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Rectangular {
    pub x: f64,
    pub y: f64,
    pub hole_diameter: Option<f64>,
}

impl Rectangular {
    pub fn new(x: f64, y: f64) -> Self {
        Rectangular {
            x: x,
            y: y,
            hole_diameter: None,
        }
    }

    pub fn with_hole(x: f64, y: f64, hole_diameter: f64) -> Self {
        Rectangular {
            x: x,
            y: y,
            hole_diameter: Some(hole_diameter),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Polygon {
    pub diameter: f64,
    pub vertices: u8, // 3--12
    pub rotation: Option<f64>,
    pub hole_diameter: Option<f64>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Polarity {
    Clear,
    Dark,
}

#[derive(Debug, Clone, PartialEq)]
pub enum StepAndRepeat {
    Open { repeat_x: u32, repeat_y: u32, distance_x: f64, distance_y: f64 },
    Close,
}

#[cfg(test)]
mod test {
    extern crate conv;

    use ::{CoordinateNumber, CoordinateFormat};
    use super::*;

    #[test]
    fn test_debug() {
        //! The debug representation should work properly.
        let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment("test".to_string())));
        let debug = format!("{:?}", c);
        assert_eq!(debug, "FunctionCode(GCode(Comment(\"test\")))");
    }

    #[test]
    fn test_coordinates_into() {
        let cf = CoordinateFormat::new(2, 4);
        let c1 = Coordinates::new(CoordinateNumber::from(1), CoordinateNumber::from(2), cf);
        let c2 = Coordinates::new(1, 2, cf);
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_coordinates_into_mixed() {
        let cf = CoordinateFormat::new(2, 4);
        let c1 = Coordinates::new(CoordinateNumber::from(1), 2, cf);
        let c2 = Coordinates::new(1, 2, cf);
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_circle_new() {
        let c1 = Circle::new(3.0);
        let c2 = Circle { diameter: 3.0, hole_diameter: None };
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_circle_with_hole() {
        let c1 = Circle::with_hole(3.0, 1.0);
        let c2 = Circle { diameter: 3.0, hole_diameter: Some(1.0) };
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_rectangular_new() {
        let r1 = Rectangular::new(2.0, 3.0);
        let r2 = Rectangular { x: 2.0, y: 3.0, hole_diameter: None };
        assert_eq!(r1, r2);
    }

    #[test]
    fn test_rectangular_with_hole() {
        let r1 = Rectangular::with_hole(3.0, 2.0, 1.0);
        let r2 = Rectangular { x: 3.0, y: 2.0, hole_diameter: Some(1.0) };
        assert_eq!(r1, r2);
    }

    #[test]
    fn test_command_from_function_code() {
        let comment = FunctionCode::GCode(GCode::Comment("hello".into()));
        let c1: Command = Command::FunctionCode(comment.clone());
        let c2: Command = comment.into();
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_command_from_extended_code() {
        let delete_attr = ExtendedCode::DeleteAttribute("hello".into());
        let c1: Command = Command::ExtendedCode(delete_attr.clone());
        let c2: Command = delete_attr.into();
        assert_eq!(c1, c2);
    }

    #[test]
    fn test_function_code_from_gcode() {
        let comment = GCode::Comment("hello".into());
        let f1: FunctionCode = FunctionCode::GCode(comment.clone());
        let f2: FunctionCode = comment.into();
        assert_eq!(f1, f2);
    }

    #[test]
    fn test_extended_code_from_polarity() {
        let e1: ExtendedCode = ExtendedCode::LoadPolarity(Polarity::Dark);
        let e2: ExtendedCode = Polarity::Dark.into();
        assert_eq!(e1, e2);
    }

}
<|endoftext|>


<commit_before>extern crate sdl2;
use std::cmp::{max, min};

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

pub trait RGB {
    fn r(&self) -> u8;
    fn g(&self) -> u8;
    fn b(&self) -> u8;
    fn rgb(&self) -> (u8,u8,u8) {
        (self.r(),self.g(),self.b())
    }
    fn new(r:u8,g:u8,b:u8) -> Self;
}

pub trait RGBA:RGB {
    fn a(&self) -> u8;
    fn rgba(&self) -> (u8,u8,u8,u8) {
        (self.r(),self.g(),self.b(),self.a())
    }
    fn new_rgba(r:u8,g:u8,b:u8,a:u8) -> Self;
}

/// will always return a flat color regardless or alpha
pub fn mix_colors<C:RGB>(color1: C, color2: C, mix_ratio: f32) -> C {
    let (r1, g1, b1) = color1.rgb();
    let (r2, g2, b2) = color2.rgb();
    let (r1, g1, b1) = (r1 as i16, g1 as i16, b1 as i16);
    let (r2, g2, b2) = (r2 as i16, g2 as i16, b2 as i16);
    let (r, g, b): (i16, i16, i16) = (((r2 - r1) as f32 * mix_ratio) as i16 + r1,
                                      ((g2 - g1) as f32 * mix_ratio) as i16 + g1,
                                      ((b2 - b1) as f32 * mix_ratio) as i16 + b1);

    let (r, g, b) =
        (max(min(r, 0xFF), 0) as u8, max(min(g, 0xFF), 0) as u8, max(min(b, 0xFF), 0) as u8);
    C::new(r, g, b)
}

pub fn fade_color<C:RGBA>(color1: C, fade_ratio: f32) -> C {
    let (r, g, b, a): (u8, u8, u8, u8) = color1.rgba();
    C::new_rgba(r, g, b, (a as f32 * fade_ratio) as u8)
}

pub fn parse_hex(hex: &str) -> Result<u32, String> {
    let mut parsed: u32 = 0;
    for character in hex.chars() {
        let char_value: u32 = try!(character.to_digit(16)
            .ok_or(String::from("failed to parse hexadecimal character")));
        parsed = parsed * 0x10 + char_value;
    }
    Ok(parsed)
}

pub fn parse_bgr<C:RGB>(bgr: &str) -> Result<C, String> {
    let bgr = bgr.trim();
    if bgr.len() != 6 {
        Err(String::from("Invalid BGR format"))
    } else {
        let (blue, greenred) = bgr.split_at(2);
        let (green, red) = greenred.split_at(2);
        let blue = try!(parse_hex(blue)) as u8;
        let green = try!(parse_hex(green)) as u8;
        let red = try!(parse_hex(red)) as u8;
        Ok(C::new(red,green,blue))
    }
}

pub fn for_each_in_dir<P: AsRef<Path>, F: Fn(&Path) -> bool>(directory: P,
                                                             recursion_level: u32,
                                                             filter: &F)
                                                             -> (Vec<PathBuf>, Vec<io::Error>) {
    if (recursion_level == 0) {
        return (vec![], vec![]);
    }
    let mut vec_path: Vec<PathBuf> = Vec::new();
    let mut vec_error: Vec<io::Error> = Vec::new();
    let paths = match fs::read_dir(directory) {
        Ok(paths) => paths,
        Err(e) => {
            return (vec![], vec![e]);
        }
    };
    for path in paths {
        match path {
            Ok(path) => {
                let filetype = path.file_type();
                match filetype {
                    Ok(finfo) => {
                        let pathbuf = path.path();
                        if finfo.is_dir() {
                            let (v_p, v_e) = for_each_in_dir(&pathbuf, recursion_level - 1, filter);
                            vec_path.extend(v_p);
                            vec_error.extend(v_e);
                        } else if filter(&pathbuf) {
                            vec_path.push(pathbuf);
                        }
                    }
                    Err(e) => {
                        vec_error.push(e);
                    }
                }
            }
            Err(e) => {
                vec_error.push(e);
            }
        }
    }
    (vec_path, vec_error)
}

#[test]
fn test_bgr() {
    let sample_bgr = "FF0000";
    assert_eq!(parse_bgr(sample_bgr).unwrap(), Color::RGB(0, 0, 255));
}

#[test]
fn test_parse_hex() {
    let sample_hex = "201";
    assert_eq!(parse_hex(sample_hex).unwrap(), 513);
}

// width and height must be between 0 and 1
pub fn fit_dims(dims:(u32,u32),
                 fit_width: Option<f32>,
                 fit_height: Option<f32>)
                 -> (Option<u32>, Option<u32>) {
    (fit_width.and_then(|width| Some((width * (dims.0 as f32)) as u32)),
     fit_height.and_then(|height| Some((height * (dims.1 as f32)) as u32)))
}
<commit_msg>fixed utils tests<commit_after>use std::cmp::{max, min};

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

pub trait RGB {
    fn r(&self) -> u8;
    fn g(&self) -> u8;
    fn b(&self) -> u8;
    fn rgb(&self) -> (u8,u8,u8) {
        (self.r(),self.g(),self.b())
    }
    fn new(r:u8,g:u8,b:u8) -> Self;
}

pub trait RGBA:RGB {
    fn a(&self) -> u8;
    fn rgba(&self) -> (u8,u8,u8,u8) {
        (self.r(),self.g(),self.b(),self.a())
    }
    fn new_rgba(r:u8,g:u8,b:u8,a:u8) -> Self;
}

/// will always return a flat color regardless or alpha
pub fn mix_colors<C:RGB>(color1: C, color2: C, mix_ratio: f32) -> C {
    let (r1, g1, b1) = color1.rgb();
    let (r2, g2, b2) = color2.rgb();
    let (r1, g1, b1) = (r1 as i16, g1 as i16, b1 as i16);
    let (r2, g2, b2) = (r2 as i16, g2 as i16, b2 as i16);
    let (r, g, b): (i16, i16, i16) = (((r2 - r1) as f32 * mix_ratio) as i16 + r1,
                                      ((g2 - g1) as f32 * mix_ratio) as i16 + g1,
                                      ((b2 - b1) as f32 * mix_ratio) as i16 + b1);

    let (r, g, b) =
        (max(min(r, 0xFF), 0) as u8, max(min(g, 0xFF), 0) as u8, max(min(b, 0xFF), 0) as u8);
    C::new(r, g, b)
}

pub fn fade_color<C:RGBA>(color1: C, fade_ratio: f32) -> C {
    let (r, g, b, a): (u8, u8, u8, u8) = color1.rgba();
    C::new_rgba(r, g, b, (a as f32 * fade_ratio) as u8)
}

pub fn parse_hex(hex: &str) -> Result<u32, String> {
    let mut parsed: u32 = 0;
    for character in hex.chars() {
        let char_value: u32 = try!(character.to_digit(16)
            .ok_or(String::from("failed to parse hexadecimal character")));
        parsed = parsed * 0x10 + char_value;
    }
    Ok(parsed)
}

pub fn parse_bgr<C:RGB>(bgr: &str) -> Result<C, String> {
    let bgr = bgr.trim();
    if bgr.len() != 6 {
        Err(String::from("Invalid BGR format"))
    } else {
        let (blue, greenred) = bgr.split_at(2);
        let (green, red) = greenred.split_at(2);
        let blue = try!(parse_hex(blue)) as u8;
        let green = try!(parse_hex(green)) as u8;
        let red = try!(parse_hex(red)) as u8;
        Ok(C::new(red,green,blue))
    }
}

pub fn for_each_in_dir<P: AsRef<Path>, F: Fn(&Path) -> bool>(directory: P,
                                                             recursion_level: u32,
                                                             filter: &F)
                                                             -> (Vec<PathBuf>, Vec<io::Error>) {
    if (recursion_level == 0) {
        return (vec![], vec![]);
    }
    let mut vec_path: Vec<PathBuf> = Vec::new();
    let mut vec_error: Vec<io::Error> = Vec::new();
    let paths = match fs::read_dir(directory) {
        Ok(paths) => paths,
        Err(e) => {
            return (vec![], vec![e]);
        }
    };
    for path in paths {
        match path {
            Ok(path) => {
                let filetype = path.file_type();
                match filetype {
                    Ok(finfo) => {
                        let pathbuf = path.path();
                        if finfo.is_dir() {
                            let (v_p, v_e) = for_each_in_dir(&pathbuf, recursion_level - 1, filter);
                            vec_path.extend(v_p);
                            vec_error.extend(v_e);
                        } else if filter(&pathbuf) {
                            vec_path.push(pathbuf);
                        }
                    }
                    Err(e) => {
                        vec_error.push(e);
                    }
                }
            }
            Err(e) => {
                vec_error.push(e);
            }
        }
    }
    (vec_path, vec_error)
}

#[test]
fn test_bgr() {
    use ::overlay::Color;
    let sample_bgr = "FF0000";
    assert_eq!(parse_bgr::<Color>(sample_bgr).unwrap(), Color::new(0, 0, 255));
}

#[test]
fn test_parse_hex() {
    let sample_hex = "201";
    assert_eq!(parse_hex(sample_hex).unwrap(), 513);
}

// width and height must be between 0 and 1
pub fn fit_dims(dims:(u32,u32),
                 fit_width: Option<f32>,
                 fit_height: Option<f32>)
                 -> (Option<u32>, Option<u32>) {
    (fit_width.and_then(|width| Some((width * (dims.0 as f32)) as u32)),
     fit_height.and_then(|height| Some((height * (dims.1 as f32)) as u32)))
}
<|endoftext|>


<commit_before>use super::*;

pub fn escape_single_quote<S: AsRef<str>>(s: S) -> String {
    s.as_ref().replace("'", "''")
}

#[test]
fn test_escape_single_quote() {
    assert_eq!(escape_single_quote("my' precious"), "my'' precious");
}

pub fn get_rootPath<'a>(
    path: &'a Path,
    languageId: &str,
    rootMarkers: &Option<RootMarkers>,
) -> Result<&'a Path> {
    if let Some(ref rootMarkers) = *rootMarkers {
        let empty = vec![];
        let rootMarkers = match *rootMarkers {
            RootMarkers::Array(ref arr) => arr,
            RootMarkers::Map(ref map) => map.get(languageId).unwrap_or(&empty),
        };

        for marker in rootMarkers {
            let ret = traverse_up(path, |dir| {
                let p = dir.join(marker);
                let p = p.to_str();
                if p.is_none() {
                    return false;
                }
                let p = p.unwrap_or_default();
                match glob::glob(p) {
                    Ok(paths) => paths.count() > 0,
                    _ => false,
                }
            });

            if ret.is_ok() {
                return ret;
            }
        }
    }

    match languageId {
        "rust" => traverse_up(path, |dir| dir.join("Cargo.toml").exists()),
        "php" => traverse_up(path, |dir| dir.join("composer.json").exists()),
        "javascript" | "typescript" => traverse_up(path, |dir| dir.join("package.json").exists()),
        "python" => traverse_up(path, |dir| {
            dir.join("setup.py").exists() || dir.join("Pipfile").exists()
                || dir.join("requirements.txt").exists()
        }),
        "c" | "cpp" => traverse_up(path, |dir| dir.join("compile_commands.json").exists()),
        "cs" => traverse_up(path, is_dotnet_root),
        "java" => traverse_up(path, |dir| {
            dir.join(".project").exists() || dir.join("pom.xml").exists()
                || dir.join("build.gradle").exists()
        }),
        "scala" => traverse_up(path, |dir| dir.join("build.sbt").exists()),
        "haskell" => traverse_up(path, |dir| dir.join("stack.yaml").exists())
            .or_else(|_| traverse_up(path, |dir| dir.join(".cabal").exists())),
        _ => Err(format_err!("Unknown languageId: {}", languageId)),
    }.or_else(|_| {
        traverse_up(path, |dir| {
            dir.join(".git").exists() || dir.join(".hg").exists() || dir.join(".svn").exists()
        })
    })
        .or_else(|_| {
            let parent = path.parent()
                .ok_or_else(|| format_err!("Failed to get parent dir! path: {:?}", path));
            warn!(
                "Unknown project type. Fallback to use dir as project root: {:?}",
                parent
            );
            parent
        })
}

fn traverse_up<F>(path: &Path, predicate: F) -> Result<&Path>
where
    F: Fn(&Path) -> bool,
{
    if predicate(path) {
        return Ok(path);
    }

    let next_path = path.parent().ok_or_else(|| err_msg("Hit root"))?;

    traverse_up(next_path, predicate)
}

fn is_dotnet_root(dir: &Path) -> bool {
    if dir.join("project.json").exists() {
        return true;
    }
    if !dir.is_dir() {
        return false;
    }

    let entries = match dir.read_dir() {
        Ok(entries) => entries,
        Err(_) => return false,
    };
    for entry in entries {
        if let Ok(entry) = entry {
            if entry.path().ends_with(".csproj") {
                return true;
            }
        }
    }

    false
}

pub trait ToUrl {
    fn to_url(&self) -> Result<Url>;
}

impl<P: AsRef<Path> + std::fmt::Debug> ToUrl for P {
    fn to_url(&self) -> Result<Url> {
        Url::from_file_path(self).or_else(|_| {
            Err(format_err!(
                "Failed to convert from path ({:?}) to Url",
                self
            ))
        })
    }
}

pub fn apply_TextEdits(lines: &[String], edits: &[TextEdit]) -> Result<Vec<String>> {
    // Edits are ordered from bottom to top, from right to left.
    let mut edits_by_index = vec![];
    for edit in edits {
        let start_line = edit.range.start.line.to_usize()?;
        let start_character: usize = edit.range.start.character.to_usize()?;
        let end_line: usize = edit.range.end.line.to_usize()?;
        let end_character: usize = edit.range.end.character.to_usize()?;

        let start = lines[..std::cmp::min(start_line, lines.len())]
            .iter()
            .map(|l| l.len())
            .fold(0, |acc, l| acc + l + 1 /*line ending*/) + start_character;
        let end = lines[..std::cmp::min(end_line, lines.len())]
            .iter()
            .map(|l| l.len())
            .fold(0, |acc, l| acc + l + 1 /*line ending*/) + end_character;
        edits_by_index.push((start, end, &edit.new_text));
    }

    let mut text = lines.join("\n");
    for (start, end, new_text) in edits_by_index {
        let start = std::cmp::min(start, text.len());
        let end = std::cmp::min(end, text.len());
        text = String::new() + &text[..start] + new_text + &text[end..];
    }

    Ok(text.lines().map(|l| l.to_owned()).collect())
}

#[test]
fn test_apply_TextEdit() {
    let lines: Vec<String> = r#"fn main() {
0;
}
"#.lines()
        .map(|l| l.to_owned())
        .collect();

    let expect: Vec<String> = r#"fn main() {
    0;
}
"#.lines()
        .map(|l| l.to_owned())
        .collect();

    let edit = TextEdit {
        range: Range {
            start: Position {
                line: 0,
                character: 0,
            },
            end: Position {
                line: 3,
                character: 0,
            },
        },
        new_text: r#"fn main() {
    0;
}
"#.to_owned(),
    };

    assert_eq!(apply_TextEdits(&lines, &[edit]).unwrap(), expect);
}

#[test]
fn test_apply_TextEdit_overlong_end() {
    let lines: Vec<String> = r#"abc = 123"#.lines().map(|l| l.to_owned()).collect();

    let expect: Vec<String> = r#"nb = 123"#.lines().map(|l| l.to_owned()).collect();

    let edit = TextEdit {
        range: Range {
            start: Position {
                line: 0,
                character: 0,
            },
            end: Position {
                line: 99999999,
                character: 0,
            },
        },
        new_text: r#"nb = 123"#.to_owned(),
    };

    assert_eq!(apply_TextEdits(&lines, &[edit]).unwrap(), expect);
}

fn get_command_add_sign(sign: &Sign, filename: &str) -> String {
    format!(
        " | execute 'sign place {} line={} name=LanguageClient{:?} file={}'",
        sign.id, sign.line, sign.severity, filename
    )
}

#[test]
fn test_get_command_add_sign() {
    let sign = Sign::new(1, "".to_owned(), DiagnosticSeverity::Error);
    assert_eq!(
        get_command_add_sign(&sign, ""),
        " | execute 'sign place 75000 line=1 name=LanguageClientError file='"
    );

    let sign = Sign::new(7, "".to_owned(), DiagnosticSeverity::Error);
    assert_eq!(
        get_command_add_sign(&sign, ""),
        " | execute 'sign place 75024 line=7 name=LanguageClientError file='"
    );

    let sign = Sign::new(7, "".to_owned(), DiagnosticSeverity::Hint);
    assert_eq!(
        get_command_add_sign(&sign, ""),
        " | execute 'sign place 75027 line=7 name=LanguageClientHint file='"
    );
}

fn get_command_delete_sign(sign: &Sign, filename: &str) -> String {
    format!(" | execute 'sign unplace {} file={}'", sign.id, filename)
}

#[test]
fn test_get_command_delete_sign() {}

use diff;

pub fn get_command_update_signs(
    signs_prev: &[Sign],
    signs: &[Sign],
    filename: &str,
) -> (Vec<Sign>, String) {
    // Sign id might become different due to lines shifting. Use sign's existing sign id to
    // track same sign.
    let mut signs_next = vec![];

    let mut cmd = "echo".to_owned();
    for comp in diff::slice(signs_prev, signs) {
        match comp {
            diff::Result::Left(sign) => {
                cmd += &get_command_delete_sign(sign, filename);
            }
            diff::Result::Right(sign) => {
                cmd += &get_command_add_sign(sign, filename);
                signs_next.push(sign.clone());
            }
            diff::Result::Both(sign, _) => {
                signs_next.push(sign.clone());
            }
        }
    }

    (signs_next, cmd)
}

#[test]
fn test_get_command_update_signs() {
    let signs_prev = vec![Sign::new(1, "abcde".to_string(), DiagnosticSeverity::Error)];
    let signs = vec![Sign::new(3, "abcde".to_string(), DiagnosticSeverity::Error)];
    let (signs_next, cmd) = get_command_update_signs(&signs_prev, &signs, "f");
    assert_eq!(
        serde_json::to_string(&signs_next).unwrap(),
        "[{\"id\":75000,\"line\":1,\"text\":\"abcde\",\"severity\":1}]"
    );
    assert_eq!(cmd, "echo");
}

pub trait Combine {
    /// Recursively combine two objects.
    fn combine(self, other: Self) -> Self
    where
        Self: Sized;
}

impl Combine for Value {
    fn combine(self, other: Self) -> Self {
        match (self, other) {
            (this, Value::Null) => this,
            (Value::Object(this), Value::Object(other)) => {
                let mut map = serde_json::map::Map::new();
                let mut keys: HashSet<String> = HashSet::new();
                for k in this.keys() {
                    keys.insert(k.clone());
                }
                for k in other.keys() {
                    keys.insert(k.clone());
                }
                for k in keys.drain() {
                    let v1 = this.get(&k).unwrap_or(&Value::Null).clone();
                    let v2 = other.get(&k).unwrap_or(&Value::Null).clone();
                    map.insert(k, v1.combine(v2));
                }
                Value::Object(map)
            }
            (_, other) => other,
        }
    }
}

pub fn vim_cmd_args_to_value(args: &[String]) -> Result<Value> {
    let mut map = serde_json::map::Map::new();
    for arg in args {
        let mut tokens: Vec<_> = arg.splitn(2, '=').collect();
        tokens.reverse();
        let key = tokens
            .pop()
            .ok_or_else(|| format_err!("Failed to parse command arguments! tokens: {:?}", tokens))?;
        let value = tokens
            .pop()
            .ok_or_else(|| format_err!("Failed to parse command arguments! tokens: {:?}", tokens))?;
        let value = Value::String(value.to_owned());
        map.insert(key.to_owned(), value);
    }

    Ok(Value::Object(map))
}

#[test]
fn test_vim_cmd_args_to_value() {
    let cmdargs = ["rootPath=/tmp".to_owned()];
    assert_eq!(
        vim_cmd_args_to_value(&cmdargs).unwrap(),
        json!({
        "rootPath": "/tmp"
    })
    );
}

pub fn diff_value<'a>(v1: &'a Value, v2: &'a Value, path: &str) -> HashMap<String, (Value, Value)> {
    let mut diffs = HashMap::new();
    match (v1, v2) {
        (&Value::Null, &Value::Null)
        | (&Value::Bool(_), &Value::Bool(_))
        | (&Value::Number(_), &Value::Number(_))
        | (&Value::String(_), &Value::String(_))
        | (&Value::Array(_), &Value::Array(_)) => if v1 != v2 {
            diffs.insert(path.to_owned(), (v1.clone(), v2.clone()));
        },
        (&Value::Object(ref map1), &Value::Object(ref map2)) => {
            let keys1: HashSet<&String> = map1.keys().collect();
            let keys2: HashSet<&String> = map2.keys().collect();
            for k in keys1.union(&keys2) {
                let mut next_path = String::from(path);
                next_path += ".";
                next_path += k;
                let next_diffs = diff_value(
                    map1.get(*k).unwrap_or(&Value::Null),
                    map2.get(*k).unwrap_or(&Value::Null),
                    &next_path,
                );
                diffs.extend(next_diffs);
            }
        }
        _ => {
            diffs.insert(path.to_owned(), (v1.clone(), v2.clone()));
        }
    }

    diffs
}

#[test]
fn test_diff_value() {
    assert_eq!(diff_value(&json!({}), &json!({}), "state",), hashmap!());
    assert_eq!(
        diff_value(
            &json!({
                "line": 1,
            }),
            &json!({
                "line": 3,
            }),
            "state"
        ),
        hashmap!{
            "state.line".to_owned() => (json!(1), json!(3)),
        }
    );
}

pub trait Canonicalize {
    fn canonicalize(&self) -> String;
}

impl<P> Canonicalize for P
where
    P: AsRef<Path>,
{
    fn canonicalize(&self) -> String {
        if let Ok(fc) = std::fs::canonicalize(self) {
            if let Some(fs) = fc.to_str() {
                return fs.to_owned();
            }
        }

        self.as_ref()
            .to_str()
            .map(|s| s.to_owned())
            .unwrap_or_default()
    }
}

pub fn get_default_initializationOptions(languageId: &str) -> Value {
    match languageId {
        "java" => json!({
            "extendedClientCapabilities": {
                "classFileContentsSupport": true
            }
        }),
        _ => json!({}),
    }
}
<commit_msg>Trim UNC prefixes.<commit_after>use super::*;

pub fn escape_single_quote<S: AsRef<str>>(s: S) -> String {
    s.as_ref().replace("'", "''")
}

#[test]
fn test_escape_single_quote() {
    assert_eq!(escape_single_quote("my' precious"), "my'' precious");
}

pub fn get_rootPath<'a>(
    path: &'a Path,
    languageId: &str,
    rootMarkers: &Option<RootMarkers>,
) -> Result<&'a Path> {
    if let Some(ref rootMarkers) = *rootMarkers {
        let empty = vec![];
        let rootMarkers = match *rootMarkers {
            RootMarkers::Array(ref arr) => arr,
            RootMarkers::Map(ref map) => map.get(languageId).unwrap_or(&empty),
        };

        for marker in rootMarkers {
            let ret = traverse_up(path, |dir| {
                let p = dir.join(marker);
                let p = p.to_str();
                if p.is_none() {
                    return false;
                }
                let p = p.unwrap_or_default();
                match glob::glob(p) {
                    Ok(paths) => paths.count() > 0,
                    _ => false,
                }
            });

            if ret.is_ok() {
                return ret;
            }
        }
    }

    match languageId {
        "rust" => traverse_up(path, |dir| dir.join("Cargo.toml").exists()),
        "php" => traverse_up(path, |dir| dir.join("composer.json").exists()),
        "javascript" | "typescript" => traverse_up(path, |dir| dir.join("package.json").exists()),
        "python" => traverse_up(path, |dir| {
            dir.join("setup.py").exists() || dir.join("Pipfile").exists()
                || dir.join("requirements.txt").exists()
        }),
        "c" | "cpp" => traverse_up(path, |dir| dir.join("compile_commands.json").exists()),
        "cs" => traverse_up(path, is_dotnet_root),
        "java" => traverse_up(path, |dir| {
            dir.join(".project").exists() || dir.join("pom.xml").exists()
                || dir.join("build.gradle").exists()
        }),
        "scala" => traverse_up(path, |dir| dir.join("build.sbt").exists()),
        "haskell" => traverse_up(path, |dir| dir.join("stack.yaml").exists())
            .or_else(|_| traverse_up(path, |dir| dir.join(".cabal").exists())),
        _ => Err(format_err!("Unknown languageId: {}", languageId)),
    }.or_else(|_| {
        traverse_up(path, |dir| {
            dir.join(".git").exists() || dir.join(".hg").exists() || dir.join(".svn").exists()
        })
    })
        .or_else(|_| {
            let parent = path.parent()
                .ok_or_else(|| format_err!("Failed to get parent dir! path: {:?}", path));
            warn!(
                "Unknown project type. Fallback to use dir as project root: {:?}",
                parent
            );
            parent
        })
}

fn traverse_up<F>(path: &Path, predicate: F) -> Result<&Path>
where
    F: Fn(&Path) -> bool,
{
    if predicate(path) {
        return Ok(path);
    }

    let next_path = path.parent().ok_or_else(|| err_msg("Hit root"))?;

    traverse_up(next_path, predicate)
}

fn is_dotnet_root(dir: &Path) -> bool {
    if dir.join("project.json").exists() {
        return true;
    }
    if !dir.is_dir() {
        return false;
    }

    let entries = match dir.read_dir() {
        Ok(entries) => entries,
        Err(_) => return false,
    };
    for entry in entries {
        if let Ok(entry) = entry {
            if entry.path().ends_with(".csproj") {
                return true;
            }
        }
    }

    false
}

pub trait ToUrl {
    fn to_url(&self) -> Result<Url>;
}

impl<P: AsRef<Path> + std::fmt::Debug> ToUrl for P {
    fn to_url(&self) -> Result<Url> {
        Url::from_file_path(self).or_else(|_| {
            Err(format_err!(
                "Failed to convert from path ({:?}) to Url",
                self
            ))
        })
    }
}

pub fn apply_TextEdits(lines: &[String], edits: &[TextEdit]) -> Result<Vec<String>> {
    // Edits are ordered from bottom to top, from right to left.
    let mut edits_by_index = vec![];
    for edit in edits {
        let start_line = edit.range.start.line.to_usize()?;
        let start_character: usize = edit.range.start.character.to_usize()?;
        let end_line: usize = edit.range.end.line.to_usize()?;
        let end_character: usize = edit.range.end.character.to_usize()?;

        let start = lines[..std::cmp::min(start_line, lines.len())]
            .iter()
            .map(|l| l.len())
            .fold(0, |acc, l| acc + l + 1 /*line ending*/) + start_character;
        let end = lines[..std::cmp::min(end_line, lines.len())]
            .iter()
            .map(|l| l.len())
            .fold(0, |acc, l| acc + l + 1 /*line ending*/) + end_character;
        edits_by_index.push((start, end, &edit.new_text));
    }

    let mut text = lines.join("\n");
    for (start, end, new_text) in edits_by_index {
        let start = std::cmp::min(start, text.len());
        let end = std::cmp::min(end, text.len());
        text = String::new() + &text[..start] + new_text + &text[end..];
    }

    Ok(text.lines().map(|l| l.to_owned()).collect())
}

#[test]
fn test_apply_TextEdit() {
    let lines: Vec<String> = r#"fn main() {
0;
}
"#.lines()
        .map(|l| l.to_owned())
        .collect();

    let expect: Vec<String> = r#"fn main() {
    0;
}
"#.lines()
        .map(|l| l.to_owned())
        .collect();

    let edit = TextEdit {
        range: Range {
            start: Position {
                line: 0,
                character: 0,
            },
            end: Position {
                line: 3,
                character: 0,
            },
        },
        new_text: r#"fn main() {
    0;
}
"#.to_owned(),
    };

    assert_eq!(apply_TextEdits(&lines, &[edit]).unwrap(), expect);
}

#[test]
fn test_apply_TextEdit_overlong_end() {
    let lines: Vec<String> = r#"abc = 123"#.lines().map(|l| l.to_owned()).collect();

    let expect: Vec<String> = r#"nb = 123"#.lines().map(|l| l.to_owned()).collect();

    let edit = TextEdit {
        range: Range {
            start: Position {
                line: 0,
                character: 0,
            },
            end: Position {
                line: 99999999,
                character: 0,
            },
        },
        new_text: r#"nb = 123"#.to_owned(),
    };

    assert_eq!(apply_TextEdits(&lines, &[edit]).unwrap(), expect);
}

fn get_command_add_sign(sign: &Sign, filename: &str) -> String {
    format!(
        " | execute 'sign place {} line={} name=LanguageClient{:?} file={}'",
        sign.id, sign.line, sign.severity, filename
    )
}

#[test]
fn test_get_command_add_sign() {
    let sign = Sign::new(1, "".to_owned(), DiagnosticSeverity::Error);
    assert_eq!(
        get_command_add_sign(&sign, ""),
        " | execute 'sign place 75000 line=1 name=LanguageClientError file='"
    );

    let sign = Sign::new(7, "".to_owned(), DiagnosticSeverity::Error);
    assert_eq!(
        get_command_add_sign(&sign, ""),
        " | execute 'sign place 75024 line=7 name=LanguageClientError file='"
    );

    let sign = Sign::new(7, "".to_owned(), DiagnosticSeverity::Hint);
    assert_eq!(
        get_command_add_sign(&sign, ""),
        " | execute 'sign place 75027 line=7 name=LanguageClientHint file='"
    );
}

fn get_command_delete_sign(sign: &Sign, filename: &str) -> String {
    format!(" | execute 'sign unplace {} file={}'", sign.id, filename)
}

#[test]
fn test_get_command_delete_sign() {}

use diff;

pub fn get_command_update_signs(
    signs_prev: &[Sign],
    signs: &[Sign],
    filename: &str,
) -> (Vec<Sign>, String) {
    // Sign id might become different due to lines shifting. Use sign's existing sign id to
    // track same sign.
    let mut signs_next = vec![];

    let mut cmd = "echo".to_owned();
    for comp in diff::slice(signs_prev, signs) {
        match comp {
            diff::Result::Left(sign) => {
                cmd += &get_command_delete_sign(sign, filename);
            }
            diff::Result::Right(sign) => {
                cmd += &get_command_add_sign(sign, filename);
                signs_next.push(sign.clone());
            }
            diff::Result::Both(sign, _) => {
                signs_next.push(sign.clone());
            }
        }
    }

    (signs_next, cmd)
}

#[test]
fn test_get_command_update_signs() {
    let signs_prev = vec![Sign::new(1, "abcde".to_string(), DiagnosticSeverity::Error)];
    let signs = vec![Sign::new(3, "abcde".to_string(), DiagnosticSeverity::Error)];
    let (signs_next, cmd) = get_command_update_signs(&signs_prev, &signs, "f");
    assert_eq!(
        serde_json::to_string(&signs_next).unwrap(),
        "[{\"id\":75000,\"line\":1,\"text\":\"abcde\",\"severity\":1}]"
    );
    assert_eq!(cmd, "echo");
}

pub trait Combine {
    /// Recursively combine two objects.
    fn combine(self, other: Self) -> Self
    where
        Self: Sized;
}

impl Combine for Value {
    fn combine(self, other: Self) -> Self {
        match (self, other) {
            (this, Value::Null) => this,
            (Value::Object(this), Value::Object(other)) => {
                let mut map = serde_json::map::Map::new();
                let mut keys: HashSet<String> = HashSet::new();
                for k in this.keys() {
                    keys.insert(k.clone());
                }
                for k in other.keys() {
                    keys.insert(k.clone());
                }
                for k in keys.drain() {
                    let v1 = this.get(&k).unwrap_or(&Value::Null).clone();
                    let v2 = other.get(&k).unwrap_or(&Value::Null).clone();
                    map.insert(k, v1.combine(v2));
                }
                Value::Object(map)
            }
            (_, other) => other,
        }
    }
}

pub fn vim_cmd_args_to_value(args: &[String]) -> Result<Value> {
    let mut map = serde_json::map::Map::new();
    for arg in args {
        let mut tokens: Vec<_> = arg.splitn(2, '=').collect();
        tokens.reverse();
        let key = tokens
            .pop()
            .ok_or_else(|| format_err!("Failed to parse command arguments! tokens: {:?}", tokens))?;
        let value = tokens
            .pop()
            .ok_or_else(|| format_err!("Failed to parse command arguments! tokens: {:?}", tokens))?;
        let value = Value::String(value.to_owned());
        map.insert(key.to_owned(), value);
    }

    Ok(Value::Object(map))
}

#[test]
fn test_vim_cmd_args_to_value() {
    let cmdargs = ["rootPath=/tmp".to_owned()];
    assert_eq!(
        vim_cmd_args_to_value(&cmdargs).unwrap(),
        json!({
        "rootPath": "/tmp"
    })
    );
}

pub fn diff_value<'a>(v1: &'a Value, v2: &'a Value, path: &str) -> HashMap<String, (Value, Value)> {
    let mut diffs = HashMap::new();
    match (v1, v2) {
        (&Value::Null, &Value::Null)
        | (&Value::Bool(_), &Value::Bool(_))
        | (&Value::Number(_), &Value::Number(_))
        | (&Value::String(_), &Value::String(_))
        | (&Value::Array(_), &Value::Array(_)) => if v1 != v2 {
            diffs.insert(path.to_owned(), (v1.clone(), v2.clone()));
        },
        (&Value::Object(ref map1), &Value::Object(ref map2)) => {
            let keys1: HashSet<&String> = map1.keys().collect();
            let keys2: HashSet<&String> = map2.keys().collect();
            for k in keys1.union(&keys2) {
                let mut next_path = String::from(path);
                next_path += ".";
                next_path += k;
                let next_diffs = diff_value(
                    map1.get(*k).unwrap_or(&Value::Null),
                    map2.get(*k).unwrap_or(&Value::Null),
                    &next_path,
                );
                diffs.extend(next_diffs);
            }
        }
        _ => {
            diffs.insert(path.to_owned(), (v1.clone(), v2.clone()));
        }
    }

    diffs
}

#[test]
fn test_diff_value() {
    assert_eq!(diff_value(&json!({}), &json!({}), "state",), hashmap!());
    assert_eq!(
        diff_value(
            &json!({
                "line": 1,
            }),
            &json!({
                "line": 3,
            }),
            "state"
        ),
        hashmap!{
            "state.line".to_owned() => (json!(1), json!(3)),
        }
    );
}

pub trait Canonicalize {
    fn canonicalize(&self) -> String;
}

impl<P> Canonicalize for P
where
    P: AsRef<Path>,
{
    fn canonicalize(&self) -> String {
        let path = match std::fs::canonicalize(self) {
            Ok(path) => path.to_string_lossy().into_owned(),
            _ => self.as_ref().to_string_lossy().into_owned(),
        };

        // Trim UNC prefixes.
        // See https://github.com/rust-lang/rust/issues/42869
        path.trim_left_matches("\\\\?\\").into()
    }
}

pub fn get_default_initializationOptions(languageId: &str) -> Value {
    match languageId {
        "java" => json!({
            "extendedClientCapabilities": {
                "classFileContentsSupport": true
            }
        }),
        _ => json!({}),
    }
}
<|endoftext|>


<commit_before>//! Useful stuff related to the spaceapi.

/// An ``Optional`` can contain ``Optional::Value<T>`` or ``Optional::Absent``.
/// It is similar to an ``Option``, but ``Optional::Absent`` means it will be
/// omitted when serialized, while ``None`` will be serialized to ``null``.
#[derive(Debug, Copy, Clone)]
pub enum Optional<T> {
    Value(T),
    Absent,
}

impl<T> Optional<T> {

    /// Moves the value `v` out of the `Optional<T>` if it is `Value(v)`.
    ///
    /// # Panics
    ///
    /// Panics if the self value equals `Absent`.
    ///
    /// # Safety note
    ///
    /// In general, because this function may panic, its use is discouraged.
    /// Instead, prefer to use pattern matching and handle the `Absent`
    /// case explicitly.
    ///
    /// # Examples
    ///
    /// ```
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let x = Value("air");
    /// assert_eq!(x.unwrap(), "air");
    /// ```
    ///
    /// ```{.should_panic}
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let x: Optional<&str> = Absent;
    /// assert_eq!(x.unwrap(), "air"); // fails
    /// ```
    pub fn unwrap(self) -> T {
        match self {
            Optional::Value(val) => val,
            Optional::Absent => panic!("called `Optional::unwrap()` on a `Absent` value"),
        }
    }

    /// Returns the contained value or computes it from a closure.
    ///
    /// # Examples
    ///
    /// ```
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let k = 10;
    /// assert_eq!(Value(4).unwrap_or_else(|| 2 * k), 4);
    /// assert_eq!(Absent.unwrap_or_else(|| 2 * k), 20);
    /// ```
    pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
        match self {
            Optional::Value(x) => x,
            Optional::Absent => f()
        }
    }

    /// Applies a function to the contained value or returns a default.  see
    /// [`std::option::Option<T>::map_or`](http://doc.rust-lang.org/std/option/enum.Option.html#method.map_or)
    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
        match self {
            Optional::Value(v) => f(v),
            Optional::Absent => def,
        }
    }

    /// Converts from `Optional<T>` to `Optional<&mut T>`
    pub fn as_mut<'r>(&'r mut self) -> Optional<&'r mut T> {
        match *self {
            Optional::Value(ref mut x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    /// Converts from `Optional<T>` to `Optional<&T>`
    pub fn as_ref<'r>(&'r self) -> Optional<&'r T> {
        match *self {
            Optional::Value(ref x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    /// Returns `true` if the optional is a `Absent` value
    ///
    /// # Examples
    ///
    /// ```
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let x: Optional<u32> = Value(2);
    /// assert_eq!(x.is_absent(), false);
    ///
    /// let x: Optional<u32> = Absent;
    /// assert_eq!(x.is_absent(), true);
    /// ```
    pub fn is_absent(&self) -> bool {
        match *self {
            Optional::Absent => true,
            _ => false
        }
    }

}
<commit_msg>Optional: Also derive (Parial)Eq/Ord and Hash<commit_after>//! Useful stuff related to the spaceapi.

/// An ``Optional`` can contain ``Optional::Value<T>`` or ``Optional::Absent``.
/// It is similar to an ``Option``, but ``Optional::Absent`` means it will be
/// omitted when serialized, while ``None`` will be serialized to ``null``.
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum Optional<T> {
    Value(T),
    Absent,
}

impl<T> Optional<T> {

    /// Moves the value `v` out of the `Optional<T>` if it is `Value(v)`.
    ///
    /// # Panics
    ///
    /// Panics if the self value equals `Absent`.
    ///
    /// # Safety note
    ///
    /// In general, because this function may panic, its use is discouraged.
    /// Instead, prefer to use pattern matching and handle the `Absent`
    /// case explicitly.
    ///
    /// # Examples
    ///
    /// ```
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let x = Value("air");
    /// assert_eq!(x.unwrap(), "air");
    /// ```
    ///
    /// ```{.should_panic}
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let x: Optional<&str> = Absent;
    /// assert_eq!(x.unwrap(), "air"); // fails
    /// ```
    pub fn unwrap(self) -> T {
        match self {
            Optional::Value(val) => val,
            Optional::Absent => panic!("called `Optional::unwrap()` on a `Absent` value"),
        }
    }

    /// Returns the contained value or computes it from a closure.
    ///
    /// # Examples
    ///
    /// ```
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let k = 10;
    /// assert_eq!(Value(4).unwrap_or_else(|| 2 * k), 4);
    /// assert_eq!(Absent.unwrap_or_else(|| 2 * k), 20);
    /// ```
    pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
        match self {
            Optional::Value(x) => x,
            Optional::Absent => f()
        }
    }

    /// Applies a function to the contained value or returns a default.  see
    /// [`std::option::Option<T>::map_or`](http://doc.rust-lang.org/std/option/enum.Option.html#method.map_or)
    pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
        match self {
            Optional::Value(v) => f(v),
            Optional::Absent => def,
        }
    }

    /// Converts from `Optional<T>` to `Optional<&mut T>`
    pub fn as_mut<'r>(&'r mut self) -> Optional<&'r mut T> {
        match *self {
            Optional::Value(ref mut x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    /// Converts from `Optional<T>` to `Optional<&T>`
    pub fn as_ref<'r>(&'r self) -> Optional<&'r T> {
        match *self {
            Optional::Value(ref x) => Optional::Value(x),
            Optional::Absent => Optional::Absent
        }
    }

    /// Returns `true` if the optional is a `Absent` value
    ///
    /// # Examples
    ///
    /// ```
    /// # use spaceapi::utils::Optional;
    /// # use spaceapi::utils::Optional::{Value,Absent};
    /// let x: Optional<u32> = Value(2);
    /// assert_eq!(x.is_absent(), false);
    ///
    /// let x: Optional<u32> = Absent;
    /// assert_eq!(x.is_absent(), true);
    /// ```
    pub fn is_absent(&self) -> bool {
        match *self {
            Optional::Absent => true,
            _ => false
        }
    }

}
<|endoftext|>