<commit_before>use crate::{private, Mapping, Value};
use std::fmt;
use std::ops;

/// A type that can be used to index into a `serde_yaml::Value`. See the `get`
/// and `get_mut` methods of `Value`.
///
/// This trait is sealed and cannot be implemented for types outside of
/// `serde_yaml`.
pub trait Index: private::Sealed {
    /// Return None if the key is not already in the sequence or object.
    #[doc(hidden)]
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;

    /// Return None if the key is not already in the sequence or object.
    #[doc(hidden)]
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;

    /// Panic if sequence index out of bounds. If key is not already in the object,
    /// insert it with a value of null. Panic if Value is a type that cannot be
    /// indexed into, except if Value is null then it can be treated as an empty
    /// object.
    #[doc(hidden)]
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
}

impl Index for usize {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match v {
            Value::Sequence(vec) => vec.get(*self),
            Value::Mapping(vec) => vec.get(&Value::Number((*self).into())),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match v {
            Value::Sequence(vec) => vec.get_mut(*self),
            Value::Mapping(vec) => vec.get_mut(&Value::Number((*self).into())),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, mut v: &'v mut Value) -> &'v mut Value {
        loop {
            match v {
                Value::Sequence(vec) => {
                    let len = vec.len();
                    return vec.get_mut(*self).unwrap_or_else(|| {
                        panic!(
                            "cannot access index {} of YAML sequence of length {}",
                            self, len
                        )
                    });
                }
                Value::Mapping(map) => {
                    let n = Value::Number((*self).into());
                    // TODO: use entry() once LinkedHashMap supports entry()
                    // https://github.com/contain-rs/linked-hash-map/issues/5
                    if !map.contains_key(&n) {
                        map.insert(n.clone(), Value::Null);
                    }
                    return map.get_mut(&n).unwrap();
                }
                Value::Tagged(tagged) => {
                    v = &mut tagged.value;
                }
                _ => panic!("cannot access index {} of YAML {}", self, Type(v)),
            }
        }
    }
}

impl Index for Value {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match v {
            Value::Mapping(map) => map.get(self),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match v {
            Value::Mapping(map) => map.get_mut(self),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        if let Value::Null = *v {
            let mut map = Mapping::new();
            map.insert(self.clone(), Value::Null);
            *v = Value::Mapping(map);
        }
        match v {
            Value::Mapping(map) => {
                // TODO: use entry() once LinkedHashMap supports entry()
                // https://github.com/contain-rs/linked-hash-map/issues/5
                if !map.contains_key(self) {
                    map.insert(self.clone(), Value::Null);
                }
                map.get_mut(self).unwrap()
            }
            _ => panic!("cannot access key {:?} in YAML {}", self, Type(v)),
        }
    }
}

impl Index for str {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        Value::String(self.into()).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        Value::String(self.into()).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        Value::String(self.into()).index_or_insert(v)
    }
}

impl Index for String {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        Value::String(self.clone()).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        Value::String(self.clone()).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        Value::String(self.clone()).index_or_insert(v)
    }
}

impl<'a, T> Index for &'a T
where
    T: ?Sized + Index,
{
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        (**self).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        (**self).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        (**self).index_or_insert(v)
    }
}

/// Used in panic messages.
struct Type<'a>(&'a Value);

impl<'a> fmt::Display for Type<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            Value::Null => formatter.write_str("null"),
            Value::Bool(_) => formatter.write_str("boolean"),
            Value::Number(_) => formatter.write_str("number"),
            Value::String(_) => formatter.write_str("string"),
            Value::Sequence(_) => formatter.write_str("sequence"),
            Value::Mapping(_) => formatter.write_str("mapping"),
            Value::Tagged(_) => unreachable!(),
        }
    }
}

// The usual semantics of Index is to panic on invalid indexing.
//
// That said, the usual semantics are for things like `Vec` and `BTreeMap` which
// have different use cases than Value. If you are working with a Vec, you know
// that you are working with a Vec and you can get the len of the Vec and make
// sure your indices are within bounds. The Value use cases are more
// loosey-goosey. You got some YAML from an endpoint and you want to pull values
// out of it. Outside of this Index impl, you already have the option of using
// `value.as_sequence()` and working with the Vec directly, or matching on
// `Value::Sequence` and getting the Vec directly. The Index impl means you can
// skip that and index directly into the thing using a concise syntax. You don't
// have to check the type, you don't have to check the len, it is all about what
// you expect the Value to look like.
//
// Basically the use cases that would be well served by panicking here are
// better served by using one of the other approaches: `get` and `get_mut`,
// `as_sequence`, or match. The value of this impl is that it adds a way of
// working with Value that is not well served by the existing approaches:
// concise and careless and sometimes that is exactly what you want.
impl<I> ops::Index<I> for Value
where
    I: Index,
{
    type Output = Value;

    /// Index into a `serde_yaml::Value` using the syntax `value[0]` or
    /// `value["k"]`.
    ///
    /// Returns `Value::Null` if the type of `self` does not match the type of
    /// the index, for example if the index is a string and `self` is a sequence
    /// or a number. Also returns `Value::Null` if the given key does not exist
    /// in the map or the given index is not within the bounds of the sequence.
    ///
    /// For retrieving deeply nested values, you should have a look at the
    /// `Value::pointer` method.
    ///
    /// # Examples
    ///
    /// ```
    /// # use serde_yaml::Value;
    /// #
    /// # fn main() -> serde_yaml::Result<()> {
    /// let data: serde_yaml::Value = serde_yaml::from_str(r#"{ x: { y: [z, zz] } }"#)?;
    ///
    /// assert_eq!(data["x"]["y"], serde_yaml::from_str::<Value>(r#"["z", "zz"]"#).unwrap());
    /// assert_eq!(data["x"]["y"][0], serde_yaml::from_str::<Value>(r#""z""#).unwrap());
    ///
    /// assert_eq!(data["a"], serde_yaml::from_str::<Value>(r#"null"#).unwrap()); // returns null for undefined values
    /// assert_eq!(data["a"]["b"], serde_yaml::from_str::<Value>(r#"null"#).unwrap()); // does not panic
    /// # Ok(())
    /// # }
    /// ```
    fn index(&self, index: I) -> &Value {
        static NULL: Value = Value::Null;
        index.index_into(self).unwrap_or(&NULL)
    }
}

impl<I> ops::IndexMut<I> for Value
where
    I: Index,
{
    /// Write into a `serde_yaml::Value` using the syntax `value[0] = ...` or
    /// `value["k"] = ...`.
    ///
    /// If the index is a number, the value must be a sequence of length bigger
    /// than the index. Indexing into a value that is not a sequence or a
    /// sequence that is too small will panic.
    ///
    /// If the index is a string, the value must be an object or null which is
    /// treated like an empty object. If the key is not already present in the
    /// object, it will be inserted with a value of null. Indexing into a value
    /// that is neither an object nor null will panic.
    ///
    /// # Examples
    ///
    /// ```
    /// # fn main() -> serde_yaml::Result<()> {
    /// let mut data: serde_yaml::Value = serde_yaml::from_str(r#"{x: 0}"#)?;
    ///
    /// // replace an existing key
    /// data["x"] = serde_yaml::from_str(r#"1"#)?;
    ///
    /// // insert a new key
    /// data["y"] = serde_yaml::from_str(r#"[false, false, false]"#)?;
    ///
    /// // replace a value in a sequence
    /// data["y"][0] = serde_yaml::from_str(r#"true"#)?;
    ///
    /// // inserted a deeply nested key
    /// data["a"]["b"]["c"]["d"] = serde_yaml::from_str(r#"true"#)?;
    ///
    /// println!("{:?}", data);
    /// # Ok(())
    /// # }
    /// ```
    fn index_mut(&mut self, index: I) -> &mut Value {
        index.index_or_insert(self)
    }
}
<commit_msg>Use indexmap's Entry API for simpler indexing<commit_after>use crate::{private, Mapping, Value};
use std::fmt;
use std::ops;

/// A type that can be used to index into a `serde_yaml::Value`. See the `get`
/// and `get_mut` methods of `Value`.
///
/// This trait is sealed and cannot be implemented for types outside of
/// `serde_yaml`.
pub trait Index: private::Sealed {
    /// Return None if the key is not already in the sequence or object.
    #[doc(hidden)]
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;

    /// Return None if the key is not already in the sequence or object.
    #[doc(hidden)]
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;

    /// Panic if sequence index out of bounds. If key is not already in the object,
    /// insert it with a value of null. Panic if Value is a type that cannot be
    /// indexed into, except if Value is null then it can be treated as an empty
    /// object.
    #[doc(hidden)]
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
}

impl Index for usize {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match v {
            Value::Sequence(vec) => vec.get(*self),
            Value::Mapping(vec) => vec.get(&Value::Number((*self).into())),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match v {
            Value::Sequence(vec) => vec.get_mut(*self),
            Value::Mapping(vec) => vec.get_mut(&Value::Number((*self).into())),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, mut v: &'v mut Value) -> &'v mut Value {
        loop {
            match v {
                Value::Sequence(vec) => {
                    let len = vec.len();
                    return vec.get_mut(*self).unwrap_or_else(|| {
                        panic!(
                            "cannot access index {} of YAML sequence of length {}",
                            self, len
                        )
                    });
                }
                Value::Mapping(map) => {
                    let n = Value::Number((*self).into());
                    return map.entry(n).or_insert(Value::Null);
                }
                Value::Tagged(tagged) => {
                    v = &mut tagged.value;
                }
                _ => panic!("cannot access index {} of YAML {}", self, Type(v)),
            }
        }
    }
}

impl Index for Value {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match v {
            Value::Mapping(map) => map.get(self),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match v {
            Value::Mapping(map) => map.get_mut(self),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        if let Value::Null = *v {
            let mut map = Mapping::new();
            map.insert(self.clone(), Value::Null);
            *v = Value::Mapping(map);
        }
        match v {
            Value::Mapping(map) => map.entry(self.clone()).or_insert(Value::Null),
            _ => panic!("cannot access key {:?} in YAML {}", self, Type(v)),
        }
    }
}

impl Index for str {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        Value::String(self.into()).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        Value::String(self.into()).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        Value::String(self.into()).index_or_insert(v)
    }
}

impl Index for String {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        Value::String(self.clone()).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        Value::String(self.clone()).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        Value::String(self.clone()).index_or_insert(v)
    }
}

impl<'a, T> Index for &'a T
where
    T: ?Sized + Index,
{
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        (**self).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        (**self).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        (**self).index_or_insert(v)
    }
}

/// Used in panic messages.
struct Type<'a>(&'a Value);

impl<'a> fmt::Display for Type<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            Value::Null => formatter.write_str("null"),
            Value::Bool(_) => formatter.write_str("boolean"),
            Value::Number(_) => formatter.write_str("number"),
            Value::String(_) => formatter.write_str("string"),
            Value::Sequence(_) => formatter.write_str("sequence"),
            Value::Mapping(_) => formatter.write_str("mapping"),
            Value::Tagged(_) => unreachable!(),
        }
    }
}

// The usual semantics of Index is to panic on invalid indexing.
//
// That said, the usual semantics are for things like `Vec` and `BTreeMap` which
// have different use cases than Value. If you are working with a Vec, you know
// that you are working with a Vec and you can get the len of the Vec and make
// sure your indices are within bounds. The Value use cases are more
// loosey-goosey. You got some YAML from an endpoint and you want to pull values
// out of it. Outside of this Index impl, you already have the option of using
// `value.as_sequence()` and working with the Vec directly, or matching on
// `Value::Sequence` and getting the Vec directly. The Index impl means you can
// skip that and index directly into the thing using a concise syntax. You don't
// have to check the type, you don't have to check the len, it is all about what
// you expect the Value to look like.
//
// Basically the use cases that would be well served by panicking here are
// better served by using one of the other approaches: `get` and `get_mut`,
// `as_sequence`, or match. The value of this impl is that it adds a way of
// working with Value that is not well served by the existing approaches:
// concise and careless and sometimes that is exactly what you want.
impl<I> ops::Index<I> for Value
where
    I: Index,
{
    type Output = Value;

    /// Index into a `serde_yaml::Value` using the syntax `value[0]` or
    /// `value["k"]`.
    ///
    /// Returns `Value::Null` if the type of `self` does not match the type of
    /// the index, for example if the index is a string and `self` is a sequence
    /// or a number. Also returns `Value::Null` if the given key does not exist
    /// in the map or the given index is not within the bounds of the sequence.
    ///
    /// For retrieving deeply nested values, you should have a look at the
    /// `Value::pointer` method.
    ///
    /// # Examples
    ///
    /// ```
    /// # use serde_yaml::Value;
    /// #
    /// # fn main() -> serde_yaml::Result<()> {
    /// let data: serde_yaml::Value = serde_yaml::from_str(r#"{ x: { y: [z, zz] } }"#)?;
    ///
    /// assert_eq!(data["x"]["y"], serde_yaml::from_str::<Value>(r#"["z", "zz"]"#).unwrap());
    /// assert_eq!(data["x"]["y"][0], serde_yaml::from_str::<Value>(r#""z""#).unwrap());
    ///
    /// assert_eq!(data["a"], serde_yaml::from_str::<Value>(r#"null"#).unwrap()); // returns null for undefined values
    /// assert_eq!(data["a"]["b"], serde_yaml::from_str::<Value>(r#"null"#).unwrap()); // does not panic
    /// # Ok(())
    /// # }
    /// ```
    fn index(&self, index: I) -> &Value {
        static NULL: Value = Value::Null;
        index.index_into(self).unwrap_or(&NULL)
    }
}

impl<I> ops::IndexMut<I> for Value
where
    I: Index,
{
    /// Write into a `serde_yaml::Value` using the syntax `value[0] = ...` or
    /// `value["k"] = ...`.
    ///
    /// If the index is a number, the value must be a sequence of length bigger
    /// than the index. Indexing into a value that is not a sequence or a
    /// sequence that is too small will panic.
    ///
    /// If the index is a string, the value must be an object or null which is
    /// treated like an empty object. If the key is not already present in the
    /// object, it will be inserted with a value of null. Indexing into a value
    /// that is neither an object nor null will panic.
    ///
    /// # Examples
    ///
    /// ```
    /// # fn main() -> serde_yaml::Result<()> {
    /// let mut data: serde_yaml::Value = serde_yaml::from_str(r#"{x: 0}"#)?;
    ///
    /// // replace an existing key
    /// data["x"] = serde_yaml::from_str(r#"1"#)?;
    ///
    /// // insert a new key
    /// data["y"] = serde_yaml::from_str(r#"[false, false, false]"#)?;
    ///
    /// // replace a value in a sequence
    /// data["y"][0] = serde_yaml::from_str(r#"true"#)?;
    ///
    /// // inserted a deeply nested key
    /// data["a"]["b"]["c"]["d"] = serde_yaml::from_str(r#"true"#)?;
    ///
    /// println!("{:?}", data);
    /// # Ok(())
    /// # }
    /// ```
    fn index_mut(&mut self, index: I) -> &mut Value {
        index.index_or_insert(self)
    }
}
<|endoftext|>


<commit_before>use crate::mapping::Entry;
use crate::{private, Mapping, Value};
use std::fmt;
use std::ops;

/// A type that can be used to index into a `serde_yaml::Value`. See the `get`
/// and `get_mut` methods of `Value`.
///
/// This trait is sealed and cannot be implemented for types outside of
/// `serde_yaml`.
pub trait Index: private::Sealed {
    /// Return None if the key is not already in the sequence or object.
    #[doc(hidden)]
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;

    /// Return None if the key is not already in the sequence or object.
    #[doc(hidden)]
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;

    /// Panic if sequence index out of bounds. If key is not already in the object,
    /// insert it with a value of null. Panic if Value is a type that cannot be
    /// indexed into, except if Value is null then it can be treated as an empty
    /// object.
    #[doc(hidden)]
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
}

impl Index for usize {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match v.untag_ref() {
            Value::Sequence(vec) => vec.get(*self),
            Value::Mapping(vec) => vec.get(&Value::Number((*self).into())),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match v.untag_mut() {
            Value::Sequence(vec) => vec.get_mut(*self),
            Value::Mapping(vec) => vec.get_mut(&Value::Number((*self).into())),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, mut v: &'v mut Value) -> &'v mut Value {
        loop {
            match v {
                Value::Sequence(vec) => {
                    let len = vec.len();
                    return vec.get_mut(*self).unwrap_or_else(|| {
                        panic!(
                            "cannot access index {} of YAML sequence of length {}",
                            self, len
                        )
                    });
                }
                Value::Mapping(map) => {
                    let n = Value::Number((*self).into());
                    return map.entry(n).or_insert(Value::Null);
                }
                Value::Tagged(tagged) => v = &mut tagged.value,
                _ => panic!("cannot access index {} of YAML {}", self, Type(v)),
            }
        }
    }
}

impl Index for Value {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match v.untag_ref() {
            Value::Mapping(map) => map.get(self),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match v.untag_mut() {
            Value::Mapping(map) => map.get_mut(self),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, mut v: &'v mut Value) -> &'v mut Value {
        if let Value::Null = *v {
            *v = Value::Mapping(Mapping::new());
            return match v {
                Value::Mapping(map) => match map.entry(self.clone()) {
                    Entry::Vacant(entry) => entry.insert(Value::Null),
                    Entry::Occupied(_) => unreachable!(),
                },
                _ => unreachable!(),
            };
        }
        loop {
            match v {
                Value::Mapping(map) => return map.entry(self.clone()).or_insert(Value::Null),
                Value::Tagged(tagged) => v = &mut tagged.value,
                _ => panic!("cannot access key {:?} in YAML {}", self, Type(v)),
            }
        }
    }
}

impl Index for str {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        Value::String(self.into()).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        Value::String(self.into()).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        Value::String(self.into()).index_or_insert(v)
    }
}

impl Index for String {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        Value::String(self.clone()).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        Value::String(self.clone()).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        Value::String(self.clone()).index_or_insert(v)
    }
}

impl<'a, T> Index for &'a T
where
    T: ?Sized + Index,
{
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        (**self).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        (**self).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        (**self).index_or_insert(v)
    }
}

/// Used in panic messages.
struct Type<'a>(&'a Value);

impl<'a> fmt::Display for Type<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            Value::Null => formatter.write_str("null"),
            Value::Bool(_) => formatter.write_str("boolean"),
            Value::Number(_) => formatter.write_str("number"),
            Value::String(_) => formatter.write_str("string"),
            Value::Sequence(_) => formatter.write_str("sequence"),
            Value::Mapping(_) => formatter.write_str("mapping"),
            Value::Tagged(_) => unreachable!(),
        }
    }
}

// The usual semantics of Index is to panic on invalid indexing.
//
// That said, the usual semantics are for things like `Vec` and `BTreeMap` which
// have different use cases than Value. If you are working with a Vec, you know
// that you are working with a Vec and you can get the len of the Vec and make
// sure your indices are within bounds. The Value use cases are more
// loosey-goosey. You got some YAML from an endpoint and you want to pull values
// out of it. Outside of this Index impl, you already have the option of using
// `value.as_sequence()` and working with the Vec directly, or matching on
// `Value::Sequence` and getting the Vec directly. The Index impl means you can
// skip that and index directly into the thing using a concise syntax. You don't
// have to check the type, you don't have to check the len, it is all about what
// you expect the Value to look like.
//
// Basically the use cases that would be well served by panicking here are
// better served by using one of the other approaches: `get` and `get_mut`,
// `as_sequence`, or match. The value of this impl is that it adds a way of
// working with Value that is not well served by the existing approaches:
// concise and careless and sometimes that is exactly what you want.
impl<I> ops::Index<I> for Value
where
    I: Index,
{
    type Output = Value;

    /// Index into a `serde_yaml::Value` using the syntax `value[0]` or
    /// `value["k"]`.
    ///
    /// Returns `Value::Null` if the type of `self` does not match the type of
    /// the index, for example if the index is a string and `self` is a sequence
    /// or a number. Also returns `Value::Null` if the given key does not exist
    /// in the map or the given index is not within the bounds of the sequence.
    ///
    /// For retrieving deeply nested values, you should have a look at the
    /// `Value::pointer` method.
    ///
    /// # Examples
    ///
    /// ```
    /// # use serde_yaml::Value;
    /// #
    /// # fn main() -> serde_yaml::Result<()> {
    /// let data: serde_yaml::Value = serde_yaml::from_str(r#"{ x: { y: [z, zz] } }"#)?;
    ///
    /// assert_eq!(data["x"]["y"], serde_yaml::from_str::<Value>(r#"["z", "zz"]"#).unwrap());
    /// assert_eq!(data["x"]["y"][0], serde_yaml::from_str::<Value>(r#""z""#).unwrap());
    ///
    /// assert_eq!(data["a"], serde_yaml::from_str::<Value>(r#"null"#).unwrap()); // returns null for undefined values
    /// assert_eq!(data["a"]["b"], serde_yaml::from_str::<Value>(r#"null"#).unwrap()); // does not panic
    /// # Ok(())
    /// # }
    /// ```
    fn index(&self, index: I) -> &Value {
        static NULL: Value = Value::Null;
        index.index_into(self).unwrap_or(&NULL)
    }
}

impl<I> ops::IndexMut<I> for Value
where
    I: Index,
{
    /// Write into a `serde_yaml::Value` using the syntax `value[0] = ...` or
    /// `value["k"] = ...`.
    ///
    /// If the index is a number, the value must be a sequence of length bigger
    /// than the index. Indexing into a value that is not a sequence or a
    /// sequence that is too small will panic.
    ///
    /// If the index is a string, the value must be an object or null which is
    /// treated like an empty object. If the key is not already present in the
    /// object, it will be inserted with a value of null. Indexing into a value
    /// that is neither an object nor null will panic.
    ///
    /// # Examples
    ///
    /// ```
    /// # fn main() -> serde_yaml::Result<()> {
    /// let mut data: serde_yaml::Value = serde_yaml::from_str(r#"{x: 0}"#)?;
    ///
    /// // replace an existing key
    /// data["x"] = serde_yaml::from_str(r#"1"#)?;
    ///
    /// // insert a new key
    /// data["y"] = serde_yaml::from_str(r#"[false, false, false]"#)?;
    ///
    /// // replace a value in a sequence
    /// data["y"][0] = serde_yaml::from_str(r#"true"#)?;
    ///
    /// // inserted a deeply nested key
    /// data["a"]["b"]["c"]["d"] = serde_yaml::from_str(r#"true"#)?;
    ///
    /// println!("{:?}", data);
    /// # Ok(())
    /// # }
    /// ```
    fn index_mut(&mut self, index: I) -> &mut Value {
        index.index_or_insert(self)
    }
}
<commit_msg>Eliminate allocation from Value indexing by str<commit_after>use crate::mapping::Entry;
use crate::{mapping, private, Mapping, Value};
use std::fmt::{self, Debug};
use std::ops;

/// A type that can be used to index into a `serde_yaml::Value`. See the `get`
/// and `get_mut` methods of `Value`.
///
/// This trait is sealed and cannot be implemented for types outside of
/// `serde_yaml`.
pub trait Index: private::Sealed {
    /// Return None if the key is not already in the sequence or object.
    #[doc(hidden)]
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;

    /// Return None if the key is not already in the sequence or object.
    #[doc(hidden)]
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;

    /// Panic if sequence index out of bounds. If key is not already in the object,
    /// insert it with a value of null. Panic if Value is a type that cannot be
    /// indexed into, except if Value is null then it can be treated as an empty
    /// object.
    #[doc(hidden)]
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
}

impl Index for usize {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        match v.untag_ref() {
            Value::Sequence(vec) => vec.get(*self),
            Value::Mapping(vec) => vec.get(&Value::Number((*self).into())),
            _ => None,
        }
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        match v.untag_mut() {
            Value::Sequence(vec) => vec.get_mut(*self),
            Value::Mapping(vec) => vec.get_mut(&Value::Number((*self).into())),
            _ => None,
        }
    }
    fn index_or_insert<'v>(&self, mut v: &'v mut Value) -> &'v mut Value {
        loop {
            match v {
                Value::Sequence(vec) => {
                    let len = vec.len();
                    return vec.get_mut(*self).unwrap_or_else(|| {
                        panic!(
                            "cannot access index {} of YAML sequence of length {}",
                            self, len
                        )
                    });
                }
                Value::Mapping(map) => {
                    let n = Value::Number((*self).into());
                    return map.entry(n).or_insert(Value::Null);
                }
                Value::Tagged(tagged) => v = &mut tagged.value,
                _ => panic!("cannot access index {} of YAML {}", self, Type(v)),
            }
        }
    }
}

fn index_into_mapping<'v, I>(index: &I, v: &'v Value) -> Option<&'v Value>
where
    I: ?Sized + mapping::Index,
{
    match v.untag_ref() {
        Value::Mapping(map) => map.get(index),
        _ => None,
    }
}

fn index_into_mut_mapping<'v, I>(index: &I, v: &'v mut Value) -> Option<&'v mut Value>
where
    I: ?Sized + mapping::Index,
{
    match v.untag_mut() {
        Value::Mapping(map) => map.get_mut(index),
        _ => None,
    }
}

fn index_or_insert_mapping<'v, I>(index: &I, mut v: &'v mut Value) -> &'v mut Value
where
    I: ?Sized + mapping::Index + ToOwned + Debug,
    Value: From<I::Owned>,
{
    if let Value::Null = *v {
        *v = Value::Mapping(Mapping::new());
        return match v {
            Value::Mapping(map) => match map.entry(index.to_owned().into()) {
                Entry::Vacant(entry) => entry.insert(Value::Null),
                Entry::Occupied(_) => unreachable!(),
            },
            _ => unreachable!(),
        };
    }
    loop {
        match v {
            Value::Mapping(map) => {
                return map.entry(index.to_owned().into()).or_insert(Value::Null);
            }
            Value::Tagged(tagged) => v = &mut tagged.value,
            _ => panic!("cannot access key {:?} in YAML {}", index, Type(v)),
        }
    }
}

impl Index for Value {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        index_into_mapping(self, v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        index_into_mut_mapping(self, v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        index_or_insert_mapping(self, v)
    }
}

impl Index for str {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        index_into_mapping(self, v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        index_into_mut_mapping(self, v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        index_or_insert_mapping(self, v)
    }
}

impl Index for String {
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        self.as_str().index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        self.as_str().index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        self.as_str().index_or_insert(v)
    }
}

impl<'a, T> Index for &'a T
where
    T: ?Sized + Index,
{
    fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
        (**self).index_into(v)
    }
    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
        (**self).index_into_mut(v)
    }
    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
        (**self).index_or_insert(v)
    }
}

/// Used in panic messages.
struct Type<'a>(&'a Value);

impl<'a> fmt::Display for Type<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            Value::Null => formatter.write_str("null"),
            Value::Bool(_) => formatter.write_str("boolean"),
            Value::Number(_) => formatter.write_str("number"),
            Value::String(_) => formatter.write_str("string"),
            Value::Sequence(_) => formatter.write_str("sequence"),
            Value::Mapping(_) => formatter.write_str("mapping"),
            Value::Tagged(_) => unreachable!(),
        }
    }
}

// The usual semantics of Index is to panic on invalid indexing.
//
// That said, the usual semantics are for things like `Vec` and `BTreeMap` which
// have different use cases than Value. If you are working with a Vec, you know
// that you are working with a Vec and you can get the len of the Vec and make
// sure your indices are within bounds. The Value use cases are more
// loosey-goosey. You got some YAML from an endpoint and you want to pull values
// out of it. Outside of this Index impl, you already have the option of using
// `value.as_sequence()` and working with the Vec directly, or matching on
// `Value::Sequence` and getting the Vec directly. The Index impl means you can
// skip that and index directly into the thing using a concise syntax. You don't
// have to check the type, you don't have to check the len, it is all about what
// you expect the Value to look like.
//
// Basically the use cases that would be well served by panicking here are
// better served by using one of the other approaches: `get` and `get_mut`,
// `as_sequence`, or match. The value of this impl is that it adds a way of
// working with Value that is not well served by the existing approaches:
// concise and careless and sometimes that is exactly what you want.
impl<I> ops::Index<I> for Value
where
    I: Index,
{
    type Output = Value;

    /// Index into a `serde_yaml::Value` using the syntax `value[0]` or
    /// `value["k"]`.
    ///
    /// Returns `Value::Null` if the type of `self` does not match the type of
    /// the index, for example if the index is a string and `self` is a sequence
    /// or a number. Also returns `Value::Null` if the given key does not exist
    /// in the map or the given index is not within the bounds of the sequence.
    ///
    /// For retrieving deeply nested values, you should have a look at the
    /// `Value::pointer` method.
    ///
    /// # Examples
    ///
    /// ```
    /// # use serde_yaml::Value;
    /// #
    /// # fn main() -> serde_yaml::Result<()> {
    /// let data: serde_yaml::Value = serde_yaml::from_str(r#"{ x: { y: [z, zz] } }"#)?;
    ///
    /// assert_eq!(data["x"]["y"], serde_yaml::from_str::<Value>(r#"["z", "zz"]"#).unwrap());
    /// assert_eq!(data["x"]["y"][0], serde_yaml::from_str::<Value>(r#""z""#).unwrap());
    ///
    /// assert_eq!(data["a"], serde_yaml::from_str::<Value>(r#"null"#).unwrap()); // returns null for undefined values
    /// assert_eq!(data["a"]["b"], serde_yaml::from_str::<Value>(r#"null"#).unwrap()); // does not panic
    /// # Ok(())
    /// # }
    /// ```
    fn index(&self, index: I) -> &Value {
        static NULL: Value = Value::Null;
        index.index_into(self).unwrap_or(&NULL)
    }
}

impl<I> ops::IndexMut<I> for Value
where
    I: Index,
{
    /// Write into a `serde_yaml::Value` using the syntax `value[0] = ...` or
    /// `value["k"] = ...`.
    ///
    /// If the index is a number, the value must be a sequence of length bigger
    /// than the index. Indexing into a value that is not a sequence or a
    /// sequence that is too small will panic.
    ///
    /// If the index is a string, the value must be an object or null which is
    /// treated like an empty object. If the key is not already present in the
    /// object, it will be inserted with a value of null. Indexing into a value
    /// that is neither an object nor null will panic.
    ///
    /// # Examples
    ///
    /// ```
    /// # fn main() -> serde_yaml::Result<()> {
    /// let mut data: serde_yaml::Value = serde_yaml::from_str(r#"{x: 0}"#)?;
    ///
    /// // replace an existing key
    /// data["x"] = serde_yaml::from_str(r#"1"#)?;
    ///
    /// // insert a new key
    /// data["y"] = serde_yaml::from_str(r#"[false, false, false]"#)?;
    ///
    /// // replace a value in a sequence
    /// data["y"][0] = serde_yaml::from_str(r#"true"#)?;
    ///
    /// // inserted a deeply nested key
    /// data["a"]["b"]["c"]["d"] = serde_yaml::from_str(r#"true"#)?;
    ///
    /// println!("{:?}", data);
    /// # Ok(())
    /// # }
    /// ```
    fn index_mut(&mut self, index: I) -> &mut Value {
        index.index_or_insert(self)
    }
}
<|endoftext|>


<commit_before>
//! Glyph caching

use error::Error;
use freetype::ffi;
use freetype;
use freetype::error::Error::MissingFontField;
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use graphics;

use Texture;

/// The type alias for the font size.
pub type FontSize = u32;

/// The type alias for font characters.
pub type Character = graphics::character::Character<Texture>;

/// A struct used for caching rendered font.
pub struct GlyphCache {
    /// The font face.
    pub face: freetype::Face,
    data: HashMap<FontSize, HashMap<char, Character>>,
}

impl GlyphCache {

    /// Constructor for a GlyphCache.
    pub fn new(font: &Path) -> Result<GlyphCache, Error> {
        let freetype = match freetype::Library::init() {
            Ok(freetype) => freetype,
            Err(why) => return Err(Error::FreetypeError(why)),
        };
        let font_str = match font.as_str() {
            Some(font_str) => font_str,
            None => return Err(Error::FreetypeError(MissingFontField)),
        };
        let face = match freetype.new_face(font_str, 0) {
            Ok(face) => face,
            Err(why) => return Err(Error::FreetypeError(why)),
        };
        Ok(GlyphCache {
            face: face,
            data: HashMap::new(),
        })
    }

    /// Load a `Character` from a given `FontSize` and `char`.
    fn load_character(&mut self, size: FontSize, ch: char) {
        // Don't load glyph twice
        if self.data.get(&size)
            .map(|entry| entry.contains_key(&ch))
            .unwrap_or(false) { return; }

        self.face.set_pixel_sizes(0, size).unwrap();
        self.face.load_char(ch as ffi::FT_ULong, freetype::face::DEFAULT).unwrap();
        let glyph = self.face.glyph().get_glyph().unwrap();
        let bitmap_glyph = glyph.to_bitmap(freetype::render_mode::RenderMode::Normal, None)
            .unwrap();
        let bitmap = bitmap_glyph.bitmap();
        let texture = Texture::from_memory_alpha(bitmap.buffer(),
                                                 bitmap.width() as u32,
                                                 bitmap.rows() as u32).unwrap();
        let glyph_size = glyph.advance();
        self.data[size].insert(ch, Character {
            offset: [
                    bitmap_glyph.left() as f64,
                    bitmap_glyph.top() as f64
                ],
            size: [
                    (glyph_size.x >> 16) as f64,
                    (glyph_size.y >> 16) as f64
                ],
            texture: texture,
        });
    }

    /// Load all characters in the `chars` iterator for `size`
    pub fn preload_chars<I: Iterator<char>>(&mut self, size: FontSize, mut chars: I) {
        for ch in chars {
            self.load_character(size, ch);
        }
    }

    /// Load all the printable ASCII characters for `size`. Includes space.
    pub fn preload_printable_ascii(&mut self, size: FontSize) {
        // [0x20, 0x7F) contains all printable ASCII characters ([' ', '~'])
        self.preload_chars(size, range(0x20u8, 0x7F).map(|ch| ch as char));
    }
}

impl graphics::character::CharacterCache<Texture> for GlyphCache {
    fn character(&mut self, size: FontSize, ch: char) -> &Character {
        match {
            match self.data.entry(size) {
                Vacant(entry) => entry.set(HashMap::new()),
                Occupied(entry) => entry.into_mut(),
            }
        }.contains_key(&ch) {
            true => &self.data[size][ch],
            false => { self.load_character(size, ch); &self.data[size][ch] }
        }
    }
}
<commit_msg>Implement `GlyphCache::opt_character()`<commit_after>
//! Glyph caching

use error::Error;
use freetype::ffi;
use freetype;
use freetype::error::Error::MissingFontField;
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use graphics;

use Texture;

/// The type alias for the font size.
pub type FontSize = u32;

/// The type alias for font characters.
pub type Character = graphics::character::Character<Texture>;

/// A struct used for caching rendered font.
pub struct GlyphCache {
    /// The font face.
    pub face: freetype::Face,
    data: HashMap<FontSize, HashMap<char, Character>>,
}

impl GlyphCache {

    /// Constructor for a GlyphCache.
    pub fn new(font: &Path) -> Result<GlyphCache, Error> {
        let freetype = match freetype::Library::init() {
            Ok(freetype) => freetype,
            Err(why) => return Err(Error::FreetypeError(why)),
        };
        let font_str = match font.as_str() {
            Some(font_str) => font_str,
            None => return Err(Error::FreetypeError(MissingFontField)),
        };
        let face = match freetype.new_face(font_str, 0) {
            Ok(face) => face,
            Err(why) => return Err(Error::FreetypeError(why)),
        };
        Ok(GlyphCache {
            face: face,
            data: HashMap::new(),
        })
    }

    /// Load a `Character` from a given `FontSize` and `char`.
    fn load_character(&mut self, size: FontSize, ch: char) {
        // Don't load glyph twice
        if self.data.get(&size)
            .map(|entry| entry.contains_key(&ch))
            .unwrap_or(false) { return; }

        self.face.set_pixel_sizes(0, size).unwrap();
        self.face.load_char(ch as ffi::FT_ULong, freetype::face::DEFAULT).unwrap();
        let glyph = self.face.glyph().get_glyph().unwrap();
        let bitmap_glyph = glyph.to_bitmap(freetype::render_mode::RenderMode::Normal, None)
            .unwrap();
        let bitmap = bitmap_glyph.bitmap();
        let texture = Texture::from_memory_alpha(bitmap.buffer(),
                                                 bitmap.width() as u32,
                                                 bitmap.rows() as u32).unwrap();
        let glyph_size = glyph.advance();
        self.data[size].insert(ch, Character {
            offset: [
                    bitmap_glyph.left() as f64,
                    bitmap_glyph.top() as f64
                ],
            size: [
                    (glyph_size.x >> 16) as f64,
                    (glyph_size.y >> 16) as f64
                ],
            texture: texture,
        });
    }

    /// Load all characters in the `chars` iterator for `size`
    pub fn preload_chars<I: Iterator<char>>(&mut self, size: FontSize, mut chars: I) {
        for ch in chars {
            self.load_character(size, ch);
        }
    }

    /// Load all the printable ASCII characters for `size`. Includes space.
    pub fn preload_printable_ascii(&mut self, size: FontSize) {
        // [0x20, 0x7F) contains all printable ASCII characters ([' ', '~'])
        self.preload_chars(size, range(0x20u8, 0x7F).map(|ch| ch as char));
    }

    /// Return `ch` for `size` if it's already cached. Don't load.
    /// See the `preload_*` functions.
    pub fn opt_character(&self, size: FontSize, ch: char) -> Option<&Character> {
        self.data.get(&size).and_then(|entry| entry.get(&ch))
    }
}

impl graphics::character::CharacterCache<Texture> for GlyphCache {
    fn character(&mut self, size: FontSize, ch: char) -> &Character {
        match {
            match self.data.entry(size) {
                Vacant(entry) => entry.set(HashMap::new()),
                Occupied(entry) => entry.into_mut(),
            }
        }.contains_key(&ch) {
            true => &self.data[size][ch],
            false => { self.load_character(size, ch); &self.data[size][ch] }
        }
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;

use ast::*;
use unit_graph::UnitGraph;
use symbols::SymbolTable;

#[derive(Debug, Clone)]
pub enum DeclError<'a> {
    UndeclaredUnit {
        name: UnitName<'a>,
        span: Span<'a>,
    },
    DuplicateUnitDecl {
        name: UnitName<'a>,
        span: Span<'a>,
    },
    UnknownAttribute {
        name: Ident<'a>,
        span: Span<'a>,
    },
}

#[derive(Debug, Clone, Default)]
pub struct Interpreter<'a> {
    units: UnitGraph<'a>,
    symbols: SymbolTable<'a>,
}

impl<'a> Interpreter<'a> {
    /// Load declarations into the global scope of the interpreter
    pub fn load_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        // We need to do this in several passes in order to satisfy the potential items each type
        // of declaration might need.

        // Macros need to be expanded before anything else
        let program = self.expand_macros(Cow::Borrowed(program))?;

        self.load_unit_decls(&program)?;
        // Constants need units so we can verify their declared unit if provided.
        self.load_const_decls(&program)?;
        // Conversions need both units and constants (+ const functions) so we can evaluate their
        // declared ratios
        self.load_conversion_decls(&program)?;

        // Functions will need the units loaded so we can verify that their parameter and return
        // units are declared. We also check the body of each function at this point to make sure
        // all unit conversions are mathematically valid so we need those loaded as well.
        self.load_fn_decls(&program)?;

        Ok(())
    }

    /// Expand any macros used in the program
    ///
    /// Any declared macros will be collected along the way and used as necessary while
    /// recursively expanding the macros
    fn expand_macros<'c>(&self, program: Cow<'c, Program<'a>>) -> Result<Cow<'c, Program<'a>>, DeclError<'a>> {
        // By using Cow here, we avoid an unnecessary clone if the program has no macros

        for decl in &program.decls {
            //TODO: Macro declarations will be processed here eventually

            if let Decl::MacroInvoke(_) = decl {
                unimplemented!();
            }
        }
        Ok(program)
    }

    /// Load declared units into the global unit graph of the interpreter
    fn load_unit_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            if let &Decl::UnitDecl(UnitDecl {ref attrs, unit_name, ref alias_for, span}) = decl {
                //TODO: insert the unit into the unit graph and add the single conversion from
                //unitless to the unit

                for &Attribute {name, tokens: _, span} in attrs {
                    match name {
                        "prefix" => {}, //TODO
                        _ => return Err(DeclError::UnknownAttribute {name, span}),
                    }
                }

                self.units.insert_unit(unit_name, span)
                    .map_err(|_| DeclError::DuplicateUnitDecl {name: unit_name, span})?;

                if let Some(_unit) = alias_for {
                    unimplemented!();
                }
            }
        }
        Ok(())
    }

    /// Load declared constants and `const fn`s into the global scope of the interpreter
    fn load_const_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            //TODO: const fn declarations will be processed and unit checked here eventually

            if let Decl::Constant(_) = decl {
                unimplemented!();
            }
        }
        Ok(())
    }

    /// Load unit conversions and evaluate any const exprs found within them
    fn load_conversion_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            if let Decl::ConversionDecl(_) = decl {
                unimplemented!();
            }
        }
        Ok(())
    }

    /// Load function declarations into the global scope and check their bodies to ensure that any
    /// conversions are valid
    fn load_fn_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            if let Decl::Function(_) = decl {
                unimplemented!();
            }
        }
        Ok(())
    }
}

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

    #[test]
    #[ignore] //TODO: Unignore once implemented
    fn multitype_function() {
        let input = r#"
        #[unit]
        #[converter]
        fn(x '_) -> 'deg { x }
        "#;
        let program = parse_program(input).unwrap();

        let mut inter = Interpreter::default();
        inter.load_decls(&program).unwrap_err();
    }
}
<commit_msg>Aliases need to be processed after all the units have been declared--during conversion collection<commit_after>use std::borrow::Cow;

use ast::*;
use unit_graph::UnitGraph;
use symbols::SymbolTable;

#[derive(Debug, Clone)]
pub enum DeclError<'a> {
    UndeclaredUnit {
        name: UnitName<'a>,
        span: Span<'a>,
    },
    DuplicateUnitDecl {
        name: UnitName<'a>,
        span: Span<'a>,
    },
    UnknownAttribute {
        name: Ident<'a>,
        span: Span<'a>,
    },
}

#[derive(Debug, Clone, Default)]
pub struct Interpreter<'a> {
    units: UnitGraph<'a>,
    symbols: SymbolTable<'a>,
}

impl<'a> Interpreter<'a> {
    /// Load declarations into the global scope of the interpreter
    pub fn load_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        // We need to do this in several passes in order to satisfy the potential items each type
        // of declaration might need.

        // Macros need to be expanded before anything else
        let program = self.expand_macros(Cow::Borrowed(program))?;

        self.load_unit_decls(&program)?;
        // Constants need units so we can verify their declared unit if provided.
        self.load_const_decls(&program)?;
        // Conversions need both units and constants (+ const functions) so we can evaluate their
        // declared ratios
        self.load_conversion_decls(&program)?;

        // Functions will need the units loaded so we can verify that their parameter and return
        // units are declared. We also check the body of each function at this point to make sure
        // all unit conversions are mathematically valid so we need those loaded as well.
        self.load_fn_decls(&program)?;

        Ok(())
    }

    /// Expand any macros used in the program
    ///
    /// Any declared macros will be collected along the way and used as necessary while
    /// recursively expanding the macros
    fn expand_macros<'c>(&self, program: Cow<'c, Program<'a>>) -> Result<Cow<'c, Program<'a>>, DeclError<'a>> {
        // By using Cow here, we avoid an unnecessary clone if the program has no macros

        for decl in &program.decls {
            //TODO: Macro declarations will be processed here eventually

            if let Decl::MacroInvoke(_) = decl {
                unimplemented!();
            }
        }
        Ok(program)
    }

    /// Load declared units into the global unit graph of the interpreter
    fn load_unit_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            if let &Decl::UnitDecl(UnitDecl {ref attrs, unit_name, span, ..}) = decl {
                //TODO: insert the unit into the unit graph and add the single conversion from
                //unitless to the unit

                for &Attribute {name, tokens: _, span} in attrs {
                    match name {
                        "prefix" => {}, //TODO
                        _ => return Err(DeclError::UnknownAttribute {name, span}),
                    }
                }

                self.units.insert_unit(unit_name, span)
                    .map_err(|_| DeclError::DuplicateUnitDecl {name: unit_name, span})?;
            }
        }
        Ok(())
    }

    /// Load declared constants and `const fn`s into the global scope of the interpreter
    fn load_const_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            //TODO: const fn declarations will be processed and unit checked here eventually

            if let Decl::Constant(_) = decl {
                unimplemented!();
            }
        }
        Ok(())
    }

    /// Load unit conversions and evaluate any const exprs found within them
    fn load_conversion_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            match decl {
                // Aliases need to be processed later when all the units have already been walked
                Decl::UnitDecl(UnitDecl {unit_name, alias_for, ..}) if alias_for.is_some() => unimplemented!(),
                Decl::ConversionDecl(_) => unimplemented!(),
                _ => {},
            }
        }
        Ok(())
    }

    /// Load function declarations into the global scope and check their bodies to ensure that any
    /// conversions are valid
    fn load_fn_decls(&mut self, program: &Program<'a>) -> Result<(), DeclError<'a>> {
        for decl in &program.decls {
            if let Decl::Function(_) = decl {
                unimplemented!();
            }
        }
        Ok(())
    }
}

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

    #[test]
    #[ignore] //TODO: Unignore once implemented
    fn multitype_function() {
        let input = r#"
        #[unit]
        #[converter]
        fn(x '_) -> 'deg { x }
        "#;
        let program = parse_program(input).unwrap();

        let mut inter = Interpreter::default();
        inter.load_decls(&program).unwrap_err();
    }
}
<|endoftext|>


<commit_before>extern crate gapbuffer;

use std::io::{File, Reader, BufferedReader};
use gapbuffer::GapBuffer;

#[deriving(Copy, Show)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

pub struct Buffer {
    pub file_path: Option<Path>,
    pub text: GapBuffer<u8>,
    pub cursor: uint,
}

impl Buffer {

    /// Constructor for empty buffer.
    pub fn new() -> Buffer {
        let text: GapBuffer<u8> = GapBuffer::new();
        Buffer {
            file_path: None,
            text: text,
            cursor: 0u,
        }
    }

    /// Constructor for buffer from reader.
    pub fn new_from_reader<R: Reader>(reader: R) -> Buffer {
        let mut buff = Buffer::new();
        if let Ok(contents) = BufferedReader::new(reader).read_to_string() {
            buff.text.extend(contents.chars());
        }
        buff
    }

    /// Constructor for buffer from file.
    pub fn new_from_file(path: Path) -> Buffer {
        if let Ok(file) = File::open(&path) {
            let mut buff = Buffer::new_from_reader(file);
            buff.file_path = Some(path);
            buff
        } else {
            Buffer::new()
        }
    }

    //Move the cursor by some amount (can be negative).
    pub fn move_cursor(&mut self, offset: int) {
        let idx = self.cursor as int + offset;
        if 0 >= idx && idx > self.text.len() as int {
            self.set_cursor(idx as uint);
        }
    }

    //Set the cursor to some index.
    pub fn set_cursor(&mut self, location: uint) {
        self.cursor = location;
    }

    //Shift the cursor by one in any of the four directions.
    pub fn shift_cursor(&mut self, direction: Direction) {
        match direction {
            Direction::Up /*if not the first line.*/            => {
                //up code
            }
            Direction::Down /*if not the last line.*/           => {
                //down code
            }
            Direction::Left if self.cursor > 0                  => {
                //needs to be changed for proper utf8 support?
                self.cursor -= 1;
            }
            Direction::Right if self.cursor < self.text.len()   => {
                //needs to be changed for proper utf8 support?
                self.cursor += 1;
            }
            _ => { break; }
        }
    }

    //Remove the char the cursor is at the index of.
    pub fn remove_char(&mut self) -> Option<char> {
        self.text.remove(self.cursor)
    }

    //Insert the char the cursor is at the index of.
    pub fn insert_char(&mut self, c: char) {
        self.text.insert(self.cursor, c);
    }

}
<commit_msg>Added Up/Down movement methods (uses experimental slicing).<commit_after>#![feature(slicing_syntax)]

//TODO: UTF8 support
//TODO: Save cursor x offset as it traverses up/down
//TODO: Write tests

extern crate gapbuffer;

use std::io::{File, Reader, BufferedReader};
use gapbuffer::GapBuffer;

#[deriving(Copy, Show)]
pub enum Direction {
    Up, Down, Left, Right,
}

pub struct Buffer {
    pub file_path: Option<Path>,
    pub text: GapBuffer<char>,
    pub cursor: uint,
}

//Private methods
impl Buffer {

    //Returns the number of newlines in the buffer before the mark.
    fn get_line(&self, mark: uint) -> Option<uint> {
        let mut linenum = 0;
        if mark < self.text.len() {
            for c in self.text[0..mark].iter() {
                if c == &'\n' { linenum += 1; }
            }
            Some(linenum)
        } else { None }
    }

    //Returns the index of the nth newline in the buffer.
    fn get_line_idx(&self, line: uint) -> Option<uint> {
        let mut linenum = 0;
        for idx in range(0, self.text.len()) {
            if self.text[idx] == '\n' { linenum += 1; if linenum == line { return Some(idx) } }
        }
        None
    }

    //Returns the index of the point the mark would be at if shifted 'offset' lines.
    fn move_line(&self, mark: uint, offset: int) -> Option<uint> {
        let mut x_offset = 1;
        loop {
            match self.text[0..mark].iter().next_back() {
                Some(&'\n') | None => { break; }
                _                  => { x_offset += 1; }
            }
        }
        if let Some(line) = self.get_line(mark) {
            let newline = (line as int - offset) as uint;
            Some(self.get_line_idx(newline).unwrap() + x_offset)
        } else { None }
    }

}

//Public methods
impl Buffer {

    /// Constructor for empty buffer.
    pub fn new() -> Buffer {
        let text = GapBuffer::new();
        Buffer {
            file_path: None,
            text: text,
            cursor: 0u,
        }
    }

    /// Constructor for buffer from reader.
    pub fn new_from_reader<R: Reader>(reader: R) -> Buffer {
        let mut buff = Buffer::new();
        if let Ok(contents) = BufferedReader::new(reader).read_to_string() {
            buff.text.extend(contents.chars());
        }
        buff
    }

    /// Constructor for buffer from file.
    pub fn new_from_file(path: Path) -> Buffer {
        if let Ok(file) = File::open(&path) {
            let mut buff = Buffer::new_from_reader(file);
            buff.file_path = Some(path);
            buff
        } else {
            Buffer::new()
        }
    }

    //Move the cursor by some amount (can be negative).
    pub fn move_cursor(&mut self, offset: int) {
        let idx = self.cursor as int + offset;
        if 0 >= idx && idx > self.text.len() as int {
            self.set_cursor(idx as uint);
        }
    }

    //Set the cursor to some index.
    pub fn set_cursor(&mut self, location: uint) {
        self.cursor = location;
    }

    //Shift the cursor by one in any of the four directions.
    pub fn shift_cursor(&mut self, direction: Direction) {
        match direction {
            Direction::Up if self.get_line(self.cursor).unwrap() > 0             => {
                self.move_line(self.cursor, -1);
            }
            Direction::Down
            if self.get_line(self.cursor) < self.get_line(self.text.len() - 1)  => {
                self.move_line(self.cursor, 1);
            }
            Direction::Left if self.cursor > 0                                  => {
                self.cursor -= 1;
            }
            Direction::Right if self.cursor < self.text.len()                   => {
                self.cursor += 1;
            }
            _ => { }
        }
    }

    //Remove the char the cursor is at the index of.
    pub fn remove_char(&mut self) -> Option<char> {
        self.text.remove(self.cursor)
    }

    //Insert the char the cursor is at the index of.
    pub fn insert_char(&mut self, c: char) {
        self.text.insert(self.cursor, c);
    }

}

#[cfg(test)]
mod test {

}
<|endoftext|>


<commit_before>/// Parse the input TokenStream of a macro, triggering a compile error if the
/// tokens fail to parse.
///
/// Refer to the [`parse` module] documentation for more details about parsing
/// in Syn.
///
/// [`parse` module]: crate::rustdoc_workaround::parse_module
///
/// # Intended usage
///
/// ```edition2018
/// extern crate proc_macro;
///
/// use proc_macro::TokenStream;
/// use syn::{parse_macro_input, Result};
/// use syn::parse::{Parse, ParseStream};
///
/// struct MyMacroInput {
///     /* ... */
/// }
///
/// impl Parse for MyMacroInput {
///     fn parse(input: ParseStream) -> Result<Self> {
///         /* ... */
/// #       Ok(MyMacroInput {})
///     }
/// }
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro]
/// # };
/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
///     let input = parse_macro_input!(tokens as MyMacroInput);
///
///     /* ... */
/// #   "".parse().unwrap()
/// }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! parse_macro_input {
    ($tokenstream:ident as $ty:ty) => {
        match $crate::parse_macro_input::parse::<$ty>($tokenstream) {
            $crate::export::Ok(data) => data,
            $crate::export::Err(err) => {
                return $crate::export::TokenStream::from(err.to_compile_error());
            }
        }
    };
    ($tokenstream:ident) => {
        parse_macro_input!($tokenstream as _)
    };
}

////////////////////////////////////////////////////////////////////////////////
// Can parse any type that implements Parse.

use crate::parse::{Parse, ParseStream, Parser, Result};
use proc_macro::TokenStream;

// Not public API.
#[doc(hidden)]
pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
    T::parse.parse(token_stream)
}

// Not public API.
#[doc(hidden)]
pub trait ParseMacroInput: Sized {
    fn parse(input: ParseStream) -> Result<Self>;
}

impl<T: Parse> ParseMacroInput for T {
    fn parse(input: ParseStream) -> Result<Self> {
        <T as Parse>::parse(input)
    }
}

////////////////////////////////////////////////////////////////////////////////
// Any other types that we want `parse_macro_input!` to be able to parse.

#[cfg(any(feature = "full", feature = "derive"))]
use crate::AttributeArgs;

#[cfg(any(feature = "full", feature = "derive"))]
impl ParseMacroInput for AttributeArgs {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut metas = Vec::new();

        loop {
            if input.is_empty() {
                break;
            }
            let value = input.parse()?;
            metas.push(value);
            if input.is_empty() {
                break;
            }
            input.parse::<Token![,]>()?;
        }

        Ok(metas)
    }
}
<commit_msg>Explain where to call parse_macro_input<commit_after>/// Parse the input TokenStream of a macro, triggering a compile error if the
/// tokens fail to parse.
///
/// Refer to the [`parse` module] documentation for more details about parsing
/// in Syn.
///
/// [`parse` module]: crate::rustdoc_workaround::parse_module
///
/// <br>
///
/// # Intended usage
///
/// This macro must be called from a function that returns
/// `proc_macro::TokenStream`. Usually this will be your proc macro entry point,
/// the function that has the #\[proc_macro\] / #\[proc_macro_derive\] /
/// #\[proc_macro_attribute\] attribute.
///
/// ```edition2018
/// extern crate proc_macro;
///
/// use proc_macro::TokenStream;
/// use syn::{parse_macro_input, Result};
/// use syn::parse::{Parse, ParseStream};
///
/// struct MyMacroInput {
///     /* ... */
/// }
///
/// impl Parse for MyMacroInput {
///     fn parse(input: ParseStream) -> Result<Self> {
///         /* ... */
/// #       Ok(MyMacroInput {})
///     }
/// }
///
/// # const IGNORE: &str = stringify! {
/// #[proc_macro]
/// # };
/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
///     let input = parse_macro_input!(tokens as MyMacroInput);
///
///     /* ... */
/// #   "".parse().unwrap()
/// }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! parse_macro_input {
    ($tokenstream:ident as $ty:ty) => {
        match $crate::parse_macro_input::parse::<$ty>($tokenstream) {
            $crate::export::Ok(data) => data,
            $crate::export::Err(err) => {
                return $crate::export::TokenStream::from(err.to_compile_error());
            }
        }
    };
    ($tokenstream:ident) => {
        parse_macro_input!($tokenstream as _)
    };
}

////////////////////////////////////////////////////////////////////////////////
// Can parse any type that implements Parse.

use crate::parse::{Parse, ParseStream, Parser, Result};
use proc_macro::TokenStream;

// Not public API.
#[doc(hidden)]
pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
    T::parse.parse(token_stream)
}

// Not public API.
#[doc(hidden)]
pub trait ParseMacroInput: Sized {
    fn parse(input: ParseStream) -> Result<Self>;
}

impl<T: Parse> ParseMacroInput for T {
    fn parse(input: ParseStream) -> Result<Self> {
        <T as Parse>::parse(input)
    }
}

////////////////////////////////////////////////////////////////////////////////
// Any other types that we want `parse_macro_input!` to be able to parse.

#[cfg(any(feature = "full", feature = "derive"))]
use crate::AttributeArgs;

#[cfg(any(feature = "full", feature = "derive"))]
impl ParseMacroInput for AttributeArgs {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut metas = Vec::new();

        loop {
            if input.is_empty() {
                break;
            }
            let value = input.parse()?;
            metas.push(value);
            if input.is_empty() {
                break;
            }
            input.parse::<Token![,]>()?;
        }

        Ok(metas)
    }
}
<|endoftext|>


<commit_before>use std::num::{One, Zero};
use structs::mat;
use traits::operations::{Inv, Transpose};
use traits::geometry::{Translation, Translate, Rotation, Rotate, Transformation, Transform};

impl One for mat::Identity {
    #[inline]
    fn one() -> mat::Identity {
        mat::Identity::new()
    }
}

impl Inv for mat::Identity {
    fn inv_cpy(_: &mat::Identity) -> Option<mat::Identity> {
        Some(mat::Identity::new())
    }

    fn inv(&mut self) -> bool {
        true
    }
}

impl<T: Clone> Mul<T, T> for mat::Identity {
    #[inline]
    fn mul(&self, other: &T) -> T {
        other.clone()
    }
}

impl Transpose for mat::Identity {
    #[inline]
    fn transpose_cpy(_: &mat::Identity) -> mat::Identity {
        mat::Identity::new()
    }

    #[inline]
    fn transpose(&mut self) {
    }
}

impl<V: Zero> Translation<V> for mat::Identity {
    #[inline]
    fn translation(&self) -> V {
        Zero::zero()
    }

    #[inline]
    fn inv_translation(&self) -> V {
        Zero::zero()
    }

    #[inline]
    fn append_translation(&mut self, _: &V) {
        fail!("Attempted to translate the identity matrix.")
    }

    #[inline]
    fn append_translation_cpy(_: &mat::Identity, _: &V) -> mat::Identity {
        fail!("Attempted to translate the identity matrix.")
    }

    #[inline]
    fn prepend_translation(&mut self, _: &V) {
        fail!("Attempted to translate the identity matrix.")
    }

    #[inline]
    fn prepend_translation_cpy(_: &mat::Identity, _: &V) -> mat::Identity {
        fail!("Attempted to translate the identity matrix.")
    }

    #[inline]
    fn set_translation(&mut self, _: V) {
        fail!("Attempted to translate the identity matrix.")
    }
}

impl<V: Clone> Translate<V> for mat::Identity {
    #[inline]
    fn translate(&self, v: &V) -> V {
        v.clone()
    }

    #[inline]
    fn inv_translate(&self, v: &V) -> V {
        v.clone()
    }
}

impl<V: Zero> Rotation<V> for mat::Identity {
    #[inline]
    fn rotation(&self) -> V {
        Zero::zero()
    }

    #[inline]
    fn inv_rotation(&self) -> V {
        Zero::zero()
    }

    #[inline]
    fn append_rotation(&mut self, _: &V) {
        fail!("Attempted to rotate the identity matrix.")
    }

    #[inline]
    fn append_rotation_cpy(_: &mat::Identity, _: &V) -> mat::Identity {
        fail!("Attempted to rotate the identity matrix.")
    }

    #[inline]
    fn prepend_rotation(&mut self, _: &V) {
        fail!("Attempted to rotate the identity matrix.")
    }

    #[inline]
    fn prepend_rotation_cpy(_: &mat::Identity, _: &V) -> mat::Identity {
        fail!("Attempted to rotate the identity matrix.")
    }

    #[inline]
    fn set_rotation(&mut self, _: V) {
        fail!("Attempted to rotate the identity matrix.")
    }
}

impl<V: Clone> Rotate<V> for mat::Identity {
    #[inline]
    fn rotate(&self, v: &V) -> V {
        v.clone()
    }

    #[inline]
    fn inv_rotate(&self, v: &V) -> V {
        v.clone()
    }
}

impl<M: One> Transformation<M> for mat::Identity {
    #[inline]
    fn transformation(&self) -> M {
        One::one()
    }

    #[inline]
    fn inv_transformation(&self) -> M {
        One::one()
    }

    #[inline]
    fn append_transformation(&mut self, _: &M) {
        fail!("Attempted to transform the identity matrix.")
    }

    #[inline]
    fn append_transformation_cpy(_: &mat::Identity, _: &M) -> mat::Identity {
        fail!("Attempted to transform the identity matrix.")
    }

    #[inline]
    fn prepend_transformation(&mut self, _: &M) {
        fail!("Attempted to transform the identity matrix.")
    }

    #[inline]
    fn prepend_transformation_cpy(_: &mat::Identity, _: &M) -> mat::Identity {
        fail!("Attempted to transform the identity matrix.")
    }

    #[inline]
    fn set_transformation(&mut self, _: M) {
        fail!("Attempted to transform the identity matrix.")
    }
}

impl<V: Clone> Transform<V> for mat::Identity {
    #[inline]
    fn transform(&self, v: &V) -> V {
        v.clone()
    }

    #[inline]
    fn inv_transform(&self, v: &V) -> V {
        v.clone()
    }
}
<commit_msg>Implement AbsoluteRotate for Identity.<commit_after>use std::num::{One, Zero};
use structs::mat;
use traits::operations::{Inv, Transpose};
use traits::geometry::{Translation, Translate, Rotation, Rotate, Transformation, Transform, AbsoluteRotate};

impl One for mat::Identity {
    #[inline]
    fn one() -> mat::Identity {
        mat::Identity::new()
    }
}

impl Inv for mat::Identity {
    fn inv_cpy(_: &mat::Identity) -> Option<mat::Identity> {
        Some(mat::Identity::new())
    }

    fn inv(&mut self) -> bool {
        true
    }
}

impl<T: Clone> Mul<T, T> for mat::Identity {
    #[inline]
    fn mul(&self, other: &T) -> T {
        other.clone()
    }
}

impl Transpose for mat::Identity {
    #[inline]
    fn transpose_cpy(_: &mat::Identity) -> mat::Identity {
        mat::Identity::new()
    }

    #[inline]
    fn transpose(&mut self) {
    }
}

impl<V: Zero> Translation<V> for mat::Identity {
    #[inline]
    fn translation(&self) -> V {
        Zero::zero()
    }

    #[inline]
    fn inv_translation(&self) -> V {
        Zero::zero()
    }

    #[inline]
    fn append_translation(&mut self, _: &V) {
        fail!("Attempted to translate the identity matrix.")
    }

    #[inline]
    fn append_translation_cpy(_: &mat::Identity, _: &V) -> mat::Identity {
        fail!("Attempted to translate the identity matrix.")
    }

    #[inline]
    fn prepend_translation(&mut self, _: &V) {
        fail!("Attempted to translate the identity matrix.")
    }

    #[inline]
    fn prepend_translation_cpy(_: &mat::Identity, _: &V) -> mat::Identity {
        fail!("Attempted to translate the identity matrix.")
    }

    #[inline]
    fn set_translation(&mut self, _: V) {
        fail!("Attempted to translate the identity matrix.")
    }
}

impl<V: Clone> Translate<V> for mat::Identity {
    #[inline]
    fn translate(&self, v: &V) -> V {
        v.clone()
    }

    #[inline]
    fn inv_translate(&self, v: &V) -> V {
        v.clone()
    }
}

impl<V: Zero> Rotation<V> for mat::Identity {
    #[inline]
    fn rotation(&self) -> V {
        Zero::zero()
    }

    #[inline]
    fn inv_rotation(&self) -> V {
        Zero::zero()
    }

    #[inline]
    fn append_rotation(&mut self, _: &V) {
        fail!("Attempted to rotate the identity matrix.")
    }

    #[inline]
    fn append_rotation_cpy(_: &mat::Identity, _: &V) -> mat::Identity {
        fail!("Attempted to rotate the identity matrix.")
    }

    #[inline]
    fn prepend_rotation(&mut self, _: &V) {
        fail!("Attempted to rotate the identity matrix.")
    }

    #[inline]
    fn prepend_rotation_cpy(_: &mat::Identity, _: &V) -> mat::Identity {
        fail!("Attempted to rotate the identity matrix.")
    }

    #[inline]
    fn set_rotation(&mut self, _: V) {
        fail!("Attempted to rotate the identity matrix.")
    }
}

impl<V: Clone> Rotate<V> for mat::Identity {
    #[inline]
    fn rotate(&self, v: &V) -> V {
        v.clone()
    }

    #[inline]
    fn inv_rotate(&self, v: &V) -> V {
        v.clone()
    }
}

impl<V: Clone> AbsoluteRotate<V> for mat::Identity {
    #[inline]
    fn absolute_rotate(&self, v: &V) -> V {
        v.clone()
    }
}

impl<M: One> Transformation<M> for mat::Identity {
    #[inline]
    fn transformation(&self) -> M {
        One::one()
    }

    #[inline]
    fn inv_transformation(&self) -> M {
        One::one()
    }

    #[inline]
    fn append_transformation(&mut self, _: &M) {
        fail!("Attempted to transform the identity matrix.")
    }

    #[inline]
    fn append_transformation_cpy(_: &mat::Identity, _: &M) -> mat::Identity {
        fail!("Attempted to transform the identity matrix.")
    }

    #[inline]
    fn prepend_transformation(&mut self, _: &M) {
        fail!("Attempted to transform the identity matrix.")
    }

    #[inline]
    fn prepend_transformation_cpy(_: &mat::Identity, _: &M) -> mat::Identity {
        fail!("Attempted to transform the identity matrix.")
    }

    #[inline]
    fn set_transformation(&mut self, _: M) {
        fail!("Attempted to transform the identity matrix.")
    }
}

impl<V: Clone> Transform<V> for mat::Identity {
    #[inline]
    fn transform(&self, v: &V) -> V {
        v.clone()
    }

    #[inline]
    fn inv_transform(&self, v: &V) -> V {
        v.clone()
    }
}
<|endoftext|>


<commit_before>#![allow(missing_docs)]
#![unstable(feature = "raw", issue = "27751")]

//! Contains struct definitions for the layout of compiler built-in types.
//!
//! They can be used as targets of transmutes in unsafe code for manipulating
//! the raw representations directly.
//!
//! Their definition should always match the ABI defined in
//! `rustc_middle::ty::layout`.

/// The representation of a trait object like `&SomeTrait`.
///
/// This struct has the same layout as types like `&SomeTrait` and
/// `Box<dyn AnotherTrait>`.
///
/// `TraitObject` is guaranteed to match layouts, but it is not the
/// type of trait objects (e.g., the fields are not directly accessible
/// on a `&SomeTrait`) nor does it control that layout (changing the
/// definition will not change the layout of a `&SomeTrait`). It is
/// only designed to be used by unsafe code that needs to manipulate
/// the low-level details.
///
/// There is no way to refer to all trait objects generically, so the only
/// way to create values of this type is with functions like
/// [`std::mem::transmute`][transmute]. Similarly, the only way to create a true
/// trait object from a `TraitObject` value is with `transmute`.
///
/// [transmute]: ../intrinsics/fn.transmute.html
///
/// Synthesizing a trait object with mismatched types—one where the
/// vtable does not correspond to the type of the value to which the
/// data pointer points—is highly likely to lead to undefined
/// behavior.
///
/// # Examples
///
/// ```
/// #![feature(raw)]
///
/// use std::{mem, raw};
///
/// // an example trait
/// trait Foo {
///     fn bar(&self) -> i32;
/// }
///
/// impl Foo for i32 {
///     fn bar(&self) -> i32 {
///          *self + 1
///     }
/// }
///
/// let value: i32 = 123;
///
/// // let the compiler make a trait object
/// let object: &dyn Foo = &value;
///
/// // look at the raw representation
/// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) };
///
/// // the data pointer is the address of `value`
/// assert_eq!(raw_object.data as *const i32, &value as *const _);
///
/// let other_value: i32 = 456;
///
/// // construct a new object, pointing to a different `i32`, being
/// // careful to use the `i32` vtable from `object`
/// let synthesized: &dyn Foo = unsafe {
///      mem::transmute(raw::TraitObject {
///          data: &other_value as *const _ as *mut (),
///          vtable: raw_object.vtable,
///      })
/// };
///
/// // it should work just as if we had constructed a trait object out of
/// // `other_value` directly
/// assert_eq!(synthesized.bar(), 457);
/// ```
#[repr(C)]
#[derive(Copy, Clone)]
#[allow(missing_debug_implementations)]
pub struct TraitObject {
    pub data: *mut (),
    pub vtable: *mut (),
}
<commit_msg>Use `dyn` trait syntax in more comments and docs<commit_after>#![allow(missing_docs)]
#![unstable(feature = "raw", issue = "27751")]

//! Contains struct definitions for the layout of compiler built-in types.
//!
//! They can be used as targets of transmutes in unsafe code for manipulating
//! the raw representations directly.
//!
//! Their definition should always match the ABI defined in
//! `rustc_middle::ty::layout`.

/// The representation of a trait object like `&dyn SomeTrait`.
///
/// This struct has the same layout as types like `&dyn SomeTrait` and
/// `Box<dyn AnotherTrait>`.
///
/// `TraitObject` is guaranteed to match layouts, but it is not the
/// type of trait objects (e.g., the fields are not directly accessible
/// on a `&dyn SomeTrait`) nor does it control that layout (changing the
/// definition will not change the layout of a `&dyn SomeTrait`). It is
/// only designed to be used by unsafe code that needs to manipulate
/// the low-level details.
///
/// There is no way to refer to all trait objects generically, so the only
/// way to create values of this type is with functions like
/// [`std::mem::transmute`][transmute]. Similarly, the only way to create a true
/// trait object from a `TraitObject` value is with `transmute`.
///
/// [transmute]: ../intrinsics/fn.transmute.html
///
/// Synthesizing a trait object with mismatched types—one where the
/// vtable does not correspond to the type of the value to which the
/// data pointer points—is highly likely to lead to undefined
/// behavior.
///
/// # Examples
///
/// ```
/// #![feature(raw)]
///
/// use std::{mem, raw};
///
/// // an example trait
/// trait Foo {
///     fn bar(&self) -> i32;
/// }
///
/// impl Foo for i32 {
///     fn bar(&self) -> i32 {
///          *self + 1
///     }
/// }
///
/// let value: i32 = 123;
///
/// // let the compiler make a trait object
/// let object: &dyn Foo = &value;
///
/// // look at the raw representation
/// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) };
///
/// // the data pointer is the address of `value`
/// assert_eq!(raw_object.data as *const i32, &value as *const _);
///
/// let other_value: i32 = 456;
///
/// // construct a new object, pointing to a different `i32`, being
/// // careful to use the `i32` vtable from `object`
/// let synthesized: &dyn Foo = unsafe {
///      mem::transmute(raw::TraitObject {
///          data: &other_value as *const _ as *mut (),
///          vtable: raw_object.vtable,
///      })
/// };
///
/// // it should work just as if we had constructed a trait object out of
/// // `other_value` directly
/// assert_eq!(synthesized.bar(), 457);
/// ```
#[repr(C)]
#[derive(Copy, Clone)]
#[allow(missing_debug_implementations)]
pub struct TraitObject {
    pub data: *mut (),
    pub vtable: *mut (),
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 William (B.J.) Snow Orvis
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use common::{Point, Turtle, TurtleApp};

/// Represents a lindenmayer system. It requires an alphabet (represented as an enum), an initial
/// sequence ("string"), and one or more rules that transform the sequence with each
/// iteration/generation.
pub trait LindenmayerSystem<Alphabet: Clone> {
    /// Should return the initial Lindenmayer system string (iteration 0).
    fn initial() -> Vec<Alphabet>;

    /// Apply Lindenmayer system rules to a given character.
    ///
    /// This is done to efficiently use `match`ing at compile time, rather than returning a hashmap
    /// and handling it at runtime.
    fn apply_rule(Alphabet) -> Vec<Alphabet>;

    /// Generates a Lindenmayer system string for `iteration`.
    ///
    /// This is done by starting with the initial sequence, and repeatedly applying the rules to
    /// the sequence `iteration` times. The result is a new vector that contains the sequence for
    /// the specified iteration.
    fn generate(iteration: u64) -> Vec<Alphabet> {
        let mut lstr: Vec<Alphabet> = Self::initial();
        let mut i = 0;
        while i < iteration {
            i = i + 1;
            let mut newlstr: Vec<Alphabet> = vec![];

            for l in lstr.iter().cloned() {
                for other in Self::apply_rule(l).iter().cloned() {
                    newlstr.push(other);
                }
            }
            lstr = newlstr;
        }
        lstr
    }
}

/// In order to draw a fractal using a Lindenmayer System, we need to translate the output from the
/// L-System into turtle commands. To do this, we need to initial the turtle, and we need a way to
/// convert the L-System's symbols into actions. This trait provides the methods needed to
/// configure the LindenmayerSystemTurtleApp, which is the glue that issues arbitrary Turtle
/// commands.
pub trait LindenmayerSystemDrawingParameters<Alphabet> {
    /// Returns the iteration that should be drawn.
    fn iteration(&self) -> u64;

    /// Set up the turtle's initial position and direction.
    ///
    /// If no direction is specified, then the turtle will start at (0.0, 0.0). Most IFS fractals
    /// have some sort of formula for their initial angle that will ensure that the fractal is
    /// drawn within the viewing space.
    fn initialize_turtle(&self, turtle: &mut Turtle);

    /// Convert symbol into turtle commands.
    ///
    /// Usually, when moving the turtle forwards, there is some formula that will ensure that the
    /// turtle always ends at a given point, such as at (1.0, 0.0).
    fn interpret_symbol(&self, symbol: Alphabet, turtle: &mut Turtle);
}

use std::marker::PhantomData;

pub struct LindenmayerSystemTurtleApp<L, A>
    where L: LindenmayerSystem<A> + LindenmayerSystemDrawingParameters<A>,
          A: Clone
{
    alphabet: PhantomData<A>,
    system: L,
}

impl<L, A> LindenmayerSystemTurtleApp<L, A>
    where L: LindenmayerSystem<A> + LindenmayerSystemDrawingParameters<A>,
          A: Clone
{
    pub fn new(system: L) -> LindenmayerSystemTurtleApp<L, A> {
        LindenmayerSystemTurtleApp {
            system: system,
            alphabet: PhantomData,
        }
    }
}

impl<L, A> TurtleApp for LindenmayerSystemTurtleApp<L, A>
    where L: LindenmayerSystem<A> + LindenmayerSystemDrawingParameters<A>,
          A: Clone
{
    fn draw(&self, turtle: &mut Turtle) {
        println!("Generating L-System sequence...");
        let sequence = L::generate(self.system.iteration());
        println!("Done");

        turtle.set_pos(Point { x: 0.0, y: 0.0 });
        self.system.initialize_turtle(turtle);
        turtle.down();

        for symbol in sequence.iter().cloned() {
            self.system.interpret_symbol(symbol, turtle);
        }
        turtle.up();
    }
}

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

    #[derive(Clone, PartialEq, Eq, Debug)]
    enum TestABC {
        A,
        B,
        C,
        Foo,
    }

    struct TestLS;

    impl LindenmayerSystem<TestABC> for TestLS {
        fn initial() -> Vec<TestABC> {
            vec![TestABC::A, TestABC::B, TestABC::C]
        }

        fn apply_rule(l: TestABC) -> Vec<TestABC> {
            match l {
                TestABC::A => vec![TestABC::A, TestABC::Foo, TestABC::B, TestABC::C],
                TestABC::B => vec![TestABC::Foo],
                TestABC::C => vec![TestABC::Foo, TestABC::B],
                TestABC::Foo => vec![TestABC::Foo],
            }
        }
    }

    #[test]
    fn test_ls() {
        assert_eq!(TestLS::generate(0), [TestABC::A, TestABC::B, TestABC::C]);
        assert_eq!(TestLS::generate(1),
                   [TestABC::A,
                    TestABC::Foo,
                    TestABC::B,
                    TestABC::C,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::B]);
        assert_eq!(TestLS::generate(2),
                   [TestABC::A,
                    TestABC::Foo,
                    TestABC::B,
                    TestABC::C,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::B,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo]);
        assert_eq!(TestLS::generate(3),
                   [TestABC::A,
                    TestABC::Foo,
                    TestABC::B,
                    TestABC::C,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::B,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo]);
    }
}
<commit_msg>More l-system doc strings<commit_after>// Copyright (c) 2015 William (B.J.) Snow Orvis
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Lindenmayer systems are a methodology for representing various kinds of
//! iterated curves or other constructions. A given system has an alphabet of
//! symbols, an initial string, and one or more rules for transforming that
//! string into the next iteration/generation.
//!
//! The resulting string at a given iteration or generation can represent a
//! sequence of commands that some representation process, such as a turtle
//! drawing program, can then use to draw a curve/fractal/plant (which is what
//! this implementation provides).
use common::{Point, Turtle, TurtleApp};

/// Represents a particular Lindenmayer system. It requires an alphabet (represented as an enum),
/// an initial sequence ("string"), and one or more rules that transform the sequence with each
/// iteration/generation.
pub trait LindenmayerSystem<Alphabet: Clone> {
    /// Should return the initial Lindenmayer system string (iteration 0).
    fn initial() -> Vec<Alphabet>;

    /// Apply Lindenmayer system rules to a given character.
    ///
    /// This is done to efficiently use `match`ing at compile time, rather than returning a hashmap
    /// and handling it at runtime.
    fn apply_rule(Alphabet) -> Vec<Alphabet>;

    /// Generates a Lindenmayer system string for `iteration`.
    ///
    /// This is done by starting with the initial sequence, and repeatedly applying the rules to
    /// the sequence `iteration` times. The result is a new vector that contains the sequence for
    /// the specified iteration.
    fn generate(iteration: u64) -> Vec<Alphabet> {
        let mut lstr: Vec<Alphabet> = Self::initial();
        let mut i = 0;
        while i < iteration {
            i = i + 1;
            let mut newlstr: Vec<Alphabet> = vec![];

            for l in lstr.iter().cloned() {
                for other in Self::apply_rule(l).iter().cloned() {
                    newlstr.push(other);
                }
            }
            lstr = newlstr;
        }
        lstr
    }
}

/// In order to draw a fractal using a Lindenmayer System, we need to translate the output from the
/// L-System into turtle commands. To do this, we need to initial the turtle, and we need a way to
/// convert the L-System's symbols into actions. This trait provides the methods needed to
/// configure the LindenmayerSystemTurtleApp, which is the glue that issues arbitrary Turtle
/// commands.
pub trait LindenmayerSystemDrawingParameters<Alphabet> {
    /// Returns the iteration that should be drawn.
    fn iteration(&self) -> u64;

    /// Set up the turtle's initial position and direction.
    ///
    /// If no direction is specified, then the turtle will start at (0.0, 0.0). Most IFS fractals
    /// have some sort of formula for their initial angle that will ensure that the fractal is
    /// drawn within the viewing space.
    fn initialize_turtle(&self, turtle: &mut Turtle);

    /// Convert symbol into turtle commands.
    ///
    /// Usually, when moving the turtle forwards, there is some formula that will ensure that the
    /// turtle always ends at a given point, such as at (1.0, 0.0).
    fn interpret_symbol(&self, symbol: Alphabet, turtle: &mut Turtle);
}

use std::marker::PhantomData;

pub struct LindenmayerSystemTurtleApp<L, A>
    where L: LindenmayerSystem<A> + LindenmayerSystemDrawingParameters<A>,
          A: Clone
{
    alphabet: PhantomData<A>,
    system: L,
}

impl<L, A> LindenmayerSystemTurtleApp<L, A>
    where L: LindenmayerSystem<A> + LindenmayerSystemDrawingParameters<A>,
          A: Clone
{
    pub fn new(system: L) -> LindenmayerSystemTurtleApp<L, A> {
        LindenmayerSystemTurtleApp {
            system: system,
            alphabet: PhantomData,
        }
    }
}

impl<L, A> TurtleApp for LindenmayerSystemTurtleApp<L, A>
    where L: LindenmayerSystem<A> + LindenmayerSystemDrawingParameters<A>,
          A: Clone
{
    fn draw(&self, turtle: &mut Turtle) {
        println!("Generating L-System sequence...");
        let sequence = L::generate(self.system.iteration());
        println!("Done");

        turtle.set_pos(Point { x: 0.0, y: 0.0 });
        self.system.initialize_turtle(turtle);
        turtle.down();

        for symbol in sequence.iter().cloned() {
            self.system.interpret_symbol(symbol, turtle);
        }
        turtle.up();
    }
}

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

    #[derive(Clone, PartialEq, Eq, Debug)]
    enum TestABC {
        A,
        B,
        C,
        Foo,
    }

    struct TestLS;

    impl LindenmayerSystem<TestABC> for TestLS {
        fn initial() -> Vec<TestABC> {
            vec![TestABC::A, TestABC::B, TestABC::C]
        }

        fn apply_rule(l: TestABC) -> Vec<TestABC> {
            match l {
                TestABC::A => vec![TestABC::A, TestABC::Foo, TestABC::B, TestABC::C],
                TestABC::B => vec![TestABC::Foo],
                TestABC::C => vec![TestABC::Foo, TestABC::B],
                TestABC::Foo => vec![TestABC::Foo],
            }
        }
    }

    #[test]
    fn test_ls() {
        assert_eq!(TestLS::generate(0), [TestABC::A, TestABC::B, TestABC::C]);
        assert_eq!(TestLS::generate(1),
                   [TestABC::A,
                    TestABC::Foo,
                    TestABC::B,
                    TestABC::C,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::B]);
        assert_eq!(TestLS::generate(2),
                   [TestABC::A,
                    TestABC::Foo,
                    TestABC::B,
                    TestABC::C,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::B,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo]);
        assert_eq!(TestLS::generate(3),
                   [TestABC::A,
                    TestABC::Foo,
                    TestABC::B,
                    TestABC::C,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::B,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo,
                    TestABC::Foo]);
    }
}
<|endoftext|>