<commit_before>use std::iter::FromIterator;
use std::mem;

use crate::repr::{Decor, InternalString};
use crate::value::{DEFAULT_LEADING_VALUE_DECOR, DEFAULT_VALUE_DECOR};
use crate::{Item, Value};

/// Type representing a TOML array,
/// payload of the `Value::Array` variant's value
#[derive(Debug, Default, Clone)]
pub struct Array {
    // `trailing` represents whitespaces, newlines
    // and comments in an empty array or after the trailing comma
    trailing: InternalString,
    trailing_comma: bool,
    // prefix before `[` and suffix after `]`
    decor: Decor,
    // always Vec<Item::Value>
    pub(crate) values: Vec<Item>,
}

/// An owned iterator type over `Table`'s key/value pairs.
pub type ArrayIntoIter = Box<dyn Iterator<Item = Value>>;
/// An iterator type over `Array`'s values.
pub type ArrayIter<'a> = Box<dyn Iterator<Item = &'a Value> + 'a>;
/// An iterator type over `Array`'s values.
pub type ArrayIterMut<'a> = Box<dyn Iterator<Item = &'a mut Value> + 'a>;

/// Constructors
///
/// See also `FromIterator`
impl Array {
    /// Create an empty `Array`
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// ```
    pub fn new() -> Self {
        Default::default()
    }

    pub(crate) fn with_vec(values: Vec<Item>) -> Self {
        Self {
            values,
            ..Default::default()
        }
    }
}

/// Formatting
impl Array {
    /// Auto formats the array.
    pub fn fmt(&mut self) {
        decorate_array(self);
    }

    /// Set whether the array will use a trailing comma
    pub fn set_trailing_comma(&mut self, yes: bool) {
        self.trailing_comma = yes;
    }

    /// Whether the array will use a trailing comma
    pub fn trailing_comma(&self) -> bool {
        self.trailing_comma
    }

    /// Set whitespace after last element
    pub fn set_trailing(&mut self, trailing: &str) {
        self.trailing = trailing.to_owned();
    }

    /// Whitespace after last element
    pub fn trailing(&self) -> &str {
        self.trailing.as_str()
    }

    /// Returns the surrounding whitespace
    pub fn decor_mut(&mut self) -> &mut Decor {
        &mut self.decor
    }

    /// Returns the surrounding whitespace
    pub fn decor(&self) -> &Decor {
        &self.decor
    }
}

impl Array {
    /// Returns an iterator over all values.
    pub fn iter(&self) -> ArrayIter<'_> {
        Box::new(self.values.iter().filter_map(Item::as_value))
    }

    /// Returns an iterator over all values.
    pub fn iter_mut(&mut self) -> ArrayIterMut<'_> {
        Box::new(self.values.iter_mut().filter_map(Item::as_value_mut))
    }

    /// Returns the length of the underlying Vec.
    ///
    /// In some rare cases, placeholder elements will exist.  For a more accurate count, call
    /// `a.iter().count()`
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    /// assert_eq!(arr.len(), 2);
    /// ```
    pub fn len(&self) -> usize {
        self.values.len()
    }

    /// Return true iff `self.len() == 0`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// assert!(arr.is_empty());
    ///
    /// arr.push(1);
    /// arr.push("foo");
    /// assert!(! arr.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Clears the array, removing all values. Keeps the allocated memory for reuse.
    pub fn clear(&mut self) {
        self.values.clear()
    }

    /// Returns a reference to the value at the given index, or `None` if the index is out of
    /// bounds.
    pub fn get(&self, index: usize) -> Option<&Value> {
        self.values.get(index).and_then(Item::as_value)
    }

    /// Returns a reference to the value at the given index, or `None` if the index is out of
    /// bounds.
    pub fn get_mut(&mut self, index: usize) -> Option<&mut Value> {
        self.values.get_mut(index).and_then(Item::as_value_mut)
    }

    /// Appends a new value to the end of the array, applying default formatting to it.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    /// ```
    pub fn push<V: Into<Value>>(&mut self, v: V) {
        self.value_op(v.into(), true, |items, value| {
            items.push(Item::Value(value))
        })
    }

    /// Appends a new, already formatted value to the end of the array.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let formatted_value = "'literal'".parse::<toml_edit::Value>().unwrap();
    /// let mut arr = toml_edit::Array::new();
    /// arr.push_formatted(formatted_value);
    /// ```
    pub fn push_formatted(&mut self, v: Value) {
        self.values.push(Item::Value(v));
    }

    /// Inserts an element at the given position within the array, applying default formatting to
    /// it and shifting all values after it to the right.
    ///
    /// # Panics
    ///
    /// Panics if `index > len`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    ///
    /// arr.insert(0, "start");
    /// ```
    pub fn insert<V: Into<Value>>(&mut self, index: usize, v: V) {
        self.value_op(v.into(), true, |items, value| {
            items.insert(index, Item::Value(value))
        })
    }

    /// Inserts an already formatted value at the given position within the array, shifting all
    /// values after it to the right.
    ///
    /// # Panics
    ///
    /// Panics if `index > len`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    ///
    /// let formatted_value = "'start'".parse::<toml_edit::Value>().unwrap();
    /// arr.insert_formatted(0, formatted_value);
    /// ```
    pub fn insert_formatted(&mut self, index: usize, v: Value) {
        self.values.insert(index, Item::Value(v))
    }

    /// Replaces the element at the given position within the array, preserving existing formatting.
    ///
    /// # Panics
    ///
    /// Panics if `index >= len`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    ///
    /// arr.replace(0, "start");
    /// ```
    pub fn replace<V: Into<Value>>(&mut self, index: usize, v: V) -> Value {
        // Read the existing value's decor and preserve it.
        let existing_decor = self
            .get(index)
            .unwrap_or_else(|| panic!("index {} out of bounds (len = {})", index, self.len()))
            .decor();
        let mut value = v.into();
        *value.decor_mut() = existing_decor.clone();
        self.replace_formatted(index, value)
    }

    /// Replaces the element at the given position within the array with an already formatted value.
    ///
    /// # Panics
    ///
    /// Panics if `index >= len`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    ///
    /// let formatted_value = "'start'".parse::<toml_edit::Value>().unwrap();
    /// arr.replace_formatted(0, formatted_value);
    /// ```
    pub fn replace_formatted(&mut self, index: usize, v: Value) -> Value {
        match mem::replace(&mut self.values[index], Item::Value(v)) {
            Item::Value(old_value) => old_value,
            x => panic!("non-value item {:?} in an array", x),
        }
    }

    /// Removes the value at the given index.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    ///
    /// arr.remove(0);
    /// assert_eq!(arr.len(), 1);
    /// ```
    pub fn remove(&mut self, index: usize) -> Value {
        let removed = self.values.remove(index);
        match removed {
            Item::Value(v) => v,
            x => panic!("non-value item {:?} in an array", x),
        }
    }

    fn value_op<T>(
        &mut self,
        v: Value,
        decorate: bool,
        op: impl FnOnce(&mut Vec<Item>, Value) -> T,
    ) -> T {
        let mut value = v;
        if !self.is_empty() && decorate {
            value.decorate(" ", "");
        } else if decorate {
            value.decorate("", "");
        }
        op(&mut self.values, value)
    }
}

impl<V: Into<Value>> Extend<V> for Array {
    fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
        for value in iter {
            self.push(value.into());
        }
    }
}

impl<V: Into<Value>> FromIterator<V> for Array {
    fn from_iter<I>(iter: I) -> Self
    where
        I: IntoIterator<Item = V>,
    {
        let v = iter.into_iter().map(|a| Item::Value(a.into()));
        let mut array = Array {
            values: v.collect(),
            ..Default::default()
        };
        array.fmt();
        array
    }
}

impl IntoIterator for Array {
    type Item = Value;
    type IntoIter = ArrayIntoIter;

    fn into_iter(self) -> Self::IntoIter {
        Box::new(
            self.values
                .into_iter()
                .filter(|v| v.is_value())
                .map(|v| v.into_value().unwrap()),
        )
    }
}

impl<'s> IntoIterator for &'s Array {
    type Item = &'s Value;
    type IntoIter = ArrayIter<'s>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

fn decorate_array(array: &mut Array) {
    for (i, value) in array
        .values
        .iter_mut()
        .filter_map(Item::as_value_mut)
        .enumerate()
    {
        // [value1, value2, value3]
        if i == 0 {
            value.decorate(DEFAULT_LEADING_VALUE_DECOR.0, DEFAULT_LEADING_VALUE_DECOR.1);
        } else {
            value.decorate(DEFAULT_VALUE_DECOR.0, DEFAULT_VALUE_DECOR.1);
        }
    }
}
<commit_msg>fix: Don't re-format (#200)<commit_after>use std::iter::FromIterator;
use std::mem;

use crate::repr::{Decor, InternalString};
use crate::value::{DEFAULT_LEADING_VALUE_DECOR, DEFAULT_VALUE_DECOR};
use crate::{Item, Value};

/// Type representing a TOML array,
/// payload of the `Value::Array` variant's value
#[derive(Debug, Default, Clone)]
pub struct Array {
    // `trailing` represents whitespaces, newlines
    // and comments in an empty array or after the trailing comma
    trailing: InternalString,
    trailing_comma: bool,
    // prefix before `[` and suffix after `]`
    decor: Decor,
    // always Vec<Item::Value>
    pub(crate) values: Vec<Item>,
}

/// An owned iterator type over `Table`'s key/value pairs.
pub type ArrayIntoIter = Box<dyn Iterator<Item = Value>>;
/// An iterator type over `Array`'s values.
pub type ArrayIter<'a> = Box<dyn Iterator<Item = &'a Value> + 'a>;
/// An iterator type over `Array`'s values.
pub type ArrayIterMut<'a> = Box<dyn Iterator<Item = &'a mut Value> + 'a>;

/// Constructors
///
/// See also `FromIterator`
impl Array {
    /// Create an empty `Array`
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// ```
    pub fn new() -> Self {
        Default::default()
    }

    pub(crate) fn with_vec(values: Vec<Item>) -> Self {
        Self {
            values,
            ..Default::default()
        }
    }
}

/// Formatting
impl Array {
    /// Auto formats the array.
    pub fn fmt(&mut self) {
        decorate_array(self);
    }

    /// Set whether the array will use a trailing comma
    pub fn set_trailing_comma(&mut self, yes: bool) {
        self.trailing_comma = yes;
    }

    /// Whether the array will use a trailing comma
    pub fn trailing_comma(&self) -> bool {
        self.trailing_comma
    }

    /// Set whitespace after last element
    pub fn set_trailing(&mut self, trailing: &str) {
        self.trailing = trailing.to_owned();
    }

    /// Whitespace after last element
    pub fn trailing(&self) -> &str {
        self.trailing.as_str()
    }

    /// Returns the surrounding whitespace
    pub fn decor_mut(&mut self) -> &mut Decor {
        &mut self.decor
    }

    /// Returns the surrounding whitespace
    pub fn decor(&self) -> &Decor {
        &self.decor
    }
}

impl Array {
    /// Returns an iterator over all values.
    pub fn iter(&self) -> ArrayIter<'_> {
        Box::new(self.values.iter().filter_map(Item::as_value))
    }

    /// Returns an iterator over all values.
    pub fn iter_mut(&mut self) -> ArrayIterMut<'_> {
        Box::new(self.values.iter_mut().filter_map(Item::as_value_mut))
    }

    /// Returns the length of the underlying Vec.
    ///
    /// In some rare cases, placeholder elements will exist.  For a more accurate count, call
    /// `a.iter().count()`
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    /// assert_eq!(arr.len(), 2);
    /// ```
    pub fn len(&self) -> usize {
        self.values.len()
    }

    /// Return true iff `self.len() == 0`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// assert!(arr.is_empty());
    ///
    /// arr.push(1);
    /// arr.push("foo");
    /// assert!(! arr.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Clears the array, removing all values. Keeps the allocated memory for reuse.
    pub fn clear(&mut self) {
        self.values.clear()
    }

    /// Returns a reference to the value at the given index, or `None` if the index is out of
    /// bounds.
    pub fn get(&self, index: usize) -> Option<&Value> {
        self.values.get(index).and_then(Item::as_value)
    }

    /// Returns a reference to the value at the given index, or `None` if the index is out of
    /// bounds.
    pub fn get_mut(&mut self, index: usize) -> Option<&mut Value> {
        self.values.get_mut(index).and_then(Item::as_value_mut)
    }

    /// Appends a new value to the end of the array, applying default formatting to it.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    /// ```
    pub fn push<V: Into<Value>>(&mut self, v: V) {
        self.value_op(v.into(), true, |items, value| {
            items.push(Item::Value(value))
        })
    }

    /// Appends a new, already formatted value to the end of the array.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let formatted_value = "'literal'".parse::<toml_edit::Value>().unwrap();
    /// let mut arr = toml_edit::Array::new();
    /// arr.push_formatted(formatted_value);
    /// ```
    pub fn push_formatted(&mut self, v: Value) {
        self.values.push(Item::Value(v));
    }

    /// Inserts an element at the given position within the array, applying default formatting to
    /// it and shifting all values after it to the right.
    ///
    /// # Panics
    ///
    /// Panics if `index > len`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    ///
    /// arr.insert(0, "start");
    /// ```
    pub fn insert<V: Into<Value>>(&mut self, index: usize, v: V) {
        self.value_op(v.into(), true, |items, value| {
            items.insert(index, Item::Value(value))
        })
    }

    /// Inserts an already formatted value at the given position within the array, shifting all
    /// values after it to the right.
    ///
    /// # Panics
    ///
    /// Panics if `index > len`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    ///
    /// let formatted_value = "'start'".parse::<toml_edit::Value>().unwrap();
    /// arr.insert_formatted(0, formatted_value);
    /// ```
    pub fn insert_formatted(&mut self, index: usize, v: Value) {
        self.values.insert(index, Item::Value(v))
    }

    /// Replaces the element at the given position within the array, preserving existing formatting.
    ///
    /// # Panics
    ///
    /// Panics if `index >= len`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    ///
    /// arr.replace(0, "start");
    /// ```
    pub fn replace<V: Into<Value>>(&mut self, index: usize, v: V) -> Value {
        // Read the existing value's decor and preserve it.
        let existing_decor = self
            .get(index)
            .unwrap_or_else(|| panic!("index {} out of bounds (len = {})", index, self.len()))
            .decor();
        let mut value = v.into();
        *value.decor_mut() = existing_decor.clone();
        self.replace_formatted(index, value)
    }

    /// Replaces the element at the given position within the array with an already formatted value.
    ///
    /// # Panics
    ///
    /// Panics if `index >= len`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    ///
    /// let formatted_value = "'start'".parse::<toml_edit::Value>().unwrap();
    /// arr.replace_formatted(0, formatted_value);
    /// ```
    pub fn replace_formatted(&mut self, index: usize, v: Value) -> Value {
        match mem::replace(&mut self.values[index], Item::Value(v)) {
            Item::Value(old_value) => old_value,
            x => panic!("non-value item {:?} in an array", x),
        }
    }

    /// Removes the value at the given index.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let mut arr = toml_edit::Array::new();
    /// arr.push(1);
    /// arr.push("foo");
    ///
    /// arr.remove(0);
    /// assert_eq!(arr.len(), 1);
    /// ```
    pub fn remove(&mut self, index: usize) -> Value {
        let removed = self.values.remove(index);
        match removed {
            Item::Value(v) => v,
            x => panic!("non-value item {:?} in an array", x),
        }
    }

    fn value_op<T>(
        &mut self,
        v: Value,
        decorate: bool,
        op: impl FnOnce(&mut Vec<Item>, Value) -> T,
    ) -> T {
        let mut value = v;
        if !self.is_empty() && decorate {
            value.decorate(" ", "");
        } else if decorate {
            value.decorate("", "");
        }
        op(&mut self.values, value)
    }
}

impl<V: Into<Value>> Extend<V> for Array {
    fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
        for value in iter {
            self.push_formatted(value.into());
        }
    }
}

impl<V: Into<Value>> FromIterator<V> for Array {
    fn from_iter<I>(iter: I) -> Self
    where
        I: IntoIterator<Item = V>,
    {
        let v = iter.into_iter().map(|a| Item::Value(a.into()));
        Array {
            values: v.collect(),
            ..Default::default()
        }
    }
}

impl IntoIterator for Array {
    type Item = Value;
    type IntoIter = ArrayIntoIter;

    fn into_iter(self) -> Self::IntoIter {
        Box::new(
            self.values
                .into_iter()
                .filter(|v| v.is_value())
                .map(|v| v.into_value().unwrap()),
        )
    }
}

impl<'s> IntoIterator for &'s Array {
    type Item = &'s Value;
    type IntoIter = ArrayIter<'s>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

fn decorate_array(array: &mut Array) {
    for (i, value) in array
        .values
        .iter_mut()
        .filter_map(Item::as_value_mut)
        .enumerate()
    {
        // [value1, value2, value3]
        if i == 0 {
            value.decorate(DEFAULT_LEADING_VALUE_DECOR.0, DEFAULT_LEADING_VALUE_DECOR.1);
        } else {
            value.decorate(DEFAULT_VALUE_DECOR.0, DEFAULT_VALUE_DECOR.1);
        }
    }
}
<|endoftext|>


<commit_before>use std::{fmt::format, path::PathBuf};

use json5;

use crate::config::Config;

pub fn build(in_dir: PathBuf) -> Result<(), String> {
    let data_file = in_dir.join("_data/config.json5");
    let data = std::fs::read_to_string(&data_file)
        .map_err(|e| format!("could not read '{}'\n{}", &data_file.to_string_lossy(), e))?;
    let config: Config = json5::from_str(&data)
        .map_err(|e| format!("could not parse '{}':\n{}", &data_file.display(), e))?;

    dbg!("{}", config);
    Ok(())
}
<commit_msg>Load all Markdown contents from file system<commit_after>use std::path::PathBuf;

use json5;

use crate::config::Config;

pub fn build(in_dir: PathBuf) -> Result<(), String> {
    let data_file = in_dir.join("_data/config.json5");
    let data = std::fs::read_to_string(&data_file)
        .map_err(|e| format!("could not read '{}'\n{}", &data_file.to_string_lossy(), e))?;
    let config: Config = json5::from_str(&data)
        .map_err(|e| format!("could not parse '{}':\n{}", &data_file.display(), e))?;

    dbg!("{}", config);

    let content_dir = in_dir.join("content");
    let content_glob = content_dir.to_string_lossy() + "/**/*.md";
    let all_contents: Vec<Result<String, String>> = glob::glob(&content_glob)
        .expect(&format!("bad glob: '{}'", &content_glob))
        .map(|result| {
            result
                .map_err(|e| format!("{}", e))
                .and_then(|file| std::fs::read_to_string(file).map_err(|e| format!("{}", e)))
        })
        .collect();
    println!("{}", all_contents.len());
    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>internal: remove erroneous Default impl for ModuleOrigin<commit_after><|endoftext|>


<commit_before>//! Prepared statements cache for faster execution.

use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use lru_cache::LruCache;
use {Result, Connection, Statement};
use raw_statement::RawStatement;
use statement::StatementCrateImpl;

impl Connection {
    /// Prepare a SQL statement for execution, returning a previously prepared (but
    /// not currently in-use) statement if one is available. The returned statement
    /// will be cached for reuse by future calls to `prepare_cached` once it is
    /// dropped.
    ///
    /// ```rust,no_run
    /// # use rusqlite::{Connection, Result};
    /// fn insert_new_people(conn: &Connection) -> Result<()> {
    ///     {
    ///         let mut stmt = try!(conn.prepare_cached("INSERT INTO People (name) VALUES (?)"));
    ///         try!(stmt.execute(&[&"Joe Smith"]));
    ///     }
    ///     {
    ///         // This will return the same underlying SQLite statement handle without
    ///         // having to prepare it again.
    ///         let mut stmt = try!(conn.prepare_cached("INSERT INTO People (name) VALUES (?)"));
    ///         try!(stmt.execute(&[&"Bob Jones"]));
    ///     }
    ///     Ok(())
    /// }
    /// ```
    ///
    /// # Failure
    ///
    /// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
    /// underlying SQLite call fails.
    pub fn prepare_cached<'a>(&'a self, sql: &str) -> Result<CachedStatement<'a>> {
        self.cache.get(self, sql)
    }

    /// Set the maximum number of cached prepared statements this connection will hold.
    /// By default, a connection will hold a relatively small number of cached statements.
    /// If you need more, or know that you will not use cached statements, you can set
    /// the capacity manually using this method.
    pub fn set_prepared_statement_cache_capacity(&self, capacity: usize) {
        self.cache.set_capacity(capacity)
    }

    pub fn flush_prepared_statement_cache(&self) {
        self.cache.flush()
    }
}

/// Prepared statements LRU cache.
#[derive(Debug)]
pub struct StatementCache(RefCell<LruCache<String, RawStatement>>);

/// Cacheable statement.
///
/// Statement will return automatically to the cache by default.
/// If you want the statement to be discarded, call `discard()` on it.
pub struct CachedStatement<'conn> {
    stmt: Option<Statement<'conn>>,
    cache: &'conn StatementCache,
}

impl<'conn> Deref for CachedStatement<'conn> {
    type Target = Statement<'conn>;

    fn deref(&self) -> &Statement<'conn> {
        self.stmt.as_ref().unwrap()
    }
}

impl<'conn> DerefMut for CachedStatement<'conn> {
    fn deref_mut(&mut self) -> &mut Statement<'conn> {
        self.stmt.as_mut().unwrap()
    }
}

impl<'conn> Drop for CachedStatement<'conn> {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        if let Some(stmt) = self.stmt.take() {
            self.cache.cache_stmt(stmt.into());
        }
    }
}

impl<'conn> CachedStatement<'conn> {
    fn new(stmt: Statement<'conn>, cache: &'conn StatementCache) -> CachedStatement<'conn> {
        CachedStatement {
            stmt: Some(stmt),
            cache: cache,
        }
    }

    /// Discard the statement, preventing it from being returned to its `Connection`'s collection
    /// of cached statements.
    pub fn discard(mut self) {
        self.stmt = None;
    }
}

impl StatementCache {
    /// Create a statement cache.
    pub fn with_capacity(capacity: usize) -> StatementCache {
        StatementCache(RefCell::new(LruCache::new(capacity)))
    }

    fn set_capacity(&self, capacity: usize) {
        self.0.borrow_mut().set_capacity(capacity)
    }

    // Search the cache for a prepared-statement object that implements `sql`.
    // If no such prepared-statement can be found, allocate and prepare a new one.
    //
    // # Failure
    //
    // Will return `Err` if no cached statement can be found and the underlying SQLite prepare
    // call fails.
    fn get<'conn>(&'conn self,
                  conn: &'conn Connection,
                  sql: &str)
                  -> Result<CachedStatement<'conn>> {
        let mut cache = self.0.borrow_mut();
        let stmt = match cache.remove(sql) {
            Some(raw_stmt) => Ok(Statement::new(conn, raw_stmt)),
            None => conn.prepare(sql),
        };
        stmt.map(|stmt| CachedStatement::new(stmt, self))
    }

    // Return a statement to the cache.
    fn cache_stmt(&self, stmt: RawStatement) {
        let mut cache = self.0.borrow_mut();
        stmt.clear_bindings();
        let sql = String::from_utf8_lossy(stmt.sql().to_bytes()).to_string();
        cache.insert(sql, stmt);
    }

    fn flush(&self) {
        let mut cache = self.0.borrow_mut();
        cache.clear()
    }
}

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

    impl StatementCache {
        fn clear(&self) {
            self.0.borrow_mut().clear();
        }

        fn len(&self) -> usize {
            self.0.borrow().len()
        }

        fn capacity(&self) -> usize {
            self.0.borrow().capacity()
        }
    }

    #[test]
    fn test_cache() {
        let db = Connection::open_in_memory().unwrap();
        let cache = &db.cache;
        let initial_capacity = cache.capacity();
        assert_eq!(0, cache.len());
        assert!(initial_capacity > 0);

        let sql = "PRAGMA schema_version";
        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(1, cache.len());

        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(1, cache.len());

        cache.clear();
        assert_eq!(0, cache.len());
        assert_eq!(initial_capacity, cache.capacity());
    }

    #[test]
    fn test_set_capacity() {
        let db = Connection::open_in_memory().unwrap();
        let cache = &db.cache;

        let sql = "PRAGMA schema_version";
        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(1, cache.len());

        db.set_prepared_statement_cache_capacity(0);
        assert_eq!(0, cache.len());

        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(0, cache.len());

        db.set_prepared_statement_cache_capacity(8);
        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(1, cache.len());
    }

    #[test]
    fn test_discard() {
        let db = Connection::open_in_memory().unwrap();
        let cache = &db.cache;

        let sql = "PRAGMA schema_version";
        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
            stmt.discard();
        }
        assert_eq!(0, cache.len());
    }

    #[test]
    fn test_ddl() {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch(r#"
            CREATE TABLE foo (x INT);
            INSERT INTO foo VALUES (1);
        "#)
            .unwrap();

        let sql = "SELECT * FROM foo";

        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(1i32,
                       stmt.query_map::<i32, _>(&[], |r| r.get(0))
                           .unwrap()
                           .next()
                           .unwrap()
                           .unwrap());
        }

        db.execute_batch(r#"
            ALTER TABLE foo ADD COLUMN y INT;
            UPDATE foo SET y = 2;
        "#)
            .unwrap();

        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!((1i32, 2i32),
                       stmt.query_map(&[], |r| (r.get(0), r.get(1)))
                           .unwrap()
                           .next()
                           .unwrap()
                           .unwrap());
        }
    }

    #[test]
    fn test_connection_close() {
        let conn = Connection::open_in_memory().unwrap();
        conn.prepare_cached("SELECT * FROM sqlite_master;")
            .unwrap();

        conn.close().expect("connection not closed");
    }
}
<commit_msg>Fix statement cache<commit_after>//! Prepared statements cache for faster execution.

use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use lru_cache::LruCache;
use {Result, Connection, Statement};
use raw_statement::RawStatement;
use statement::StatementCrateImpl;

impl Connection {
    /// Prepare a SQL statement for execution, returning a previously prepared (but
    /// not currently in-use) statement if one is available. The returned statement
    /// will be cached for reuse by future calls to `prepare_cached` once it is
    /// dropped.
    ///
    /// ```rust,no_run
    /// # use rusqlite::{Connection, Result};
    /// fn insert_new_people(conn: &Connection) -> Result<()> {
    ///     {
    ///         let mut stmt = try!(conn.prepare_cached("INSERT INTO People (name) VALUES (?)"));
    ///         try!(stmt.execute(&[&"Joe Smith"]));
    ///     }
    ///     {
    ///         // This will return the same underlying SQLite statement handle without
    ///         // having to prepare it again.
    ///         let mut stmt = try!(conn.prepare_cached("INSERT INTO People (name) VALUES (?)"));
    ///         try!(stmt.execute(&[&"Bob Jones"]));
    ///     }
    ///     Ok(())
    /// }
    /// ```
    ///
    /// # Failure
    ///
    /// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
    /// underlying SQLite call fails.
    pub fn prepare_cached<'a>(&'a self, sql: &str) -> Result<CachedStatement<'a>> {
        self.cache.get(self, sql)
    }

    /// Set the maximum number of cached prepared statements this connection will hold.
    /// By default, a connection will hold a relatively small number of cached statements.
    /// If you need more, or know that you will not use cached statements, you can set
    /// the capacity manually using this method.
    pub fn set_prepared_statement_cache_capacity(&self, capacity: usize) {
        self.cache.set_capacity(capacity)
    }

    /// Remove/finalize all prepared statements currently in the cache.
    pub fn flush_prepared_statement_cache(&self) {
        self.cache.flush()
    }
}

/// Prepared statements LRU cache.
#[derive(Debug)]
pub struct StatementCache(RefCell<LruCache<String, RawStatement>>);

/// Cacheable statement.
///
/// Statement will return automatically to the cache by default.
/// If you want the statement to be discarded, call `discard()` on it.
pub struct CachedStatement<'conn> {
    stmt: Option<Statement<'conn>>,
    cache: &'conn StatementCache,
}

impl<'conn> Deref for CachedStatement<'conn> {
    type Target = Statement<'conn>;

    fn deref(&self) -> &Statement<'conn> {
        self.stmt.as_ref().unwrap()
    }
}

impl<'conn> DerefMut for CachedStatement<'conn> {
    fn deref_mut(&mut self) -> &mut Statement<'conn> {
        self.stmt.as_mut().unwrap()
    }
}

impl<'conn> Drop for CachedStatement<'conn> {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        if let Some(stmt) = self.stmt.take() {
            self.cache.cache_stmt(stmt.into());
        }
    }
}

impl<'conn> CachedStatement<'conn> {
    fn new(stmt: Statement<'conn>, cache: &'conn StatementCache) -> CachedStatement<'conn> {
        CachedStatement {
            stmt: Some(stmt),
            cache: cache,
        }
    }

    /// Discard the statement, preventing it from being returned to its `Connection`'s collection
    /// of cached statements.
    pub fn discard(mut self) {
        self.stmt = None;
    }
}

impl StatementCache {
    /// Create a statement cache.
    pub fn with_capacity(capacity: usize) -> StatementCache {
        StatementCache(RefCell::new(LruCache::new(capacity)))
    }

    fn set_capacity(&self, capacity: usize) {
        self.0.borrow_mut().set_capacity(capacity)
    }

    // Search the cache for a prepared-statement object that implements `sql`.
    // If no such prepared-statement can be found, allocate and prepare a new one.
    //
    // # Failure
    //
    // Will return `Err` if no cached statement can be found and the underlying SQLite prepare
    // call fails.
    fn get<'conn>(&'conn self,
                  conn: &'conn Connection,
                  sql: &str)
                  -> Result<CachedStatement<'conn>> {
        let mut cache = self.0.borrow_mut();
        let stmt = match cache.remove(sql.trim()) {
            Some(raw_stmt) => Ok(Statement::new(conn, raw_stmt)),
            None => conn.prepare(sql),
        };
        stmt.map(|stmt| CachedStatement::new(stmt, self))
    }

    // Return a statement to the cache.
    fn cache_stmt(&self, stmt: RawStatement) {
        let mut cache = self.0.borrow_mut();
        stmt.clear_bindings();
        let sql = String::from_utf8_lossy(stmt.sql().to_bytes()).trim().to_string();
        cache.insert(sql, stmt);
    }

    fn flush(&self) {
        let mut cache = self.0.borrow_mut();
        cache.clear()
    }
}

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

    impl StatementCache {
        fn clear(&self) {
            self.0.borrow_mut().clear();
        }

        fn len(&self) -> usize {
            self.0.borrow().len()
        }

        fn capacity(&self) -> usize {
            self.0.borrow().capacity()
        }
    }

    #[test]
    fn test_cache() {
        let db = Connection::open_in_memory().unwrap();
        let cache = &db.cache;
        let initial_capacity = cache.capacity();
        assert_eq!(0, cache.len());
        assert!(initial_capacity > 0);

        let sql = "PRAGMA schema_version";
        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(1, cache.len());

        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(1, cache.len());

        cache.clear();
        assert_eq!(0, cache.len());
        assert_eq!(initial_capacity, cache.capacity());
    }

    #[test]
    fn test_set_capacity() {
        let db = Connection::open_in_memory().unwrap();
        let cache = &db.cache;

        let sql = "PRAGMA schema_version";
        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(1, cache.len());

        db.set_prepared_statement_cache_capacity(0);
        assert_eq!(0, cache.len());

        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(0, cache.len());

        db.set_prepared_statement_cache_capacity(8);
        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(1, cache.len());
    }

    #[test]
    fn test_discard() {
        let db = Connection::open_in_memory().unwrap();
        let cache = &db.cache;

        let sql = "PRAGMA schema_version";
        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
            stmt.discard();
        }
        assert_eq!(0, cache.len());
    }

    #[test]
    fn test_ddl() {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch(r#"
            CREATE TABLE foo (x INT);
            INSERT INTO foo VALUES (1);
        "#)
            .unwrap();

        let sql = "SELECT * FROM foo";

        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(1i32,
                       stmt.query_map::<i32, _>(&[], |r| r.get(0))
                           .unwrap()
                           .next()
                           .unwrap()
                           .unwrap());
        }

        db.execute_batch(r#"
            ALTER TABLE foo ADD COLUMN y INT;
            UPDATE foo SET y = 2;
        "#)
            .unwrap();

        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!((1i32, 2i32),
                       stmt.query_map(&[], |r| (r.get(0), r.get(1)))
                           .unwrap()
                           .next()
                           .unwrap()
                           .unwrap());
        }
    }

    #[test]
    fn test_connection_close() {
        let conn = Connection::open_in_memory().unwrap();
        conn.prepare_cached("SELECT * FROM sqlite_master;")
            .unwrap();

        conn.close().expect("connection not closed");
    }

    #[test]
    fn test_cache_key() {
        let db = Connection::open_in_memory().unwrap();
        let cache = &db.cache;
        assert_eq!(0, cache.len());

        //let sql = " PRAGMA schema_version; -- comment";
        let sql = "PRAGMA schema_version; ";
        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(1, cache.len());

        {
            let mut stmt = db.prepare_cached(sql).unwrap();
            assert_eq!(0, cache.len());
            assert_eq!(0, stmt.query_row(&[], |r| r.get::<i32, i64>(0)).unwrap());
        }
        assert_eq!(1, cache.len());
    }
}
<|endoftext|>


<commit_before>//! Exposes the `chain` trait and `StackChain` type.

use std::fmt::Show;

use super::response::Response;
use super::request::Request;
use super::alloy::Alloy;
use super::middleware::{Middleware, Status, Continue, Error};

/// `chains` are the backbone of `Iron`. They coordinate `Middleware`
/// to ensure they are resolved and called in the right order,
/// create and distribute `Alloys`, and handle incoming requests.
///
/// `chains` are internal tools. Unless you want additional
/// or unusual behavior such as enhanced debug logging you
/// probably don't need to mess with `chain` internals.
///
/// That being said, custom `chains` are extremely powerful as they
/// allow you to completely control the resolution of `Middleware`.
pub trait Chain: Send + Clone {
    /// `dispatch` will be called once per `Request`, and may be
    /// called either with or without an existing `Alloy`. `dispatch` is responsible
    /// for delegating the request to the correct `Middleware` and in the correct
    /// order. Effectively, 99% of the work done by a `chain` is done here.
    fn dispatch(&mut self,
                request: &mut Request,
                response: &mut Response,
                opt_alloy: Option<&mut Alloy>) -> Status {
        let mut alloy = &mut Alloy::new();
        match opt_alloy {
            Some(a) => alloy = a,
            None => ()
        };

        let mut status = self.chain_enter(request, response, alloy);
        match status {
            Error(ref mut e) => {
                let error: &mut Show = *e;
                let _ = self.chain_error(request, response, alloy, error);
            },
            _ => {
                let _ = self.chain_exit(request, response, alloy);
            }
        };

        status
    }

    #[doc(hidden)]
    fn chain_enter(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status;

    #[doc(hidden)]
    fn chain_exit(&mut self,
                  _request: &mut Request,
                  _response: &mut Response,
                  _alloy: &mut Alloy) -> Status {
        Continue
    }

    #[doc(hidden)]
    fn chain_error(&mut self,
                  _request: &mut Request,
                  _response: &mut Response,
                  _alloy: &mut Alloy,
                  _error: &mut Show) { () }

    /// `link` is responsible for adding new `Middleware` to the `chain's` internal
    /// storage of `Middleware`. Different `chains` may implement different behavior
    /// for `link`, but - ideally - `Middleware` added here will be delegated to during
    /// `Requests`.
    fn link<M: Middleware>(&mut self, _middleware: M);

    /// Create a new instance of `chain`.
    fn new() -> Self;

    #[doc(hidden)]
    fn clone_box(&self) -> Box<Chain + Send> { box self.clone() as Box<Chain + Send> }
}

impl Clone for Box<Chain + Send> {
    fn clone(&self) -> Box<Chain + Send> { self.clone_box() }
}

/// The default `chain` used by `Iron`.
pub mod stackchain {
    use std::fmt::Show;

    use super::super::request::Request;
    use super::super::response::Response;
    use super::super::middleware::{Middleware, Continue, Unwind, Error, Status};
    use super::super::alloy::Alloy;

    use super::Chain;

    /// The default `Chain` used by `Iron`.
    /// `StackChain` runs each `Request` through all `Middleware` in its stack.
    ///
    /// When it hits `Middleware` which returns `Unwind`, it passes
    /// the `Request` back up through all `Middleware` it has hit so far.
    ///
    /// If no `Middleware` return `Unwind` to indicate that they handled
    /// the request, then a 404 is automatically returned.
    #[deriving(Clone)]
    pub struct StackChain {
        /// The storage used by `StackChain` to hold all `Middleware`
        /// that have been `linked` to it.
        stack: Vec<Box<Middleware + Send>>,
        status: ChainStatus,
    }

    #[deriving(Clone)]
    enum ChainStatus { Unwound(uint), Errored(uint), Unhandled }

    /// `StackChain` is a `Chain`
    impl Chain for StackChain {
        fn dispatch(&mut self,
                    request: &mut Request,
                    response: &mut Response,
                    opt_alloy: Option<&mut Alloy>) -> Status {
            let mut alloy = &mut Alloy::new();
            match opt_alloy {
                Some(a) => alloy = a,
                None => ()
            };

            let mut status = self.chain_enter(request, response, alloy);
            match status {
                Error(ref mut e) => {
                    let error: &mut Show = *e;
                    let _ = self.chain_error(request, response, alloy, error);
                },
                Continue => {
                    // If no middleware returned unwind, or errored
                    // then we send a 404.
                    //
                    // At least one middleware should return unwind when a
                    // terminal endpoint, such as a router, has been reached.
                    //
                    // We don't write to the body as other middleware may want
                    // to change headers.
                    response.status = ::http::status::NotFound;
                }
                Unwind => {
                    let _ = self.chain_exit(request, response, alloy);
                }
            };

            status
        }

        fn chain_enter(&mut self,
                 request: &mut Request,
                 response: &mut Response,
                 alloy: &mut Alloy) -> Status {
            // The `exit_stack` will hold all `Middleware` that are passed through
            // in the enter loop. This is so we know to take exactly the same
            // path through `Middleware` in reverse order than we did on the way in.
            self.status = Unhandled;

            'enter: for (i, middleware) in self.stack.mut_iter().enumerate() {
                match middleware.enter(request, response, alloy) {
                    Unwind   => {
                        self.status = Unwound(i);
                        return Unwind;
                    },
                    e @ Error(_) => {
                        self.status = Errored(i);
                        return e;
                    }
                    // Mark the middleware for traversal on exit.
                    Continue => ()
                }
            }

            self.status = Unhandled;
            Continue
        }

        fn chain_exit(&mut self,
                 request: &mut Request,
                 response: &mut Response,
                 alloy: &mut Alloy) -> Status {
            match self.status {
                Unwound(i) => {
                    for middleware in self.stack.mut_slice_to(i).mut_iter().rev() {
                        let _ = middleware.exit(request, response, alloy);
                    }
                },
                Unhandled => {
                    for middleware in self.stack.mut_iter().rev() {
                        let _ = middleware.exit(request, response, alloy);
                    }
                },
                Errored(_) => fail!("chain_exit called on a StackChain which Errored.")
            }

            Continue
        }

        fn chain_error(&mut self,
                      request: &mut Request,
                      response: &mut Response,
                      alloy: &mut Alloy,
                      error: &mut Show) {
            match self.status {
                Errored(i) => {
                    for middleware in self.stack.mut_slice_to(i).mut_iter().rev() {
                        let _ = middleware.on_error(request, response, alloy, error);
                    }
                },
                _ => fail!("chain_error called on a chain which did not error.")
            }
        }

        /// Add `Middleware` to the `Chain`.
        fn link<M: Middleware>(&mut self, middleware: M) {
            self.stack.push(box middleware);
        }

        /// Create a new instance of `StackChain`.
        fn new() -> StackChain {
            StackChain {
                stack: vec![],
                status: Unhandled
            }
        }
    }

    impl FromIterator<Box<Middleware + Send>> for StackChain {
        fn from_iter<T: Iterator<Box<Middleware + Send>>>(mut iterator: T) -> StackChain {
            StackChain {
                stack: iterator.collect(),
                status: Unhandled
            }
        }
    }

    #[cfg(test)]
    mod test {
        pub use super::*;
        pub use super::super::super::request::Request;
        pub use super::super::super::response::Response;
        pub use super::super::super::alloy::Alloy;
        pub use super::super::super::middleware::{Middleware, Status, Continue, Unwind};
        pub use std::sync::{Arc, Mutex};

        #[deriving(Clone)]
        pub struct CallCount {
            enter: Arc<Mutex<u64>>,
            exit: Arc<Mutex<u64>>
        }

        impl Middleware for CallCount {
            fn enter(&mut self, _req: &mut Request,
                     _res: &mut Response, _alloy: &mut Alloy) -> Status {
                let mut enter = self.enter.lock();
                *enter += 1;
                Continue
            }

            fn exit(&mut self, _req: &mut Request,
                    _res: &mut Response, _alloy: &mut Alloy) -> Status {
                let mut exit = self.exit.lock();
                *exit += 1;
                Continue
            }
        }

        #[deriving(Clone)]
        pub struct Stopper;

        impl Middleware for Stopper {
            fn enter(&mut self, _req: &mut Request,
                     _res: &mut Response, _alloy: &mut Alloy) -> Status {
                Unwind // Stop .status from being accessed, which fails.
            }
        }

        mod dispatch {
            use super::{CallCount, Arc, Mutex, Stopper};
            use super::super::StackChain;
            use super::super::super::Chain;
            use std::mem::{uninitialized};

            #[test]
            fn calls_middleware_enter() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
                testchain.link(Stopper);
                unsafe {
                    let _ = testchain.dispatch(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*enter.lock(), 1);
            }

            #[test]
            fn calls_middleware_exit() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
                testchain.link(Stopper);
                unsafe {
                    let _ = testchain.dispatch(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*exit.lock(), 1);
            }

            #[test]
            fn calls_all_middleware_enter_exit() {
                let mut testchain: StackChain = Chain::new();
                let enter_exits: Vec<(Arc<Mutex<u64>>, Arc<Mutex<u64>>)> = vec![];

                for _ in range(0u8, 10) {
                    let (enter, exit) = (Arc::new(Mutex::new(0)), Arc::new(Mutex::new(0)));
                    testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
                }

                testchain.link(Stopper);
                unsafe {
                    let _ = testchain.dispatch(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }

                for (enter, exit) in enter_exits.move_iter() {
                    assert_eq!(*enter.lock(), 1);
                    assert_eq!(*exit.lock(), 1);
                }
            }
        }

        mod chain_enter {
            use super::{CallCount, Arc, Mutex, Stopper};
            use super::super::StackChain;
            use super::super::super::Chain;
            use std::mem::{uninitialized};

            #[test]
            fn calls_middleware_enter() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
                testchain.link(Stopper);
                unsafe {
                    let _ = testchain.chain_enter(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*enter.lock(), 1);
            }

            #[test]
            fn doesnt_call_middleware_exit() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
                testchain.link(Stopper);
                unsafe {
                    let _ = testchain.chain_enter(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*exit.lock(), 0);
            }
        }

        mod chain_exit {
            use super::{CallCount, Arc, Mutex, Stopper};
            use super::super::{StackChain, Unwound};
            use super::super::super::Chain;
            use std::mem::uninitialized;

            #[test]
            fn calls_middleware_exit() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount {
                    enter: enter.clone(), exit: exit.clone()
                });
                testchain.link(Stopper);
                unsafe {
                    let _  = testchain.chain_enter(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );

                    let _  = testchain.chain_exit(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*exit.lock(), 1);
            }

            #[test]
            fn doesnt_call_middleware_enter() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount {
                    enter: enter.clone(), exit: exit.clone()
                });
                testchain.status = Unwound(1);
                unsafe {
                    let _  = testchain.chain_exit(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*enter.lock(), 0);
            }
        }

        mod bench {
            use super::super::super::super::middleware::Middleware;
            pub use super::Stopper;

            #[deriving(Clone)]
            struct Noop;

            impl Middleware for Noop {}

            macro_rules! bench_noop_x (
                ($name:ident, $num:expr, $method:ident) => {
                    #[bench]
                    fn $name(b: &mut Bencher) {
                        let mut testchain: StackChain = Chain::new();
                        for _ in range(0, $num) {
                            testchain.link(Noop);
                        }
                        testchain.link(Stopper);
                        b.iter(|| {
                            black_box(unsafe {
                                let _ = testchain.$method(
                                    uninitialized(),
                                    uninitialized(),
                                    uninitialized()
                                );
                            })
                        });
                    }
                }
            )

            macro_rules! bench_method (
                ($method:ident) => {
                    mod $method {
                        use std::mem::uninitialized;
                        use test::{Bencher, black_box};
                        use super::{Noop, Stopper};
                        use super::super::super::StackChain;
                        use super::super::super::super::Chain;

                        bench_noop_x!(bench_empty, 0u8, $method)
                        bench_noop_x!(bench_1, 1u8, $method)
                        bench_noop_x!(bench_2, 2u8, $method)
                        bench_noop_x!(bench_3, 3u8, $method)
                        bench_noop_x!(bench_4, 4u8, $method)
                        bench_noop_x!(bench_10, 10u8, $method)
                        bench_noop_x!(bench_100, 100u8, $method)
                    }
                }
            )

            bench_method!(dispatch)
            bench_method!(chain_enter)
        }
    }
}
<commit_msg>(cleanup) Move automatic 404 generation.<commit_after>//! Exposes the `chain` trait and `StackChain` type.

use std::fmt::Show;

use super::response::Response;
use super::request::Request;
use super::alloy::Alloy;
use super::middleware::{Middleware, Status, Continue, Error};

/// `chains` are the backbone of `Iron`. They coordinate `Middleware`
/// to ensure they are resolved and called in the right order,
/// create and distribute `Alloys`, and handle incoming requests.
///
/// `chains` are internal tools. Unless you want additional
/// or unusual behavior such as enhanced debug logging you
/// probably don't need to mess with `chain` internals.
///
/// That being said, custom `chains` are extremely powerful as they
/// allow you to completely control the resolution of `Middleware`.
pub trait Chain: Send + Clone {
    /// `dispatch` will be called once per `Request`, and may be
    /// called either with or without an existing `Alloy`. `dispatch` is responsible
    /// for delegating the request to the correct `Middleware` and in the correct
    /// order. Effectively, 99% of the work done by a `chain` is done here.
    fn dispatch(&mut self,
                request: &mut Request,
                response: &mut Response,
                opt_alloy: Option<&mut Alloy>) -> Status {
        let mut alloy = &mut Alloy::new();
        match opt_alloy {
            Some(a) => alloy = a,
            None => ()
        };

        let mut status = self.chain_enter(request, response, alloy);
        match status {
            Error(ref mut e) => {
                let error: &mut Show = *e;
                let _ = self.chain_error(request, response, alloy, error);
            },
            _ => {
                let _ = self.chain_exit(request, response, alloy);
            }
        };

        status
    }

    #[doc(hidden)]
    fn chain_enter(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status;

    #[doc(hidden)]
    fn chain_exit(&mut self,
                  _request: &mut Request,
                  _response: &mut Response,
                  _alloy: &mut Alloy) -> Status {
        Continue
    }

    #[doc(hidden)]
    fn chain_error(&mut self,
                  _request: &mut Request,
                  _response: &mut Response,
                  _alloy: &mut Alloy,
                  _error: &mut Show) { () }

    /// `link` is responsible for adding new `Middleware` to the `chain's` internal
    /// storage of `Middleware`. Different `chains` may implement different behavior
    /// for `link`, but - ideally - `Middleware` added here will be delegated to during
    /// `Requests`.
    fn link<M: Middleware>(&mut self, _middleware: M);

    /// Create a new instance of `chain`.
    fn new() -> Self;

    #[doc(hidden)]
    fn clone_box(&self) -> Box<Chain + Send> { box self.clone() as Box<Chain + Send> }
}

impl Clone for Box<Chain + Send> {
    fn clone(&self) -> Box<Chain + Send> { self.clone_box() }
}

/// The default `chain` used by `Iron`.
pub mod stackchain {
    use std::fmt::Show;

    use super::super::request::Request;
    use super::super::response::Response;
    use super::super::middleware::{Middleware, Continue, Unwind, Error, Status};
    use super::super::alloy::Alloy;

    use super::Chain;

    /// The default `Chain` used by `Iron`.
    /// `StackChain` runs each `Request` through all `Middleware` in its stack.
    ///
    /// When it hits `Middleware` which returns `Unwind`, it passes
    /// the `Request` back up through all `Middleware` it has hit so far.
    ///
    /// If no `Middleware` return `Unwind` to indicate that they handled
    /// the request, then a 404 is automatically returned.
    #[deriving(Clone)]
    pub struct StackChain {
        /// The storage used by `StackChain` to hold all `Middleware`
        /// that have been `linked` to it.
        stack: Vec<Box<Middleware + Send>>,
        status: ChainStatus,
    }

    #[deriving(Clone)]
    enum ChainStatus { Unwound(uint), Errored(uint), Unhandled }

    /// `StackChain` is a `Chain`
    impl Chain for StackChain {
        fn dispatch(&mut self,
                    request: &mut Request,
                    response: &mut Response,
                    opt_alloy: Option<&mut Alloy>) -> Status {
            let mut alloy = &mut Alloy::new();
            match opt_alloy {
                Some(a) => alloy = a,
                None => ()
            };

            let mut status = self.chain_enter(request, response, alloy);
            match status {
                Error(ref mut e) => {
                    let error: &mut Show = *e;
                    let _ = self.chain_error(request, response, alloy, error);
                },
                _ => {
                    let _ = self.chain_exit(request, response, alloy);
                }
            };

            status
        }

        fn chain_enter(&mut self,
                 request: &mut Request,
                 response: &mut Response,
                 alloy: &mut Alloy) -> Status {
            // The `exit_stack` will hold all `Middleware` that are passed through
            // in the enter loop. This is so we know to take exactly the same
            // path through `Middleware` in reverse order than we did on the way in.
            self.status = Unhandled;

            'enter: for (i, middleware) in self.stack.mut_iter().enumerate() {
                match middleware.enter(request, response, alloy) {
                    Unwind   => {
                        self.status = Unwound(i);
                        return Unwind;
                    },
                    e @ Error(_) => {
                        self.status = Errored(i);
                        return e;
                    }
                    // Mark the middleware for traversal on exit.
                    Continue => ()
                }
            }

            self.status = Unhandled;
            Continue
        }

        fn chain_exit(&mut self,
                 request: &mut Request,
                 response: &mut Response,
                 alloy: &mut Alloy) -> Status {
            match self.status {
                Unwound(i) => {
                    for middleware in self.stack.mut_slice_to(i).mut_iter().rev() {
                        let _ = middleware.exit(request, response, alloy);
                    }
                },
                Unhandled => {
                    for middleware in self.stack.mut_iter().rev() {
                        let _ = middleware.exit(request, response, alloy);
                    }
                },
                Errored(_) => fail!("chain_exit called on a StackChain which Errored.")
            }

            Continue
        }

        fn chain_error(&mut self,
                      request: &mut Request,
                      response: &mut Response,
                      alloy: &mut Alloy,
                      error: &mut Show) {
            match self.status {
                Errored(i) => {
                    for middleware in self.stack.mut_slice_to(i).mut_iter().rev() {
                        let _ = middleware.on_error(request, response, alloy, error);
                    }
                },
                _ => fail!("chain_error called on a chain which did not error.")
            }
        }

        /// Add `Middleware` to the `Chain`.
        fn link<M: Middleware>(&mut self, middleware: M) {
            self.stack.push(box middleware);
        }

        /// Create a new instance of `StackChain`.
        fn new() -> StackChain {
            StackChain {
                stack: vec![],
                status: Unhandled
            }
        }
    }

    impl FromIterator<Box<Middleware + Send>> for StackChain {
        fn from_iter<T: Iterator<Box<Middleware + Send>>>(mut iterator: T) -> StackChain {
            StackChain {
                stack: iterator.collect(),
                status: Unhandled
            }
        }
    }

    #[cfg(test)]
    mod test {
        pub use super::*;
        pub use super::super::super::request::Request;
        pub use super::super::super::response::Response;
        pub use super::super::super::alloy::Alloy;
        pub use super::super::super::middleware::{Middleware, Status, Continue, Unwind};
        pub use std::sync::{Arc, Mutex};

        #[deriving(Clone)]
        pub struct CallCount {
            enter: Arc<Mutex<u64>>,
            exit: Arc<Mutex<u64>>
        }

        impl Middleware for CallCount {
            fn enter(&mut self, _req: &mut Request,
                     _res: &mut Response, _alloy: &mut Alloy) -> Status {
                let mut enter = self.enter.lock();
                *enter += 1;
                Continue
            }

            fn exit(&mut self, _req: &mut Request,
                    _res: &mut Response, _alloy: &mut Alloy) -> Status {
                let mut exit = self.exit.lock();
                *exit += 1;
                Continue
            }
        }

        #[deriving(Clone)]
        pub struct Stopper;

        impl Middleware for Stopper {
            fn enter(&mut self, _req: &mut Request,
                     _res: &mut Response, _alloy: &mut Alloy) -> Status {
                Unwind // Stop .status from being accessed, which fails.
            }
        }

        mod dispatch {
            use super::{CallCount, Arc, Mutex, Stopper};
            use super::super::StackChain;
            use super::super::super::Chain;
            use std::mem::{uninitialized};

            #[test]
            fn calls_middleware_enter() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
                testchain.link(Stopper);
                unsafe {
                    let _ = testchain.dispatch(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*enter.lock(), 1);
            }

            #[test]
            fn calls_middleware_exit() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
                testchain.link(Stopper);
                unsafe {
                    let _ = testchain.dispatch(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*exit.lock(), 1);
            }

            #[test]
            fn calls_all_middleware_enter_exit() {
                let mut testchain: StackChain = Chain::new();
                let enter_exits: Vec<(Arc<Mutex<u64>>, Arc<Mutex<u64>>)> = vec![];

                for _ in range(0u8, 10) {
                    let (enter, exit) = (Arc::new(Mutex::new(0)), Arc::new(Mutex::new(0)));
                    testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
                }

                testchain.link(Stopper);
                unsafe {
                    let _ = testchain.dispatch(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }

                for (enter, exit) in enter_exits.move_iter() {
                    assert_eq!(*enter.lock(), 1);
                    assert_eq!(*exit.lock(), 1);
                }
            }
        }

        mod chain_enter {
            use super::{CallCount, Arc, Mutex, Stopper};
            use super::super::StackChain;
            use super::super::super::Chain;
            use std::mem::{uninitialized};

            #[test]
            fn calls_middleware_enter() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
                testchain.link(Stopper);
                unsafe {
                    let _ = testchain.chain_enter(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*enter.lock(), 1);
            }

            #[test]
            fn doesnt_call_middleware_exit() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
                testchain.link(Stopper);
                unsafe {
                    let _ = testchain.chain_enter(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*exit.lock(), 0);
            }
        }

        mod chain_exit {
            use super::{CallCount, Arc, Mutex, Stopper};
            use super::super::{StackChain, Unwound};
            use super::super::super::Chain;
            use std::mem::uninitialized;

            #[test]
            fn calls_middleware_exit() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount {
                    enter: enter.clone(), exit: exit.clone()
                });
                testchain.link(Stopper);
                unsafe {
                    let _  = testchain.chain_enter(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );

                    let _  = testchain.chain_exit(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*exit.lock(), 1);
            }

            #[test]
            fn doesnt_call_middleware_enter() {
                let mut testchain: StackChain = Chain::new();
                let enter = Arc::new(Mutex::new(0));
                let exit = Arc::new(Mutex::new(0));
                testchain.link(CallCount {
                    enter: enter.clone(), exit: exit.clone()
                });
                testchain.status = Unwound(1);
                unsafe {
                    let _  = testchain.chain_exit(
                        uninitialized(),
                        uninitialized(),
                        uninitialized()
                    );
                }
                assert_eq!(*enter.lock(), 0);
            }
        }

        mod bench {
            use super::super::super::super::middleware::Middleware;
            pub use super::Stopper;

            #[deriving(Clone)]
            struct Noop;

            impl Middleware for Noop {}

            macro_rules! bench_noop_x (
                ($name:ident, $num:expr, $method:ident) => {
                    #[bench]
                    fn $name(b: &mut Bencher) {
                        let mut testchain: StackChain = Chain::new();
                        for _ in range(0, $num) {
                            testchain.link(Noop);
                        }
                        testchain.link(Stopper);
                        b.iter(|| {
                            black_box(unsafe {
                                let _ = testchain.$method(
                                    uninitialized(),
                                    uninitialized(),
                                    uninitialized()
                                );
                            })
                        });
                    }
                }
            )

            macro_rules! bench_method (
                ($method:ident) => {
                    mod $method {
                        use std::mem::uninitialized;
                        use test::{Bencher, black_box};
                        use super::{Noop, Stopper};
                        use super::super::super::StackChain;
                        use super::super::super::super::Chain;

                        bench_noop_x!(bench_empty, 0u8, $method)
                        bench_noop_x!(bench_1, 1u8, $method)
                        bench_noop_x!(bench_2, 2u8, $method)
                        bench_noop_x!(bench_3, 3u8, $method)
                        bench_noop_x!(bench_4, 4u8, $method)
                        bench_noop_x!(bench_10, 10u8, $method)
                        bench_noop_x!(bench_100, 100u8, $method)
                    }
                }
            )

            bench_method!(dispatch)
            bench_method!(chain_enter)
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign};

use cgmath::prelude::*;
use cgmath::Vector3;

use crate::util::ConvArr;
use crate::Float;

/// Convert u8 color to float color in range [0, 1]
pub fn to_float(c: u8) -> Float {
    Float::from(c) / 255.0
}

/// Convert srgb color to linear color
fn to_linear(c: Float) -> Float {
    c.powf(2.2)
}

#[derive(Clone, Copy, Debug)]
pub struct SrgbColor(BaseColor);

impl SrgbColor {
    pub fn from_pixel(rgb: image::Rgb<u8>) -> Self {
        Self(BaseColor::from_pixel(rgb))
    }

    pub fn is_gray(&self) -> bool {
        self.0.is_gray()
    }

    pub fn to_linear(self) -> Color {
        Color(self.0.to_linear())
    }

    pub fn to_vec(self) -> Vector3<Float> {
        self.0.color
    }
}

#[derive(Clone, Copy, Debug)]
pub struct Color(BaseColor);

impl Color {
    pub fn black() -> Self {
        Self(BaseColor::black())
    }

    pub fn white() -> Self {
        Self(BaseColor::white())
    }

    pub fn from_normal(n: Vector3<Float>) -> Self {
        let c_vec = (0.5 * n).add_element_wise(0.5);
        Self(BaseColor::from(c_vec))
    }

    pub fn luma(&self) -> Float {
        self.0.luma()
    }

    pub fn is_black(&self) -> bool {
        self.0.is_black()
    }

    pub fn r(&self) -> Float {
        self.0.r()
    }

    pub fn g(&self) -> Float {
        self.0.g()
    }

    pub fn b(&self) -> Float {
        self.0.b()
    }
}

#[derive(Clone, Copy, Debug)]
struct BaseColor {
    color: Vector3<Float>,
}

impl BaseColor {
    fn new(r: Float, g: Float, b: Float) -> Self {
        Self {
            color: Vector3::new(r, g, b),
        }
    }

    fn black() -> Self {
        Self::new(0.0, 0.0, 0.0)
    }

    fn white() -> Self {
        Self::new(1.0, 1.0, 1.0)
    }

    fn from_pixel(rgb: image::Rgb<u8>) -> Self {
        Self::new(
            to_float(rgb.data[0]),
            to_float(rgb.data[1]),
            to_float(rgb.data[2]),
        )
    }

    fn to_linear(self) -> Self {
        Self::new(
            to_linear(self.color[0]),
            to_linear(self.color[1]),
            to_linear(self.color[2]),
        )
    }

    fn luma(&self) -> Float {
        let luma_vec = Vector3::new(0.2126, 0.7152, 0.0722);
        luma_vec.dot(self.color)
    }

    fn is_black(&self) -> bool {
        self.color.x == 0.0 && self.color.y == 0.0 && self.color.z == 0.0
    }

    fn is_gray(&self) -> bool {
        self.color.x == self.color.y && self.color.y == self.color.z
    }

    fn r(&self) -> Float {
        self.color.x
    }

    fn g(&self) -> Float {
        self.color.y
    }

    fn b(&self) -> Float {
        self.color.z
    }
}

impl Index<usize> for BaseColor {
    type Output = Float;

    fn index(&self, i: usize) -> &Float {
        &self.color[i]
    }
}

impl IndexMut<usize> for BaseColor {
    fn index_mut(&mut self, i: usize) -> &mut Float {
        &mut self.color[i]
    }
}

impl From<Vector3<Float>> for BaseColor {
    #[allow(clippy::identity_conversion)]
    fn from(vec: Vector3<Float>) -> Self {
        Self { color: vec }
    }
}

impl From<[f32; 3]> for BaseColor {
    #[allow(clippy::identity_conversion)]
    fn from(arr: [f32; 3]) -> Self {
        Self {
            color: Vector3::from_arr(arr),
        }
    }
}

impl Into<[f32; 3]> for BaseColor {
    fn into(self) -> [f32; 3] {
        self.color.into_arr()
    }
}

impl From<[f32; 3]> for Color {
    #[allow(clippy::identity_conversion)]
    fn from(arr: [f32; 3]) -> Self {
        Self(BaseColor::from(arr))
    }
}

impl Into<[f32; 3]> for Color {
    fn into(self) -> [f32; 3] {
        self.0.into()
    }
}

// Arithmetic operations

impl Add for BaseColor {
    type Output = Self;

    fn add(mut self, rhs: Self) -> Self {
        self += rhs;
        self
    }
}

impl AddAssign for BaseColor {
    fn add_assign(&mut self, rhs: Self) {
        self.color += rhs.color;
    }
}

impl Div<Float> for BaseColor {
    type Output = Self;

    fn div(mut self, rhs: Float) -> Self {
        self /= rhs;
        self
    }
}

impl DivAssign<Float> for BaseColor {
    fn div_assign(&mut self, rhs: Float) {
        let recip = rhs.recip();
        self.color *= recip;
    }
}

impl Mul for BaseColor {
    type Output = Self;

    fn mul(mut self, rhs: Self) -> Self {
        self *= rhs;
        self
    }
}

impl MulAssign for BaseColor {
    fn mul_assign(&mut self, rhs: Self) {
        self.color.mul_assign_element_wise(rhs.color);
    }
}

impl Mul<Float> for BaseColor {
    type Output = Self;

    fn mul(mut self, rhs: Float) -> Self {
        self *= rhs;
        self
    }
}

impl MulAssign<Float> for BaseColor {
    fn mul_assign(&mut self, rhs: Float) {
        self.color.mul_assign_element_wise(rhs);
    }
}

impl Mul<BaseColor> for Float {
    type Output = BaseColor;

    // Delegate to BaseColor Mul
    fn mul(self, rhs: BaseColor) -> Self::Output {
        rhs * self
    }
}

// Color operations delegated to BaseColor

impl Add for Color {
    type Output = Self;

    fn add(mut self, rhs: Self) -> Self {
        self.0 += rhs.0;
        self
    }
}

impl AddAssign for Color {
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0;
    }
}

impl Div<Float> for Color {
    type Output = Self;

    fn div(mut self, rhs: Float) -> Self {
        self.0 /= rhs;
        self
    }
}

impl DivAssign<Float> for Color {
    fn div_assign(&mut self, rhs: Float) {
        let recip = rhs.recip();
        self.0 *= recip;
    }
}

impl Mul for Color {
    type Output = Self;

    fn mul(mut self, rhs: Self) -> Self {
        self.0 *= rhs.0;
        self
    }
}

impl Mul<Float> for Color {
    type Output = Self;

    fn mul(mut self, rhs: Float) -> Self {
        self.0 *= rhs;
        self
    }
}

impl Mul<Color> for Float {
    type Output = Color;

    // Delegate to BaseColor Mul
    fn mul(self, rhs: Color) -> Self::Output {
        rhs * self
    }
}

// SrgbColor operations delegated to BaseColor

impl Add for SrgbColor {
    type Output = Self;

    fn add(mut self, rhs: Self) -> Self {
        self.0 += rhs.0;
        self
    }
}

impl AddAssign for SrgbColor {
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0;
    }
}

impl Div<Float> for SrgbColor {
    type Output = Self;

    fn div(mut self, rhs: Float) -> Self {
        self.0 /= rhs;
        self
    }
}

impl DivAssign<Float> for SrgbColor {
    fn div_assign(&mut self, rhs: Float) {
        let recip = rhs.recip();
        self.0 *= recip;
    }
}

impl Mul for SrgbColor {
    type Output = Self;

    fn mul(mut self, rhs: Self) -> Self {
        self.0 *= rhs.0;
        self
    }
}

impl Mul<Float> for SrgbColor {
    type Output = Self;

    fn mul(mut self, rhs: Float) -> Self {
        self.0 *= rhs;
        self
    }
}

impl Mul<SrgbColor> for Float {
    type Output = SrgbColor;

    // Delegate to BaseColor Mul
    fn mul(self, rhs: SrgbColor) -> Self::Output {
        rhs * self
    }
}
<commit_msg>Use epsilon in gray check<commit_after>use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign};

use cgmath::prelude::*;
use cgmath::Vector3;

use crate::consts;
use crate::util::ConvArr;
use crate::Float;

/// Convert u8 color to float color in range [0, 1]
pub fn to_float(c: u8) -> Float {
    Float::from(c) / 255.0
}

/// Convert srgb color to linear color
fn to_linear(c: Float) -> Float {
    c.powf(2.2)
}

#[derive(Clone, Copy, Debug)]
pub struct SrgbColor(BaseColor);

impl SrgbColor {
    pub fn from_pixel(rgb: image::Rgb<u8>) -> Self {
        Self(BaseColor::from_pixel(rgb))
    }

    pub fn is_gray(&self) -> bool {
        self.0.is_gray()
    }

    pub fn to_linear(self) -> Color {
        Color(self.0.to_linear())
    }

    pub fn to_vec(self) -> Vector3<Float> {
        self.0.color
    }
}

#[derive(Clone, Copy, Debug)]
pub struct Color(BaseColor);

impl Color {
    pub fn black() -> Self {
        Self(BaseColor::black())
    }

    pub fn white() -> Self {
        Self(BaseColor::white())
    }

    pub fn from_normal(n: Vector3<Float>) -> Self {
        let c_vec = (0.5 * n).add_element_wise(0.5);
        Self(BaseColor::from(c_vec))
    }

    pub fn luma(&self) -> Float {
        self.0.luma()
    }

    pub fn is_black(&self) -> bool {
        self.0.is_black()
    }

    pub fn r(&self) -> Float {
        self.0.r()
    }

    pub fn g(&self) -> Float {
        self.0.g()
    }

    pub fn b(&self) -> Float {
        self.0.b()
    }
}

#[derive(Clone, Copy, Debug)]
struct BaseColor {
    color: Vector3<Float>,
}

impl BaseColor {
    fn new(r: Float, g: Float, b: Float) -> Self {
        Self {
            color: Vector3::new(r, g, b),
        }
    }

    fn black() -> Self {
        Self::new(0.0, 0.0, 0.0)
    }

    fn white() -> Self {
        Self::new(1.0, 1.0, 1.0)
    }

    fn from_pixel(rgb: image::Rgb<u8>) -> Self {
        Self::new(
            to_float(rgb.data[0]),
            to_float(rgb.data[1]),
            to_float(rgb.data[2]),
        )
    }

    fn to_linear(self) -> Self {
        Self::new(
            to_linear(self.color[0]),
            to_linear(self.color[1]),
            to_linear(self.color[2]),
        )
    }

    fn luma(&self) -> Float {
        let luma_vec = Vector3::new(0.2126, 0.7152, 0.0722);
        luma_vec.dot(self.color)
    }

    fn is_black(&self) -> bool {
        self.color.x == 0.0 && self.color.y == 0.0 && self.color.z == 0.0
    }

    fn is_gray(&self) -> bool {
        (self.color.x - self.color.y).abs() < consts::EPSILON
            && (self.color.y - self.color.z).abs() < consts::EPSILON
    }

    fn r(&self) -> Float {
        self.color.x
    }

    fn g(&self) -> Float {
        self.color.y
    }

    fn b(&self) -> Float {
        self.color.z
    }
}

impl Index<usize> for BaseColor {
    type Output = Float;

    fn index(&self, i: usize) -> &Float {
        &self.color[i]
    }
}

impl IndexMut<usize> for BaseColor {
    fn index_mut(&mut self, i: usize) -> &mut Float {
        &mut self.color[i]
    }
}

impl From<Vector3<Float>> for BaseColor {
    #[allow(clippy::identity_conversion)]
    fn from(vec: Vector3<Float>) -> Self {
        Self { color: vec }
    }
}

impl From<[f32; 3]> for BaseColor {
    #[allow(clippy::identity_conversion)]
    fn from(arr: [f32; 3]) -> Self {
        Self {
            color: Vector3::from_arr(arr),
        }
    }
}

impl Into<[f32; 3]> for BaseColor {
    fn into(self) -> [f32; 3] {
        self.color.into_arr()
    }
}

impl From<[f32; 3]> for Color {
    #[allow(clippy::identity_conversion)]
    fn from(arr: [f32; 3]) -> Self {
        Self(BaseColor::from(arr))
    }
}

impl Into<[f32; 3]> for Color {
    fn into(self) -> [f32; 3] {
        self.0.into()
    }
}

// Arithmetic operations

impl Add for BaseColor {
    type Output = Self;

    fn add(mut self, rhs: Self) -> Self {
        self += rhs;
        self
    }
}

impl AddAssign for BaseColor {
    fn add_assign(&mut self, rhs: Self) {
        self.color += rhs.color;
    }
}

impl Div<Float> for BaseColor {
    type Output = Self;

    fn div(mut self, rhs: Float) -> Self {
        self /= rhs;
        self
    }
}

impl DivAssign<Float> for BaseColor {
    fn div_assign(&mut self, rhs: Float) {
        let recip = rhs.recip();
        self.color *= recip;
    }
}

impl Mul for BaseColor {
    type Output = Self;

    fn mul(mut self, rhs: Self) -> Self {
        self *= rhs;
        self
    }
}

impl MulAssign for BaseColor {
    fn mul_assign(&mut self, rhs: Self) {
        self.color.mul_assign_element_wise(rhs.color);
    }
}

impl Mul<Float> for BaseColor {
    type Output = Self;

    fn mul(mut self, rhs: Float) -> Self {
        self *= rhs;
        self
    }
}

impl MulAssign<Float> for BaseColor {
    fn mul_assign(&mut self, rhs: Float) {
        self.color.mul_assign_element_wise(rhs);
    }
}

impl Mul<BaseColor> for Float {
    type Output = BaseColor;

    // Delegate to BaseColor Mul
    fn mul(self, rhs: BaseColor) -> Self::Output {
        rhs * self
    }
}

// Color operations delegated to BaseColor

impl Add for Color {
    type Output = Self;

    fn add(mut self, rhs: Self) -> Self {
        self.0 += rhs.0;
        self
    }
}

impl AddAssign for Color {
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0;
    }
}

impl Div<Float> for Color {
    type Output = Self;

    fn div(mut self, rhs: Float) -> Self {
        self.0 /= rhs;
        self
    }
}

impl DivAssign<Float> for Color {
    fn div_assign(&mut self, rhs: Float) {
        let recip = rhs.recip();
        self.0 *= recip;
    }
}

impl Mul for Color {
    type Output = Self;

    fn mul(mut self, rhs: Self) -> Self {
        self.0 *= rhs.0;
        self
    }
}

impl Mul<Float> for Color {
    type Output = Self;

    fn mul(mut self, rhs: Float) -> Self {
        self.0 *= rhs;
        self
    }
}

impl Mul<Color> for Float {
    type Output = Color;

    // Delegate to BaseColor Mul
    fn mul(self, rhs: Color) -> Self::Output {
        rhs * self
    }
}

// SrgbColor operations delegated to BaseColor

impl Add for SrgbColor {
    type Output = Self;

    fn add(mut self, rhs: Self) -> Self {
        self.0 += rhs.0;
        self
    }
}

impl AddAssign for SrgbColor {
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0;
    }
}

impl Div<Float> for SrgbColor {
    type Output = Self;

    fn div(mut self, rhs: Float) -> Self {
        self.0 /= rhs;
        self
    }
}

impl DivAssign<Float> for SrgbColor {
    fn div_assign(&mut self, rhs: Float) {
        let recip = rhs.recip();
        self.0 *= recip;
    }
}

impl Mul for SrgbColor {
    type Output = Self;

    fn mul(mut self, rhs: Self) -> Self {
        self.0 *= rhs.0;
        self
    }
}

impl Mul<Float> for SrgbColor {
    type Output = Self;

    fn mul(mut self, rhs: Float) -> Self {
        self.0 *= rhs;
        self
    }
}

impl Mul<SrgbColor> for Float {
    type Output = SrgbColor;

    // Delegate to BaseColor Mul
    fn mul(self, rhs: SrgbColor) -> Self::Output {
        rhs * self
    }
}
<|endoftext|>


<commit_before>//! Convert a string in IBM codepage 437 to UTF-8

/// Trait to convert IBM codepage 437 to the target type
pub trait FromCp437 {
    /// Target type
    type Target;

    /// Function that does the conversion from cp437.
    /// Gennerally allocations will be avoided if all data falls into the ASCII range.
    fn from_cp437(self) -> Self::Target;
}

impl<'a> FromCp437 for &'a [u8] {
    type Target = ::std::borrow::Cow<'a, str>;

    fn from_cp437(self) -> Self::Target
    {
        if self.iter().all(|c| *c < 0x80) {
            ::std::str::from_utf8(self).unwrap().into()
        }
        else {
            self.iter().map(|c| to_char(*c)).collect::<String>().into()
        }
    }
}

impl FromCp437 for Vec<u8> {
    type Target = String;

    fn from_cp437(self) -> Self::Target {
        if self.iter().all(|c| *c < 0x80) {
            String::from_utf8(self).unwrap()
        }
        else {
            self.into_iter().map(|c| to_char(c)).collect()
        }
    }
}

fn to_char(input: u8) -> char
{
    let output = match input
    {
        0x00 ... 0x7f => input as u32,
        0x80 => 0x00c7,
        0x81 => 0x00fc,
        0x82 => 0x00e9,
        0x83 => 0x00e2,
        0x84 => 0x00e4,
        0x85 => 0x00e0,
        0x86 => 0x00e5,
        0x87 => 0x00e7,
        0x88 => 0x00ea,
        0x89 => 0x00eb,
        0x8a => 0x00e8,
        0x8b => 0x00ef,
        0x8c => 0x00ee,
        0x8d => 0x00ec,
        0x8e => 0x00c4,
        0x8f => 0x00c5,
        0x90 => 0x00c9,
        0x91 => 0x00e6,
        0x92 => 0x00c6,
        0x93 => 0x00f4,
        0x94 => 0x00f6,
        0x95 => 0x00f2,
        0x96 => 0x00fb,
        0x97 => 0x00f9,
        0x98 => 0x00ff,
        0x99 => 0x00d6,
        0x9a => 0x00dc,
        0x9b => 0x00a2,
        0x9c => 0x00a3,
        0x9d => 0x00a5,
        0x9e => 0x20a7,
        0x9f => 0x0192,
        0xa0 => 0x00e1,
        0xa1 => 0x00ed,
        0xa2 => 0x00f3,
        0xa3 => 0x00fa,
        0xa4 => 0x00f1,
        0xa5 => 0x00d1,
        0xa6 => 0x00aa,
        0xa7 => 0x00ba,
        0xa8 => 0x00bf,
        0xa9 => 0x2310,
        0xaa => 0x00ac,
        0xab => 0x00bd,
        0xac => 0x00bc,
        0xad => 0x00a1,
        0xae => 0x00ab,
        0xaf => 0x00bb,
        0xb0 => 0x2591,
        0xb1 => 0x2592,
        0xb2 => 0x2593,
        0xb3 => 0x2502,
        0xb4 => 0x2524,
        0xb5 => 0x2561,
        0xb6 => 0x2562,
        0xb7 => 0x2556,
        0xb8 => 0x2555,
        0xb9 => 0x2563,
        0xba => 0x2551,
        0xbb => 0x2557,
        0xbc => 0x255d,
        0xbd => 0x255c,
        0xbe => 0x255b,
        0xbf => 0x2510,
        0xc0 => 0x2514,
        0xc1 => 0x2534,
        0xc2 => 0x252c,
        0xc3 => 0x251c,
        0xc4 => 0x2500,
        0xc5 => 0x253c,
        0xc6 => 0x255e,
        0xc7 => 0x255f,
        0xc8 => 0x255a,
        0xc9 => 0x2554,
        0xca => 0x2569,
        0xcb => 0x2566,
        0xcc => 0x2560,
        0xcd => 0x2550,
        0xce => 0x256c,
        0xcf => 0x2567,
        0xd0 => 0x2568,
        0xd1 => 0x2564,
        0xd2 => 0x2565,
        0xd3 => 0x2559,
        0xd4 => 0x2558,
        0xd5 => 0x2552,
        0xd6 => 0x2553,
        0xd7 => 0x256b,
        0xd8 => 0x256a,
        0xd9 => 0x2518,
        0xda => 0x250c,
        0xdb => 0x2588,
        0xdc => 0x2584,
        0xdd => 0x258c,
        0xde => 0x2590,
        0xdf => 0x2580,
        0xe0 => 0x03b1,
        0xe1 => 0x00df,
        0xe2 => 0x0393,
        0xe3 => 0x03c0,
        0xe4 => 0x03a3,
        0xe5 => 0x03c3,
        0xe6 => 0x00b5,
        0xe7 => 0x03c4,
        0xe8 => 0x03a6,
        0xe9 => 0x0398,
        0xea => 0x03a9,
        0xeb => 0x03b4,
        0xec => 0x221e,
        0xed => 0x03c6,
        0xee => 0x03b5,
        0xef => 0x2229,
        0xf0 => 0x2261,
        0xf1 => 0x00b1,
        0xf2 => 0x2265,
        0xf3 => 0x2264,
        0xf4 => 0x2320,
        0xf5 => 0x2321,
        0xf6 => 0x00f7,
        0xf7 => 0x2248,
        0xf8 => 0x00b0,
        0xf9 => 0x2219,
        0xfa => 0x00b7,
        0xfb => 0x221a,
        0xfc => 0x207f,
        0xfd => 0x00b2,
        0xfe => 0x25a0,
        0xff => 0x00a0,
        _ => unreachable!(),
    };
    ::std::char::from_u32(output).unwrap()
}

#[cfg(test)]
mod test
{
    #[test]
    fn to_char_valid()
    {
        for i in 0x00_u32 .. 0x100
        {
            super::to_char(i as u8);
        }
    }

    #[test]
    fn ascii() {
        for i in 0x00 .. 0x80 {
            assert_eq!(super::to_char(i), i as char);
        }
    }

    #[test]
    fn example_slice() {
        use super::FromCp437;
        let data : &[u8] = &[0x43, 0x75, 0x72, 0x61, 0x87, 0x61, 0x6F];
        assert!(::std::str::from_utf8(data).is_err());
        assert_eq!(data.from_cp437(), "Curaçao");
    }

    #[test]
    fn example_vec() {
        use super::FromCp437;
        let data = vec![0xCC, 0xCD, 0xCD, 0xB9];
        assert!(String::from_utf8(data.clone()).is_err());
        assert_eq!(&data.from_cp437(), "╠══╣");
    }
}
<commit_msg>Simplify one test<commit_after>//! Convert a string in IBM codepage 437 to UTF-8

/// Trait to convert IBM codepage 437 to the target type
pub trait FromCp437 {
    /// Target type
    type Target;

    /// Function that does the conversion from cp437.
    /// Gennerally allocations will be avoided if all data falls into the ASCII range.
    fn from_cp437(self) -> Self::Target;
}

impl<'a> FromCp437 for &'a [u8] {
    type Target = ::std::borrow::Cow<'a, str>;

    fn from_cp437(self) -> Self::Target
    {
        if self.iter().all(|c| *c < 0x80) {
            ::std::str::from_utf8(self).unwrap().into()
        }
        else {
            self.iter().map(|c| to_char(*c)).collect::<String>().into()
        }
    }
}

impl FromCp437 for Vec<u8> {
    type Target = String;

    fn from_cp437(self) -> Self::Target {
        if self.iter().all(|c| *c < 0x80) {
            String::from_utf8(self).unwrap()
        }
        else {
            self.into_iter().map(|c| to_char(c)).collect()
        }
    }
}

fn to_char(input: u8) -> char
{
    let output = match input
    {
        0x00 ... 0x7f => input as u32,
        0x80 => 0x00c7,
        0x81 => 0x00fc,
        0x82 => 0x00e9,
        0x83 => 0x00e2,
        0x84 => 0x00e4,
        0x85 => 0x00e0,
        0x86 => 0x00e5,
        0x87 => 0x00e7,
        0x88 => 0x00ea,
        0x89 => 0x00eb,
        0x8a => 0x00e8,
        0x8b => 0x00ef,
        0x8c => 0x00ee,
        0x8d => 0x00ec,
        0x8e => 0x00c4,
        0x8f => 0x00c5,
        0x90 => 0x00c9,
        0x91 => 0x00e6,
        0x92 => 0x00c6,
        0x93 => 0x00f4,
        0x94 => 0x00f6,
        0x95 => 0x00f2,
        0x96 => 0x00fb,
        0x97 => 0x00f9,
        0x98 => 0x00ff,
        0x99 => 0x00d6,
        0x9a => 0x00dc,
        0x9b => 0x00a2,
        0x9c => 0x00a3,
        0x9d => 0x00a5,
        0x9e => 0x20a7,
        0x9f => 0x0192,
        0xa0 => 0x00e1,
        0xa1 => 0x00ed,
        0xa2 => 0x00f3,
        0xa3 => 0x00fa,
        0xa4 => 0x00f1,
        0xa5 => 0x00d1,
        0xa6 => 0x00aa,
        0xa7 => 0x00ba,
        0xa8 => 0x00bf,
        0xa9 => 0x2310,
        0xaa => 0x00ac,
        0xab => 0x00bd,
        0xac => 0x00bc,
        0xad => 0x00a1,
        0xae => 0x00ab,
        0xaf => 0x00bb,
        0xb0 => 0x2591,
        0xb1 => 0x2592,
        0xb2 => 0x2593,
        0xb3 => 0x2502,
        0xb4 => 0x2524,
        0xb5 => 0x2561,
        0xb6 => 0x2562,
        0xb7 => 0x2556,
        0xb8 => 0x2555,
        0xb9 => 0x2563,
        0xba => 0x2551,
        0xbb => 0x2557,
        0xbc => 0x255d,
        0xbd => 0x255c,
        0xbe => 0x255b,
        0xbf => 0x2510,
        0xc0 => 0x2514,
        0xc1 => 0x2534,
        0xc2 => 0x252c,
        0xc3 => 0x251c,
        0xc4 => 0x2500,
        0xc5 => 0x253c,
        0xc6 => 0x255e,
        0xc7 => 0x255f,
        0xc8 => 0x255a,
        0xc9 => 0x2554,
        0xca => 0x2569,
        0xcb => 0x2566,
        0xcc => 0x2560,
        0xcd => 0x2550,
        0xce => 0x256c,
        0xcf => 0x2567,
        0xd0 => 0x2568,
        0xd1 => 0x2564,
        0xd2 => 0x2565,
        0xd3 => 0x2559,
        0xd4 => 0x2558,
        0xd5 => 0x2552,
        0xd6 => 0x2553,
        0xd7 => 0x256b,
        0xd8 => 0x256a,
        0xd9 => 0x2518,
        0xda => 0x250c,
        0xdb => 0x2588,
        0xdc => 0x2584,
        0xdd => 0x258c,
        0xde => 0x2590,
        0xdf => 0x2580,
        0xe0 => 0x03b1,
        0xe1 => 0x00df,
        0xe2 => 0x0393,
        0xe3 => 0x03c0,
        0xe4 => 0x03a3,
        0xe5 => 0x03c3,
        0xe6 => 0x00b5,
        0xe7 => 0x03c4,
        0xe8 => 0x03a6,
        0xe9 => 0x0398,
        0xea => 0x03a9,
        0xeb => 0x03b4,
        0xec => 0x221e,
        0xed => 0x03c6,
        0xee => 0x03b5,
        0xef => 0x2229,
        0xf0 => 0x2261,
        0xf1 => 0x00b1,
        0xf2 => 0x2265,
        0xf3 => 0x2264,
        0xf4 => 0x2320,
        0xf5 => 0x2321,
        0xf6 => 0x00f7,
        0xf7 => 0x2248,
        0xf8 => 0x00b0,
        0xf9 => 0x2219,
        0xfa => 0x00b7,
        0xfb => 0x221a,
        0xfc => 0x207f,
        0xfd => 0x00b2,
        0xfe => 0x25a0,
        0xff => 0x00a0,
        _ => unreachable!(),
    };
    ::std::char::from_u32(output).unwrap()
}

#[cfg(test)]
mod test
{
    #[test]
    fn to_char_valid()
    {
        for i in 0x00_u32 .. 0x100
        {
            super::to_char(i as u8);
        }
    }

    #[test]
    fn ascii() {
        for i in 0x00 .. 0x80 {
            assert_eq!(super::to_char(i), i as char);
        }
    }

    #[test]
    fn example_slice() {
        use super::FromCp437;
        let data = b"Cura\x87ao";
        assert!(::std::str::from_utf8(data).is_err());
        assert_eq!(data.from_cp437(), "Curaçao");
    }

    #[test]
    fn example_vec() {
        use super::FromCp437;
        let data = vec![0xCC, 0xCD, 0xCD, 0xB9];
        assert!(String::from_utf8(data.clone()).is_err());
        assert_eq!(&data.from_cp437(), "╠══╣");
    }
}
<|endoftext|>