<commit_before>//! Heatmap provides a time-series of Histograms, which is useful for
//! recording distributions over time and reporting percentiles over time
//!
//!
//! # Goals
//! * pre-allocated datastructure
//! * report time-series percentiles
//! * auto-slicing by record time
//!
//! # Future work
//! * make it work
//! * make it awesome
//! * add roll-up
//!
//! # Usage
//! Create a heatmap. Insert values over time. Profit.
//!
//! ```
//!
//! use heatmap::*;

#![crate_type = "lib"]

#![crate_name = "heatmap"]

extern crate histogram;
extern crate time;

use histogram::*;
use time::*;

#[derive(Clone, Copy)]
pub struct HeatmapConfig {
    precision: u32,
    max_memory: u32,
    max_value: u64,
    slice_duration: u64,
    num_slices: usize,
    start: u64,
}

impl HeatmapConfig {
    pub fn new() -> HeatmapConfig {
        HeatmapConfig {
            precision: 3,
            max_memory: 0,
            max_value: 1_000_000_000,
            slice_duration: 60_000_000_000,
            num_slices: 60,
            start: 0,
        }
    }

    pub fn precision(&mut self, precision: u32) -> &mut Self {
        self.precision = precision;
        self
    }

    pub fn max_memory(&mut self, bytes: u32) -> &mut Self {
        self.max_memory = bytes;
        self
    }

    pub fn max_value(&mut self, value: u64) -> &mut Self {
        self.max_value = value;
        self
    }

    pub fn slice_duration(&mut self, duration: u64) -> &mut Self {
        self.slice_duration = duration;
        self
    }

    pub fn num_slices(&mut self, count: usize) -> &mut Self {
        self.num_slices = count;
        self
    }

    pub fn start(&mut self, time: u64) -> &mut Self {
        self.start = time;
        self
    }
}

#[derive(Clone, Copy)]
pub struct HeatmapCounters {
    entries_total: u64,
}

impl HeatmapCounters {
    pub fn new() -> HeatmapCounters {
        HeatmapCounters { entries_total: 0 }
    }

    pub fn clear(&mut self) {
        self.entries_total = 0;
    }
}

#[derive(Clone)]
pub struct HeatmapData {
    data: Vec<Histogram>,
    counters: HeatmapCounters,
    iterator: usize,
    start: u64,
    stop: u64,
}

#[derive(Clone, Copy)]
pub struct HeatmapProperties;

#[derive(Clone)]
pub struct Heatmap {
    config: HeatmapConfig,
    data: HeatmapData,
    properties: HeatmapProperties,
}

#[derive(Clone)]
pub struct HeatmapSlice {
    pub start: u64,
    pub stop: u64,
    pub histogram: Histogram,
}

impl HeatmapSlice {
    pub fn start(self) -> u64 {
        self.start
    }

    pub fn stop(self) -> u64 {
        self.stop
    }

    pub fn histogram(self) -> Histogram {
        self.histogram
    }
}

impl Iterator for Heatmap {
    type Item = HeatmapSlice;

    fn next(&mut self) -> Option<HeatmapSlice> {
        let current = self.data.iterator;
        self.data.iterator += 1;

        if current == (self.config.num_slices as usize) {
            self.data.iterator = 0;
            None
        } else {
            let start = (self.data.iterator as u64 * self.config.slice_duration) + self.data.start;
            Some(HeatmapSlice {
                start: start,
                stop: start + self.config.slice_duration,
                histogram: self.data.data[current].clone(),
            })
        }
    }
}

impl Heatmap {

    /// create a new Heatmap with defaults
    ///
    /// # Example
    /// ```
    /// # use heatmap::Heatmap;
    ///
    /// let mut h = Heatmap::new().unwrap();
    pub fn new() -> Option<Heatmap> {
        Heatmap::configured(HeatmapConfig::new())
    }

    /// create a new Heatmap
    ///
    /// # Example
    /// ```
    /// # use heatmap::{Heatmap,HeatmapConfig};
    ///
    /// let mut c = HeatmapConfig::new();
    /// c.precision(4); // set precision to 4 digits
    /// c.max_value(1_000_000_000); // store values up to 1 Million
    /// c.slice_duration(1_000_000_000); // 1 second slices
    /// c.num_slices(300); // 300 slices => 5 minutes of records
    ///
    /// let mut h = Heatmap::configured(c).unwrap();
    pub fn configured(config: HeatmapConfig) -> Option<Heatmap> {

        let mut data = Vec::with_capacity(config.num_slices);

        unsafe {
            data.set_len(config.num_slices);
        }

        for i in 0..config.num_slices {
            let mut c = HistogramConfig::new();
            c.max_value(config.max_value);
            c.precision(config.precision);
            c.max_memory(config.max_memory / config.num_slices as u32);

            data[i] = Histogram::configured(c).unwrap();
        }

        let start = config.start;

        Some(Heatmap {
            config: config,
            data: HeatmapData {
                data: data,
                counters: HeatmapCounters::new(),
                iterator: 0,
                start: start,
                stop: start + config.slice_duration * config.num_slices as u64,
            },
            properties: HeatmapProperties,
        })
    }

    /// clear the heatmap data
    ///
    /// # Example
    /// ```
    /// # use heatmap::{Heatmap,HeatmapConfig};
    ///
    /// let mut h = Heatmap::new(
    ///     HeatmapConfig{
    ///         max_value: 1000000,
    ///         precision: 3,
    ///         max_memory: 0,
    ///			slice_duration: 1000000000,
    ///			num_slices: 300,
    /// }).unwrap();
    ///
    /// h.increment(1);
    /// assert_eq!(h.entries(), 1);
    /// h.clear();
    /// assert_eq!(h.entries(), 0);
    pub fn clear(&mut self) -> Result<(), &'static str> {
        for i in 0..self.config.num_slices {
            match self.data.data[i].clear() {
                Ok(_) => {}
                Err(e) => {
                    return Err(e);
                }
            }
        }

        self.data.counters.clear();
        self.data.start = time::precise_time_ns();
        self.data.stop = self.data.start +
                         self.config.slice_duration * self.config.num_slices as u64;
        Ok(())
    }

    /// increment the count for a value at a time
    ///
    /// # Example
    /// ```
    /// extern crate heatmap;
    /// extern crate time;
    ///
    /// let mut h = heatmap::Heatmap::new().unwrap();
    ///
    /// h.increment(time::precise_time_ns(), 1);
    /// assert_eq!(h.entries(), 1);
    pub fn increment(&mut self, time: u64, value: u64) -> Result<(), &'static str> {
        self.record(time, value, 1_u64)
    }

    /// record additional counts for value at a time
    ///
    /// # Example
    /// ```
    /// extern crate heatmap;
    /// extern crate time;
    ///
    /// let mut h = heatmap::Heatmap::new().unwrap();
    ///
    /// h.record(time::precise_time_ns(), 1, 1);
    /// assert_eq!(h.entries(), 1);
    ///
    /// h.record(time::precise_time_ns(), 2, 2);
    /// assert_eq!(h.entries(), 3);
    ///
    /// h.record(time::precise_time_ns(), 10, 10);
    /// assert_eq!(h.entries(), 13);
    pub fn record(&mut self, time: u64, value: u64, count: u64) -> Result<(), &'static str> {
        self.data.counters.entries_total = self.data.counters.entries_total.saturating_add(count);

        match self.histogram_index(time) {
            Ok(histogram_index) => {
                self.data.data[histogram_index].record(value, count)
            }
            Err(e) => {
                Err(e)
            }
        }
    }

    pub fn get(&mut self, time: u64, value: u64) -> Result<u64, &'static str> {
        match self.histogram_index(time) {
            Ok(histogram_index) => {
                match self.data.data[histogram_index].get(value) {
                    Some(count) => {
                        Ok(count)
                    }
                    None => {
                        Err("histogram didn't have")
                    }
                }
            }
            Err(e) => {
                Err(e)
            }
        }
    }

    /// internal function to find the index of the histogram in the heatmap
    fn histogram_index(&mut self, time: u64) -> Result<usize, &'static str> {
        if time < self.data.start {
            return Err("sample too early");
        } else if time > self.data.stop {
            return Err("sample too late");
        }
        let index: usize = ((time - self.data.start) as f64 /
                            self.config.slice_duration as f64)
                               .floor() as usize;
        println!("index: time: {} is {}", time, index);
        Ok(index)
    }

    /// return the number of entries in the Histogram
    ///
    /// # Example
    /// ```
    /// extern crate heatmap;
    /// extern crate time;
    ///
    /// let mut h = heatmap::Heatmap::new().unwrap();
    ///
    /// assert_eq!(h.entries(), 0);
    /// h.record(time::precise_time_ns(), 1, 1);
    /// assert_eq!(h.entries(), 1);
    pub fn entries(&mut self) -> u64 {
        self.data.counters.entries_total
    }

    /// merge one Heatmap into another Heatmap
    ///
    /// # Example
    /// ```
    /// extern crate heatmap;
    /// extern crate time;
    ///
    /// let mut c = heatmap::HeatmapConfig::new();
    /// c.num_slices(61);
    ///
    /// let mut a = heatmap::Heatmap::configured(c).unwrap();
    ///
    /// let mut b = heatmap::Heatmap::new().unwrap();
    ///
    /// assert_eq!(a.entries(), 0);
    /// assert_eq!(b.entries(), 0);
    ///
    /// let _ = a.increment(1, 1);
    /// let _ = b.increment(1, 1);
    ///
    /// assert_eq!(a.entries(), 1);
    /// assert_eq!(b.entries(), 1);
    ///
    /// a.merge(&mut b);
    ///
    /// assert_eq!(a.entries(), 2);
    /// assert_eq!(a.get(1, 1).unwrap(), 1);
    /// assert_eq!(a.get(2, 1).unwrap(), 1);
    pub fn merge(&mut self, other: &mut Heatmap) {
        loop {
            match other.next() {
                Some(other_slice) => {
                    match self.histogram_index(other_slice.clone().start()) {
                        Ok(i) => {
                            self.data.data[i].merge(&mut other_slice.clone().histogram.clone());
                            self.data.counters.entries_total += other_slice.clone()
                                                                           .histogram
                                                                           .clone()
                                                                           .entries();
                        }
                        Err(e) => {}
                    }

                }
                None => {
                    break;
                }
            }
        }
    }
}
<commit_msg>only nightly caught this<commit_after>//! Heatmap provides a time-series of Histograms, which is useful for
//! recording distributions over time and reporting percentiles over time
//!
//!
//! # Goals
//! * pre-allocated datastructure
//! * report time-series percentiles
//! * auto-slicing by record time
//!
//! # Future work
//! * make it work
//! * make it awesome
//! * add roll-up
//!
//! # Usage
//! Create a heatmap. Insert values over time. Profit.
//!
//! ```
//!
//! use heatmap::*;

#![crate_type = "lib"]

#![crate_name = "heatmap"]

extern crate histogram;
extern crate time;

use histogram::*;
use time::*;

#[derive(Clone, Copy)]
pub struct HeatmapConfig {
    precision: u32,
    max_memory: u32,
    max_value: u64,
    slice_duration: u64,
    num_slices: usize,
    start: u64,
}

impl HeatmapConfig {
    pub fn new() -> HeatmapConfig {
        HeatmapConfig {
            precision: 3,
            max_memory: 0,
            max_value: 1_000_000_000,
            slice_duration: 60_000_000_000,
            num_slices: 60,
            start: 0,
        }
    }

    pub fn precision(&mut self, precision: u32) -> &mut Self {
        self.precision = precision;
        self
    }

    pub fn max_memory(&mut self, bytes: u32) -> &mut Self {
        self.max_memory = bytes;
        self
    }

    pub fn max_value(&mut self, value: u64) -> &mut Self {
        self.max_value = value;
        self
    }

    pub fn slice_duration(&mut self, duration: u64) -> &mut Self {
        self.slice_duration = duration;
        self
    }

    pub fn num_slices(&mut self, count: usize) -> &mut Self {
        self.num_slices = count;
        self
    }

    pub fn start(&mut self, time: u64) -> &mut Self {
        self.start = time;
        self
    }
}

#[derive(Clone, Copy)]
pub struct HeatmapCounters {
    entries_total: u64,
}

impl HeatmapCounters {
    pub fn new() -> HeatmapCounters {
        HeatmapCounters { entries_total: 0 }
    }

    pub fn clear(&mut self) {
        self.entries_total = 0;
    }
}

#[derive(Clone)]
pub struct HeatmapData {
    data: Vec<Histogram>,
    counters: HeatmapCounters,
    iterator: usize,
    start: u64,
    stop: u64,
}

#[derive(Clone, Copy)]
pub struct HeatmapProperties;

#[derive(Clone)]
pub struct Heatmap {
    config: HeatmapConfig,
    data: HeatmapData,
    properties: HeatmapProperties,
}

#[derive(Clone)]
pub struct HeatmapSlice {
    pub start: u64,
    pub stop: u64,
    pub histogram: Histogram,
}

impl HeatmapSlice {
    pub fn start(self) -> u64 {
        self.start
    }

    pub fn stop(self) -> u64 {
        self.stop
    }

    pub fn histogram(self) -> Histogram {
        self.histogram
    }
}

impl Iterator for Heatmap {
    type Item = HeatmapSlice;

    fn next(&mut self) -> Option<HeatmapSlice> {
        let current = self.data.iterator;
        self.data.iterator += 1;

        if current == (self.config.num_slices as usize) {
            self.data.iterator = 0;
            None
        } else {
            let start = (self.data.iterator as u64 * self.config.slice_duration) + self.data.start;
            Some(HeatmapSlice {
                start: start,
                stop: start + self.config.slice_duration,
                histogram: self.data.data[current].clone(),
            })
        }
    }
}

impl Heatmap {

    /// create a new Heatmap with defaults
    ///
    /// # Example
    /// ```
    /// # use heatmap::Heatmap;
    ///
    /// let mut h = Heatmap::new().unwrap();
    pub fn new() -> Option<Heatmap> {
        Heatmap::configured(HeatmapConfig::new())
    }

    /// create a new Heatmap
    ///
    /// # Example
    /// ```
    /// # use heatmap::{Heatmap,HeatmapConfig};
    ///
    /// let mut c = HeatmapConfig::new();
    /// c.precision(4); // set precision to 4 digits
    /// c.max_value(1_000_000_000); // store values up to 1 Million
    /// c.slice_duration(1_000_000_000); // 1 second slices
    /// c.num_slices(300); // 300 slices => 5 minutes of records
    ///
    /// let mut h = Heatmap::configured(c).unwrap();
    pub fn configured(config: HeatmapConfig) -> Option<Heatmap> {

        let mut data = Vec::with_capacity(config.num_slices);

        unsafe {
            data.set_len(config.num_slices);
        }

        for i in 0..config.num_slices {
            let mut c = HistogramConfig::new();
            c.max_value(config.max_value);
            c.precision(config.precision);
            c.max_memory(config.max_memory / config.num_slices as u32);

            data[i] = Histogram::configured(c).unwrap();
        }

        let start = config.start;

        Some(Heatmap {
            config: config,
            data: HeatmapData {
                data: data,
                counters: HeatmapCounters::new(),
                iterator: 0,
                start: start,
                stop: start + config.slice_duration * config.num_slices as u64,
            },
            properties: HeatmapProperties,
        })
    }

    /// clear the heatmap data
    ///
    /// # Example
    /// ```
    /// # use heatmap::{Heatmap,HeatmapConfig};
    ///
    /// let mut h = Heatmap::new(
    ///     HeatmapConfig{
    ///         max_value: 1000000,
    ///         precision: 3,
    ///         max_memory: 0,
    ///			slice_duration: 1000000000,
    ///			num_slices: 300,
    /// }).unwrap();
    ///
    /// h.increment(1, 1);
    /// assert_eq!(h.entries(), 1);
    /// h.clear();
    /// assert_eq!(h.entries(), 0);
    pub fn clear(&mut self) -> Result<(), &'static str> {
        for i in 0..self.config.num_slices {
            match self.data.data[i].clear() {
                Ok(_) => {}
                Err(e) => {
                    return Err(e);
                }
            }
        }

        self.data.counters.clear();
        self.data.start = time::precise_time_ns();
        self.data.stop = self.data.start +
                         self.config.slice_duration * self.config.num_slices as u64;
        Ok(())
    }

    /// increment the count for a value at a time
    ///
    /// # Example
    /// ```
    /// extern crate heatmap;
    /// extern crate time;
    ///
    /// let mut h = heatmap::Heatmap::new().unwrap();
    ///
    /// h.increment(time::precise_time_ns(), 1);
    /// assert_eq!(h.entries(), 1);
    pub fn increment(&mut self, time: u64, value: u64) -> Result<(), &'static str> {
        self.record(time, value, 1_u64)
    }

    /// record additional counts for value at a time
    ///
    /// # Example
    /// ```
    /// extern crate heatmap;
    /// extern crate time;
    ///
    /// let mut h = heatmap::Heatmap::new().unwrap();
    ///
    /// h.record(time::precise_time_ns(), 1, 1);
    /// assert_eq!(h.entries(), 1);
    ///
    /// h.record(time::precise_time_ns(), 2, 2);
    /// assert_eq!(h.entries(), 3);
    ///
    /// h.record(time::precise_time_ns(), 10, 10);
    /// assert_eq!(h.entries(), 13);
    pub fn record(&mut self, time: u64, value: u64, count: u64) -> Result<(), &'static str> {
        self.data.counters.entries_total = self.data.counters.entries_total.saturating_add(count);

        match self.histogram_index(time) {
            Ok(histogram_index) => {
                self.data.data[histogram_index].record(value, count)
            }
            Err(e) => {
                Err(e)
            }
        }
    }

    pub fn get(&mut self, time: u64, value: u64) -> Result<u64, &'static str> {
        match self.histogram_index(time) {
            Ok(histogram_index) => {
                match self.data.data[histogram_index].get(value) {
                    Some(count) => {
                        Ok(count)
                    }
                    None => {
                        Err("histogram didn't have")
                    }
                }
            }
            Err(e) => {
                Err(e)
            }
        }
    }

    /// internal function to find the index of the histogram in the heatmap
    fn histogram_index(&mut self, time: u64) -> Result<usize, &'static str> {
        if time < self.data.start {
            return Err("sample too early");
        } else if time > self.data.stop {
            return Err("sample too late");
        }
        let index: usize = ((time - self.data.start) as f64 /
                            self.config.slice_duration as f64)
                               .floor() as usize;
        println!("index: time: {} is {}", time, index);
        Ok(index)
    }

    /// return the number of entries in the Histogram
    ///
    /// # Example
    /// ```
    /// extern crate heatmap;
    /// extern crate time;
    ///
    /// let mut h = heatmap::Heatmap::new().unwrap();
    ///
    /// assert_eq!(h.entries(), 0);
    /// h.record(time::precise_time_ns(), 1, 1);
    /// assert_eq!(h.entries(), 1);
    pub fn entries(&mut self) -> u64 {
        self.data.counters.entries_total
    }

    /// merge one Heatmap into another Heatmap
    ///
    /// # Example
    /// ```
    /// extern crate heatmap;
    /// extern crate time;
    ///
    /// let mut c = heatmap::HeatmapConfig::new();
    /// c.num_slices(61);
    ///
    /// let mut a = heatmap::Heatmap::configured(c).unwrap();
    ///
    /// let mut b = heatmap::Heatmap::new().unwrap();
    ///
    /// assert_eq!(a.entries(), 0);
    /// assert_eq!(b.entries(), 0);
    ///
    /// let _ = a.increment(1, 1);
    /// let _ = b.increment(1, 1);
    ///
    /// assert_eq!(a.entries(), 1);
    /// assert_eq!(b.entries(), 1);
    ///
    /// a.merge(&mut b);
    ///
    /// assert_eq!(a.entries(), 2);
    /// assert_eq!(a.get(1, 1).unwrap(), 1);
    /// assert_eq!(a.get(2, 1).unwrap(), 1);
    pub fn merge(&mut self, other: &mut Heatmap) {
        loop {
            match other.next() {
                Some(other_slice) => {
                    match self.histogram_index(other_slice.clone().start()) {
                        Ok(i) => {
                            self.data.data[i].merge(&mut other_slice.clone().histogram.clone());
                            self.data.counters.entries_total += other_slice.clone()
                                                                           .histogram
                                                                           .clone()
                                                                           .entries();
                        }
                        Err(e) => {}
                    }

                }
                None => {
                    break;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "specialization", feature(specialization))]

#[macro_use] extern crate nom;

mod display_html_safe;
pub use display_html_safe::DisplayHtmlSafe;

mod conditional;
pub use conditional::Conditional;

mod negative_iterator;
pub use negative_iterator::NegativeIterator;
<commit_msg>Start documenting inline with rustdoc<commit_after>/*!

Bart is a compile time templating language inspired by
[Mustache](https://mustache.github.io/mustache.5.html). It plays to Rust's
strengths by statically compiling the template into efficient code and
performing full variable resolution and type checking at compile time.

Cargo dependencies
==================
To use Bart, add these dependencies to your `Cargo.toml`:

```toml
[dependencies]
bart = "0.1.0"
bart_derive = "0.1.0"
```

Example
=======
Given the template file `hello_world.html`:

```text
Hello {{name}}
```

We can write the following program:

```
#[macro_use] extern crate bart_derive;

#[derive(BartDisplay)]
#[template = "examples/hello_world.html"]
struct HelloWorld<'a> {
    name: &'a str,
}

fn main() {
    print!("{}", &HelloWorld { name: "World" });
#   assert_eq!("Hello World\n", format!("{}", &HelloWorld { name: "World" }));
}
```

*/

#![cfg_attr(feature = "specialization", feature(specialization))]

#[macro_use] extern crate nom;

mod display_html_safe;

// With specialization, DisplayHtmlSafe could be something that the
// user wants to deal with. But specialization is still unstable.
#[doc(hidden)]
pub use display_html_safe::DisplayHtmlSafe;

mod conditional;
pub use conditional::Conditional;

mod negative_iterator;
pub use negative_iterator::NegativeIterator;
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate comrak;
#[cfg(feature = "csv")]
extern crate csv;
extern crate svgbob;
extern crate typed_arena;
extern crate url;
extern crate url_path;
#[macro_use]
extern crate log;
extern crate ammonia;
#[macro_use]
extern crate maplit;

use ammonia::Builder;
use comrak::nodes::{AstNode, NodeHtmlBlock, NodeValue};
use comrak::{format_html, parse_document, ComrakOptions};
use errors::Error;
use std::collections::HashMap;
use svgbob::Grid;
use typed_arena::Arena;
use url_path::UrlPath;
use std::sync::{Arc,Mutex};

mod errors {
    use std::string::FromUtf8Error;
    #[derive(Debug)]
    pub enum Error {
        ParseError,
        PluginError,
        Utf8Error(FromUtf8Error),
    }
    impl From<FromUtf8Error> for Error {
        fn from(e: FromUtf8Error) -> Self {
            Error::Utf8Error(e)
        }
    }
}

/// convert bob ascii diagrams to svg
fn bob_handler(s: &str, _settings: &Settings) -> Result<String, Error> {
    let grid = Grid::from_str(s, &svgbob::Settings::default());
    let (width, height) = grid.get_size();
    let svg = grid.get_svg();
    let bob_container = format!(
        "
{}
",
        width, height, svg
    );
    Ok(bob_container)
}

/// convert csv content into html table
#[cfg(feature = "csv")]
fn csv_handler(s: &str, _settings: &Settings) -> Result<String, Error> {
    let mut buff = String::new();
    let mut rdr = csv::Reader::from_reader(s.as_bytes());
    buff.push_str("
");
    buff.push_str("
");
    for header in rdr.headers() {
        buff.push_str("
");
        for h in header {
            buff.push_str(&format!("{}	", h));
        }
        buff.push_str("
");
    }
    buff.push_str("
");
    buff.push_str("
");
    buff.push_str("
");
    for record in rdr.records() {
        buff.push_str("
");
        if let Ok(record) = record {
            for value in record.iter() {
                buff.push_str(&format!("{}	", value));
            }
        }
        buff.push_str("
");
    }
    buff.push_str("
");
    buff.push_str("
");
    Ok(buff)
}

pub struct Settings {
    base_dir: Option<String>,
    clean_xss: bool,
}

impl Default for Settings {
    fn default() -> Self {
        Settings {
            base_dir: None,
            clean_xss: true,
        }
    }
}

pub fn parse(arg: &str) -> Result {
    parse_with_settings(arg, &Settings::default())
}

pub fn parse_with_base_dir(arg: &str, base_dir: &str) -> Result {
    let settings = Settings {
        base_dir: Some(base_dir.to_string()),
        ..Default::default()
    };
    parse_with_settings(arg, &settings)
}

pub fn parse_with_settings(arg: &str, settings: &Settings) -> Result {
    let mut plugins: HashMap<String, Box<Fn(&str, &Settings) -> Result<String, Error>>> =
        HashMap::new();
    plugins.insert("bob".into(), Box::new(bob_handler));
    #[cfg(feature = "csv")]
    plugins.insert("csv".into(), Box::new(csv_handler));
    let html = parse_via_comrak(arg, &plugins, settings);
    html
}

pub fn parse_bob(arg: &str) -> Result<String, Error> {
    bob_handler(arg, &Settings::default())
}

#[cfg(feature = "csv")]
pub fn parse_csv(arg: &str) -> Result<String, Error> {
    csv_handler(arg, &Settings::default())
}

/// Plugin info, format:
/// [<selector>] <plugin_name>[@version][://<URI>]
/// example:
/// #table1 csv://data_file.csv
#[allow(dead_code)]
struct PluginInfo {
    selector: Option<String>,
    plugin_name: String,
    version: Option<String>,
    uri: Option<String>,
}

#[derive(Debug)]
pub struct Html{
    pub title: Option<String>,
    pub content: String,
}

fn parse_via_comrak(
    arg: &str,
    plugins: &HashMap<String, Box<Fn(&str, &Settings) -> Result<String, Error>>>,
    settings: &Settings,
) -> Result {
    // The returned nodes are created in the supplied Arena, and are bound by its lifetime.
    let arena = Arena::new();
    let option = ComrakOptions {
        hardbreaks: true,
        github_pre_lang: true,
        default_info_string: None,
        width: 0,
        ext_strikethrough: true,
        ext_tagfilter: true,
        ext_table: true,
        ext_autolink: true,
        ext_tasklist: true,
        ext_superscript: false,
        ext_header_ids: None,
        ext_footnotes: true,
        ext_description_lists: true,
        smart: false,
        safe: true,
    };

    let title: Arc<Mutex<Option<String>>> = Arc::new(Mutex::new(None));
    let is_heading: Arc<Mutex<bool>> = Arc::new(Mutex::new(false));

    let root = parse_document(&arena, arg, &option);

    fn iter_nodes<'a, F>(node: &'a AstNode<'a>, is_heading: Arc<Mutex<bool>>, title: Arc<Mutex<Option<String>>>, f: &F)
    where
        F: Fn(&'a AstNode<'a>),
    {
        f(node);
        for c in node.children() {
            iter_nodes(c, is_heading.clone(), title.clone(), f);
        }
    }

    iter_nodes(root, is_heading.clone(), title.clone(), &|node| {
        let ref mut value = node.data.borrow_mut().value;
        let new_value = match value {
            &mut NodeValue::CodeBlock(ref codeblock) => {
                let codeblock_info = String::from_utf8(codeblock.info.to_owned()).unwrap();
                if let Some(handler) = plugins.get(&codeblock_info) {
                    let codeblock_literal =
                        String::from_utf8(codeblock.literal.to_owned()).unwrap();
                    match handler(&codeblock_literal, settings) {
                        Ok(out) => NodeValue::HtmlBlock(NodeHtmlBlock {
                            literal: out.into_bytes(),
                            block_type: 0,
                        }),
                        Err(_) => NodeValue::CodeBlock(codeblock.clone()),
                    }
                } else {
                    value.clone()
                }
            }
            &mut NodeValue::Link(ref nodelink) => {
                if let Ok(url) = String::from_utf8(nodelink.url.clone()) {
                    if let Some(ref base_dir) = settings.base_dir {
                        let url1 = UrlPath::new(&url);
                        let url2 = url1.normalize();
                        let url3 = if url1.is_external() {
                            url2
                        } else if url1.is_absolute() {
                            url2
                        } else {
                            format!("{}/{}", base_dir, url)
                        };
                        let url4 = UrlPath::new(&url3);
                        let url5 = url4.normalize();
                        let url6 = format!("/#{}", url5);
                        info!("url6: {}", url6);
                        let mut new_nodelink = nodelink.clone();
                        new_nodelink.url = url6.into_bytes();
                        NodeValue::Link(new_nodelink)
                    } else {
                        value.clone()
                    }
                } else {
                    value.clone()
                }
            }
            &mut NodeValue::Heading(ref heading) => {
                if heading.level == 1{
                    if let Ok(mut is_heading) = is_heading.lock(){
                        *is_heading = true;
                    }
                }
                value.clone()
            }
            &mut NodeValue::Text(ref text) => {
                if let Ok(is_heading) = is_heading.lock() {
                    if *is_heading{
                        let txt = String::from_utf8(text.to_owned()).expect("Unable to convert to string");
                        if let Ok(mut title) = title.lock(){
                            if title.is_none(){ // only when unset
                                *title = Some(txt.to_string());
                            }
                        }
                    }
                }
                value.clone()
            }
            _ => value.clone(),
        };
        *value = new_value;
    });

    let mut html = vec![];

    if let Ok(()) = format_html(root, &ComrakOptions::default(), &mut html) {
        let render_html = String::from_utf8(html)?;
        let title = if let Ok(mut got) = title.lock(){
            if let Some(ref got) = *got{
                Some(got.to_string())
            }else{
                None
            }
        }else{
            None
        };
        if settings.clean_xss {
            let builder = ammonia_builder();
            let clean_html = builder.clean(&render_html).to_string();
            Ok(Html{title, content: clean_html})
        } else {
            Ok(Html{title, content:render_html})
        }
    } else {
        Err(Error::ParseError)
    }
}

/// Create an ammonia builder and whitelisting the svg tags and attributes
fn ammonia_builder<'a>() -> Builder<'a> {
    let map: HashMap<&str, Vec<&str>> = hashmap!{
        "div" => vec!["class","style"],
        "svg" => vec!["class","font-family","font-size","height","width","xmlns"],
        "text" => vec!["class", "x","y"],
        "rect" => vec!["class", "fill", "height", "width", "x", "y", "stroke", "stroke-width"],
        "circle" => vec!["class","cx","cy","r", "fill", "stroke", "stroke-width"],
        "path" => vec!["class","fill"],
        "line" => vec!["class", "x1","x2", "y1", "y2", "marker-start", "marker-end"],
        "path" => vec!["class","d","fill","stroke","stroke-dasharry"],
        "polygon" => vec!["class","points","fill","stroke","stroke-dasharry"],
        "g" => vec![],
        "defs" => vec![],
        "style" => vec!["type"],
        "marker" => vec!["id","markerHeight","markerUnits","markerWidth","orient","refX", "refY", "viewBox"]
    };
    let mut builder = Builder::default();
    for (k, v) in map.iter() {
        builder.add_tags(std::iter::once(*k));
        for att in v.iter() {
            builder.add_tag_attributes(k, std::iter::once(*att));
        }
    }
    builder
}

#[cfg(test)]
mod test{

    use super::*;

    #[test]
    fn title(){
        let input = "# Hello\n
        world";
        let html = parse(input);
        println!("html: {:?}", html);
        assert!(html.is_ok());
        let html = html.unwrap();
        assert_eq!(Some("Hello".to_string()), html.title);

    }
}
<commit_msg>Add external link settings<commit_after>#![deny(warnings)]

extern crate comrak;
#[cfg(feature = "csv")]
extern crate csv;
extern crate svgbob;
extern crate typed_arena;
extern crate url;
extern crate url_path;
#[macro_use]
extern crate log;
extern crate ammonia;
#[macro_use]
extern crate maplit;

use ammonia::Builder;
use comrak::nodes::{AstNode, NodeHtmlBlock, NodeValue};
use comrak::{format_html, parse_document, ComrakOptions};
use errors::Error;
use std::collections::HashMap;
use svgbob::Grid;
use typed_arena::Arena;
use url_path::UrlPath;
use std::sync::{Arc,Mutex};

mod errors {
    use std::string::FromUtf8Error;
    #[derive(Debug)]
    pub enum Error {
        ParseError,
        PluginError,
        Utf8Error(FromUtf8Error),
    }
    impl From<FromUtf8Error> for Error {
        fn from(e: FromUtf8Error) -> Self {
            Error::Utf8Error(e)
        }
    }
}

/// convert bob ascii diagrams to svg
fn bob_handler(s: &str, _settings: &Settings) -> Result<String, Error> {
    let grid = Grid::from_str(s, &svgbob::Settings::default());
    let (width, height) = grid.get_size();
    let svg = grid.get_svg();
    let bob_container = format!(
        "
{}
",
        width, height, svg
    );
    Ok(bob_container)
}

/// convert csv content into html table
#[cfg(feature = "csv")]
fn csv_handler(s: &str, _settings: &Settings) -> Result<String, Error> {
    let mut buff = String::new();
    let mut rdr = csv::Reader::from_reader(s.as_bytes());
    buff.push_str("
");
    buff.push_str("
");
    for header in rdr.headers() {
        buff.push_str("
");
        for h in header {
            buff.push_str(&format!("{}	", h));
        }
        buff.push_str("
");
    }
    buff.push_str("
");
    buff.push_str("
");
    buff.push_str("
");
    for record in rdr.records() {
        buff.push_str("
");
        if let Ok(record) = record {
            for value in record.iter() {
                buff.push_str(&format!("{}	", value));
            }
        }
        buff.push_str("
");
    }
    buff.push_str("
");
    buff.push_str("
");
    Ok(buff)
}

pub struct Settings {
    /// add a base directory for all links to other md files
    base_dir: Option<String>,
    /// apply ammonia to remove xss from the generated html
    clean_xss: bool,
    /// if true, external links that doesn't end with `.md` will be linked as is
    link_non_md_external: bool,
}

impl Default for Settings {
    fn default() -> Self {
        Settings {
            base_dir: None,
            clean_xss: true,
            link_non_md_external: true,
        }
    }
}

pub fn parse(arg: &str) -> Result {
    parse_with_settings(arg, &Settings::default())
}

pub fn parse_with_base_dir(arg: &str, base_dir: &str) -> Result {
    let settings = Settings {
        base_dir: Some(base_dir.to_string()),
        ..Default::default()
    };
    parse_with_settings(arg, &settings)
}

pub fn parse_with_settings(arg: &str, settings: &Settings) -> Result {
    let mut plugins: HashMap<String, Box<Fn(&str, &Settings) -> Result<String, Error>>> =
        HashMap::new();
    plugins.insert("bob".into(), Box::new(bob_handler));
    #[cfg(feature = "csv")]
    plugins.insert("csv".into(), Box::new(csv_handler));
    let html = parse_via_comrak(arg, &plugins, settings);
    html
}

pub fn parse_bob(arg: &str) -> Result<String, Error> {
    bob_handler(arg, &Settings::default())
}

#[cfg(feature = "csv")]
pub fn parse_csv(arg: &str) -> Result<String, Error> {
    csv_handler(arg, &Settings::default())
}

/// Plugin info, format:
/// [<selector>] <plugin_name>[@version][://<URI>]
/// example:
/// #table1 csv://data_file.csv
#[allow(dead_code)]
struct PluginInfo {
    selector: Option<String>,
    plugin_name: String,
    version: Option<String>,
    uri: Option<String>,
}

#[derive(Debug)]
pub struct Html{
    pub title: Option<String>,
    pub content: String,
}

fn parse_via_comrak(
    arg: &str,
    plugins: &HashMap<String, Box<Fn(&str, &Settings) -> Result<String, Error>>>,
    settings: &Settings,
) -> Result {
    // The returned nodes are created in the supplied Arena, and are bound by its lifetime.
    let arena = Arena::new();
    let option = ComrakOptions {
        hardbreaks: true,
        github_pre_lang: true,
        default_info_string: None,
        width: 0,
        ext_strikethrough: true,
        ext_tagfilter: true,
        ext_table: true,
        ext_autolink: true,
        ext_tasklist: true,
        ext_superscript: false,
        ext_header_ids: None,
        ext_footnotes: true,
        ext_description_lists: true,
        smart: false,
        safe: true,
    };

    let title: Arc<Mutex<Option<String>>> = Arc::new(Mutex::new(None));
    let is_heading: Arc<Mutex<bool>> = Arc::new(Mutex::new(false));

    let root = parse_document(&arena, arg, &option);

    fn iter_nodes<'a, F>(node: &'a AstNode<'a>, is_heading: Arc<Mutex<bool>>, title: Arc<Mutex<Option<String>>>, f: &F)
    where
        F: Fn(&'a AstNode<'a>),
    {
        f(node);
        for c in node.children() {
            iter_nodes(c, is_heading.clone(), title.clone(), f);
        }
    }

    iter_nodes(root, is_heading.clone(), title.clone(), &|node| {
        let ref mut value = node.data.borrow_mut().value;
        let new_value = match value {
            &mut NodeValue::CodeBlock(ref codeblock) => {
                let codeblock_info = String::from_utf8(codeblock.info.to_owned()).unwrap();
                if let Some(handler) = plugins.get(&codeblock_info) {
                    let codeblock_literal =
                        String::from_utf8(codeblock.literal.to_owned()).unwrap();
                    match handler(&codeblock_literal, settings) {
                        Ok(out) => NodeValue::HtmlBlock(NodeHtmlBlock {
                            literal: out.into_bytes(),
                            block_type: 0,
                        }),
                        Err(_) => NodeValue::CodeBlock(codeblock.clone()),
                    }
                } else {
                    value.clone()
                }
            }
            &mut NodeValue::Link(ref nodelink) => {
                if let Ok(url) = String::from_utf8(nodelink.url.clone()) {
                    if let Some(ref base_dir) = settings.base_dir {
                        let url1 = UrlPath::new(&url);
                        let url2 = url1.normalize();
                        let url3 = if url1.is_external() {
                            url2
                        } else if url1.is_absolute() {
                            url2
                        } else {
                            format!("{}/{}", base_dir, url)
                        };
                        let url4 = UrlPath::new(&url3);
                        let url5 = url4.normalize();
                        let url6 = if url4.is_external()
                            && !url4.is_extension("md")
                            && settings.link_non_md_external {
                            // leave as it
                            url5
                        }else{
                            format!("/#{}", url5)
                        };
                        info!("url6: {}", url6);
                        let mut new_nodelink = nodelink.clone();
                        new_nodelink.url = url6.into_bytes();
                        NodeValue::Link(new_nodelink)
                    } else {
                        value.clone()
                    }
                } else {
                    value.clone()
                }
            }
            &mut NodeValue::Heading(ref heading) => {
                if heading.level == 1{
                    if let Ok(mut is_heading) = is_heading.lock(){
                        *is_heading = true;
                    }
                }
                value.clone()
            }
            &mut NodeValue::Text(ref text) => {
                if let Ok(is_heading) = is_heading.lock() {
                    if *is_heading{
                        let txt = String::from_utf8(text.to_owned()).expect("Unable to convert to string");
                        if let Ok(mut title) = title.lock(){
                            if title.is_none(){ // only when unset
                                *title = Some(txt.to_string());
                            }
                        }
                    }
                }
                value.clone()
            }
            _ => value.clone(),
        };
        *value = new_value;
    });

    let mut html = vec![];

    if let Ok(()) = format_html(root, &ComrakOptions::default(), &mut html) {
        let render_html = String::from_utf8(html)?;
        let title = if let Ok(mut got) = title.lock(){
            if let Some(ref got) = *got{
                Some(got.to_string())
            }else{
                None
            }
        }else{
            None
        };
        if settings.clean_xss {
            let builder = ammonia_builder();
            let clean_html = builder.clean(&render_html).to_string();
            Ok(Html{title, content: clean_html})
        } else {
            Ok(Html{title, content:render_html})
        }
    } else {
        Err(Error::ParseError)
    }
}

/// Create an ammonia builder and whitelisting the svg tags and attributes
fn ammonia_builder<'a>() -> Builder<'a> {
    let map: HashMap<&str, Vec<&str>> = hashmap!{
        "div" => vec!["class","style"],
        "svg" => vec!["class","font-family","font-size","height","width","xmlns"],
        "text" => vec!["class", "x","y"],
        "rect" => vec!["class", "fill", "height", "width", "x", "y", "stroke", "stroke-width"],
        "circle" => vec!["class","cx","cy","r", "fill", "stroke", "stroke-width"],
        "path" => vec!["class","fill"],
        "line" => vec!["class", "x1","x2", "y1", "y2", "marker-start", "marker-end"],
        "path" => vec!["class","d","fill","stroke","stroke-dasharry"],
        "polygon" => vec!["class","points","fill","stroke","stroke-dasharry"],
        "g" => vec![],
        "defs" => vec![],
        "style" => vec!["type"],
        "marker" => vec!["id","markerHeight","markerUnits","markerWidth","orient","refX", "refY", "viewBox"]
    };
    let mut builder = Builder::default();
    for (k, v) in map.iter() {
        builder.add_tags(std::iter::once(*k));
        for att in v.iter() {
            builder.add_tag_attributes(k, std::iter::once(*att));
        }
    }
    builder
}

#[cfg(test)]
mod test{

    use super::*;

    #[test]
    fn title(){
        let input = "# Hello\n
        world";
        let html = parse(input);
        println!("html: {:?}", html);
        assert!(html.is_ok());
        let html = html.unwrap();
        assert_eq!(Some("Hello".to_string()), html.title);

    }
}
<|endoftext|>


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

extern crate libc;
extern crate errno;
#[macro_use]
extern crate bitflags;

mod device;
mod frontend;
mod demux;

pub use device::{ReadWriteMode,BlockMode,DeviceError};
pub use frontend::*;
pub use frontend::properties::*;
pub use demux::*;<commit_msg>Expose modules, add convenience functions.<commit_after>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate libc;
extern crate errno;
#[macro_use]
extern crate bitflags;

use std::path::Path;

mod device;
mod frontend;
mod demux;

pub use device::{ReadWriteMode,BlockMode,DeviceError,DeviceResult};
pub use frontend::*;
pub use frontend::properties::*;
pub use frontend::caps as frontendcaps;
pub use demux::*;
pub use demux::flags as demuxflags;

pub fn open_frontend(adapter: u32, frontend: u32, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Frontend> {
    let path_string = format!("/dev/dvb/adapter{}/frontend{}", adapter, frontend);
    let path = Path::new(&path_string);
    Frontend::open(path, rw_mode, block_mode)
}

pub fn open_demux(adapter: u32, demux: u32, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Demux> {
    let path_string = format!("/dev/dvb/adapter{}/demux{}", adapter, demux);
    let path = Path::new(&path_string);
    Demux::open(path, rw_mode, block_mode)
}

pub fn open_dvr(adapter: u32, dvr: u32, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Dvr> {
    let path_string = format!("/dev/dvb/adapter{}/dvr{}", adapter, dvr);
    let path = Path::new(&path_string);
    Dvr::open(path, rw_mode, block_mode)
}
<|endoftext|>


<commit_before>use std::io::BufRead;

pub fn count_lines_of_code<R: BufRead>(input: R) -> usize {
    input.lines()
        // TODO: error handling
        .map(|result| result.unwrap())
        .filter(|line| line.trim().len() != 0)
        .count()
}

mod test {
    #[test]
    fn counts_lines() {
        use std::io::Cursor;
        let cursor = Cursor::new(b"lorem\nipsum\r\ndolor");
        let loc = super::count_lines_of_code(cursor);
        assert_eq!(loc, 3);
    }

    #[test]
    fn ignores_empty_lines() {
        use std::io::Cursor;
        let cursor = Cursor::new(b"lorem\n \r\ndolor");
        let loc = super::count_lines_of_code(cursor);
        assert_eq!(loc, 2);
    }
}<commit_msg>added sloppy single line comment handling<commit_after>use std::io::BufRead;

pub fn count_lines_of_code<R: BufRead>(input: R) -> usize {
    input.lines()
        // TODO: error handling
        .map(|result| result.unwrap())
        .map(|line| line.trim().to_string())
        .filter(|trimmed_line| trimmed_line.len() != 0)
        .filter(|trimmed_line| !trimmed_line.starts_with("//"))
        .count()
}

mod test {
    #[test]
    fn counts_lines() {
        use std::io::Cursor;
        let cursor = Cursor::new(b"counts\ncounts\r\ncounts");
        let loc = super::count_lines_of_code(cursor);
        assert_eq!(loc, 3);
    }

    #[test]
    fn ignores_empty_lines() {
        use std::io::Cursor;
        let cursor = Cursor::new(b"counts\n \r\ncounts");
        let loc = super::count_lines_of_code(cursor);
        assert_eq!(loc, 2);
    }

    #[test]
    fn ignores_single_line_comments() {
        use std::io::Cursor;
        let cursor = Cursor::new(b"counts\ncounts//\n//doesnt");
        let loc = super::count_lines_of_code(cursor);
        assert_eq!(loc, 2);
    }
}<|endoftext|>


<commit_before>//! Least squares

use lapacke;
use ndarray::{ErrorKind, ShapeError};
use num_traits::Zero;

use crate::error::*;
use crate::layout::MatrixLayout;
use crate::types::*;

use super::into_result;

/// Result of LeastSquares
pub struct LeastSquaresOutput<A: Scalar> {
    /// singular values
    pub singular_values: Vec<A::Real>,
    /// The rank of the input matrix A
    pub rank: i32,
}

/// Wraps `*gelsd`
pub trait LeastSquaresSvdDivideConquer_: Scalar {
    unsafe fn least_squares(
        a_layout: MatrixLayout,
        a: &mut [Self],
        b: &mut [Self],
    ) -> Result<LeastSquaresOutput<Self>>;

    unsafe fn least_squares_nrhs(
        a_layout: MatrixLayout,
        a: &mut [Self],
        b_layout: MatrixLayout,
        b: &mut [Self],
    ) -> Result<LeastSquaresOutput<Self>>;
}

macro_rules! impl_least_squares {
    ($scalar:ty, $gelsd:path) => {
        impl LeastSquaresSvdDivideConquer_ for $scalar {
            unsafe fn least_squares(
                a_layout: MatrixLayout,
                a: &mut [Self],
                b: &mut [Self],
            ) -> Result<LeastSquaresOutput<Self>> {
                let (m, n) = a_layout.size();
                if (m as usize) > b.len() || (n as usize) > b.len() {
                    return Err(LinalgError::Shape(ShapeError::from_kind(
                        ErrorKind::IncompatibleShape,
                    )));
                }
                let k = ::std::cmp::min(m, n);
                let nrhs = 1;
                let rcond: Self::Real = -1.;
                let mut singular_values: Vec<Self::Real> = vec![Self::Real::zero(); k as usize];
                let mut rank: i32 = 0;

                let status = $gelsd(
                    a_layout.lapacke_layout(),
                    m,
                    n,
                    nrhs,
                    a,
                    a_layout.lda(),
                    b,
                    // this is the 'leading dimension of b', in the case where
                    // b is a single vector, this should be 1
                    nrhs,
                    &mut singular_values,
                    rcond,
                    &mut rank,
                );

                // FIXME: make use of this fact (from lapack docs)
                // https://www.netlib.org/lapack/explore-html/d7/d3b/group__double_g_esolve_ga94bd4a63a6dacf523e25ff617719f752
                // could check how this is done by scipy here: https://github.com/scipy/scipy/blob/v1.4.1/scipy/linalg/basic.py#L1047-L1246
                // If m >= n and RANK = n, the residual
                // sum-of-squares for the solution in the i-th column is given
                // by the sum of squares of elements n+1:m in that column.
                into_result(
                    status,
                    LeastSquaresOutput {
                        singular_values,
                        rank,
                    },
                )
            }

            unsafe fn least_squares_nrhs(
                a_layout: MatrixLayout,
                a: &mut [Self],
                b_layout: MatrixLayout,
                b: &mut [Self],
            ) -> Result<LeastSquaresOutput<Self>> {
                let (m, n) = a_layout.size();
                if (m as usize) > b.len()
                    || (n as usize) > b.len()
                    || a_layout.lapacke_layout() != b_layout.lapacke_layout()
                {
                    return Err(LinalgError::Shape(ShapeError::from_kind(
                        ErrorKind::IncompatibleShape,
                    )));
                }
                let k = ::std::cmp::min(m, n);
                let nrhs = b_layout.size().1;
                let rcond: Self::Real = -1.;
                let mut singular_values: Vec<Self::Real> = vec![Self::Real::zero(); k as usize];
                let mut rank: i32 = 0;

                let status = $gelsd(
                    a_layout.lapacke_layout(),
                    m,
                    n,
                    nrhs,
                    a,
                    a_layout.lda(),
                    b,
                    // this is the 'leading dimension of b', in the case where
                    // b is a single vector, this should be 1
                    b_layout.lda(),
                    &mut singular_values,
                    rcond,
                    &mut rank,
                );

                // FIXME: make use of this fact (from lapack docs)
                // https://www.netlib.org/lapack/explore-html/d7/d3b/group__double_g_esolve_ga94bd4a63a6dacf523e25ff617719f752
                // could check how this is done by scipy here: https://github.com/scipy/scipy/blob/v1.4.1/scipy/linalg/basic.py#L1047-L1246
                // If m >= n and RANK = n, the residual
                // sum-of-squares for the solution in the i-th column is given
                // by the sum of squares of elements n+1:m in that column.
                into_result(
                    status,
                    LeastSquaresOutput {
                        singular_values,
                        rank,
                    },
                )
            }
        }
    };
}

impl_least_squares!(f64, lapacke::dgelsd);
impl_least_squares!(f32, lapacke::sgelsd);
impl_least_squares!(c64, lapacke::zgelsd);
impl_least_squares!(c32, lapacke::cgelsd);
<commit_msg>Remove obsolete comments<commit_after>//! Least squares

use lapacke;
use ndarray::{ErrorKind, ShapeError};
use num_traits::Zero;

use crate::error::*;
use crate::layout::MatrixLayout;
use crate::types::*;

use super::into_result;

/// Result of LeastSquares
pub struct LeastSquaresOutput<A: Scalar> {
    /// singular values
    pub singular_values: Vec<A::Real>,
    /// The rank of the input matrix A
    pub rank: i32,
}

/// Wraps `*gelsd`
pub trait LeastSquaresSvdDivideConquer_: Scalar {
    unsafe fn least_squares(
        a_layout: MatrixLayout,
        a: &mut [Self],
        b: &mut [Self],
    ) -> Result<LeastSquaresOutput<Self>>;

    unsafe fn least_squares_nrhs(
        a_layout: MatrixLayout,
        a: &mut [Self],
        b_layout: MatrixLayout,
        b: &mut [Self],
    ) -> Result<LeastSquaresOutput<Self>>;
}

macro_rules! impl_least_squares {
    ($scalar:ty, $gelsd:path) => {
        impl LeastSquaresSvdDivideConquer_ for $scalar {
            unsafe fn least_squares(
                a_layout: MatrixLayout,
                a: &mut [Self],
                b: &mut [Self],
            ) -> Result<LeastSquaresOutput<Self>> {
                let (m, n) = a_layout.size();
                if (m as usize) > b.len() || (n as usize) > b.len() {
                    return Err(LinalgError::Shape(ShapeError::from_kind(
                        ErrorKind::IncompatibleShape,
                    )));
                }
                let k = ::std::cmp::min(m, n);
                let nrhs = 1;
                let rcond: Self::Real = -1.;
                let mut singular_values: Vec<Self::Real> = vec![Self::Real::zero(); k as usize];
                let mut rank: i32 = 0;

                let status = $gelsd(
                    a_layout.lapacke_layout(),
                    m,
                    n,
                    nrhs,
                    a,
                    a_layout.lda(),
                    b,
                    // this is the 'leading dimension of b', in the case where
                    // b is a single vector, this is 1
                    nrhs,
                    &mut singular_values,
                    rcond,
                    &mut rank,
                );

                into_result(
                    status,
                    LeastSquaresOutput {
                        singular_values,
                        rank,
                    },
                )
            }

            unsafe fn least_squares_nrhs(
                a_layout: MatrixLayout,
                a: &mut [Self],
                b_layout: MatrixLayout,
                b: &mut [Self],
            ) -> Result<LeastSquaresOutput<Self>> {
                let (m, n) = a_layout.size();
                if (m as usize) > b.len()
                    || (n as usize) > b.len()
                    || a_layout.lapacke_layout() != b_layout.lapacke_layout()
                {
                    return Err(LinalgError::Shape(ShapeError::from_kind(
                        ErrorKind::IncompatibleShape,
                    )));
                }
                let k = ::std::cmp::min(m, n);
                let nrhs = b_layout.size().1;
                let rcond: Self::Real = -1.;
                let mut singular_values: Vec<Self::Real> = vec![Self::Real::zero(); k as usize];
                let mut rank: i32 = 0;

                let status = $gelsd(
                    a_layout.lapacke_layout(),
                    m,
                    n,
                    nrhs,
                    a,
                    a_layout.lda(),
                    b,
                    b_layout.lda(),
                    &mut singular_values,
                    rcond,
                    &mut rank,
                );

                into_result(
                    status,
                    LeastSquaresOutput {
                        singular_values,
                        rank,
                    },
                )
            }
        }
    };
}

impl_least_squares!(f64, lapacke::dgelsd);
impl_least_squares!(f32, lapacke::sgelsd);
impl_least_squares!(c64, lapacke::zgelsd);
impl_least_squares!(c32, lapacke::cgelsd);
<|endoftext|>


<commit_before>use super::super::commands::CommandResult;
use super::super::{LayoutTree, TreeError};
use super::super::core::Direction;
use super::super::core::container::{Container, ContainerType, Handle, Layout};

use petgraph::graph::NodeIndex;
use rustwlc::WlcView;
use uuid::Uuid;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum FocusError {
    /// Reached a container where we can keep climbing the tree no longer.
    ///
    /// Usually this is a workspace, because it doesn't make sense to move a
    /// container out of a workspace
    ReachedLimit(NodeIndex),
    /// Tried to focus on a container that was not a view.
    NotAView(Uuid),
    /// Tried to focus on a container (first one),
    /// but that container was superseded by a fullscreen container (second one)
    BlockedByFullscreen(Uuid, Uuid)
}

impl LayoutTree {
    /// Focuses on the container by the uuid, if it points to a View.
    /// Otherwise, an error is returned.
    pub fn focus_on(&mut self, uuid: Uuid) -> CommandResult {
        if let Some(fullscreen_id) = try!(self.in_fullscreen_workspace(uuid)) {
            if fullscreen_id != uuid {
                return Err(TreeError::Focus(FocusError::BlockedByFullscreen(uuid, fullscreen_id)))
            }
        }
        let container = try!(self.lookup(uuid));
        match *container {
            Container::View { handle, .. } => {
                handle.focus();
                Ok(())
            },
            _ => Err(TreeError::Focus(FocusError::NotAView(uuid)))
        }
    }
    /// Focus on the container relative to the active container.
    ///
    /// If Horizontal, left and right will move within siblings.
    /// If Vertical, up and down will move within siblings.
    /// Other wise, it moves to the next sibling of the parent container.
    ///
    /// If the edge of the children is hit, it does not wrap around,
    /// but moves between ancestor siblings.
    pub fn move_focus(&mut self, direction: Direction) -> CommandResult {
        if let Some(prev_active_ix) = self.active_container {
            let active_id = self.tree[prev_active_ix].get_id();
            if let Some(fullscreen_id) = try!(self.in_fullscreen_workspace(active_id)) {
                return Err(TreeError::Focus(
                    FocusError::BlockedByFullscreen(active_id, fullscreen_id)))
            }
            let new_active_ix = self.move_focus_recurse(prev_active_ix, direction)
                .unwrap_or(prev_active_ix);
            try!(self.set_active_node(new_active_ix));
            match self.tree[self.active_container.unwrap()] {
                Container::View { ref handle, .. } => handle.focus(),
                _ => warn!("move_focus returned a non-view, cannot focus")
            }
        } else {
            return Err(TreeError::NoActiveContainer)
        }
        self.validate();
        Ok(())
    }

    fn move_focus_recurse(&mut self, node_ix: NodeIndex, direction: Direction)
                          -> Result<NodeIndex, TreeError> {
        match self.tree[node_ix].get_type() {
            ContainerType::View | ContainerType::Container => { /* continue */ },
            _ => return Err(TreeError::UuidWrongType(self.tree[node_ix].get_id(),
                                                     vec!(ContainerType::View, ContainerType::Container)))
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Active ix had no parent");
        match self.tree[parent_ix] {
            Container::Container { layout, .. } => {
                match (layout, direction) {
                    (Layout::Horizontal, Direction::Left) |
                    (Layout::Horizontal, Direction::Right) |
                    (Layout::Vertical, Direction::Up) |
                    (Layout::Vertical, Direction::Down) => {
                        let siblings = self.tree.children_of(parent_ix);
                        let cur_index = siblings.iter().position(|node| {
                            *node == node_ix
                        }).expect("Could not find self in parent");
                        let maybe_new_index = match direction {
                            Direction::Right | Direction::Down => {
                                cur_index.checked_add(1)
                            }
                            Direction::Left  | Direction::Up => {
                                cur_index.checked_sub(1)
                            }
                        };
                        if maybe_new_index.is_some() &&
                            maybe_new_index.unwrap() < siblings.len() {
                                // There is a sibling to move to.
                                let new_index = maybe_new_index.unwrap();
                                let new_active_ix = siblings[new_index];
                                match self.tree[new_active_ix].get_type() {
                                    ContainerType::Container => {
                                        let path_ix = self.tree.follow_path(new_active_ix);
                                        // If the path wasn't complete, find the first view and focus on that
                                        let node_ix = try!(self.tree.descendant_of_type(path_ix, ContainerType::View)
                                                           .map_err(|err| TreeError::PetGraph(err)));
                                        let parent_ix = try!(self.tree.parent_of(node_ix)
                                                             .map_err(|err| TreeError::PetGraph(err)));
                                        match self.tree[node_ix].get_type() {
                                            ContainerType::View | ContainerType::Container => {},
                                            _ => panic!("Following path did not lead to a container or a view!")
                                        }
                                        trace!("Moving to different view {:?} in container {:?}",
                                                self.tree[node_ix], self.tree[parent_ix]);
                                        return Ok(node_ix);
                                    },
                                    ContainerType::View => {
                                        trace!("Moving to other view {:?}", self.tree[new_active_ix]);
                                        return Ok(new_active_ix)
                                    },
                                    _ => unreachable!()
                                };
                            }
                    },
                    _ => { /* We are moving out of siblings, recurse */ }
                }
            }
            Container::Workspace { .. } => {
                return Err(TreeError::Focus(FocusError::ReachedLimit(parent_ix)));
            }
            _ => unreachable!()
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Node had no parent");
        return self.move_focus_recurse(parent_ix, direction);
    }

    /// Updates the current active container to be the next container or view
    /// to focus on after the previous view/container was moved/removed.
    ///
    /// A new view will tried to be set, starting with the children of the
    /// parent node. If a view cannot be found there, it starts climbing the
    /// tree until either a view is found or the workspace is (in which case
    /// it set the active container to the root container of the workspace)
    ///
    /// If there is a fullscreen container in this workspace, that is focused on next,
    /// with the active path updated accordingly.
    pub fn focus_on_next_container(&mut self, mut parent_ix: NodeIndex) {
        let last_ix = self.tree.active_path().last()
            .expect("Active path did not lead anywhere").0;
        let id = self.tree[last_ix].get_id();
        match self.in_fullscreen_workspace(id) {
            Ok(Some(fullscreen_id)) => {
                self.set_active_container(fullscreen_id)
                    .unwrap_or_else(|err| {
                        error!("Could not set {:?} to be the active container, \
                                even though it's the fullscreen container! {:?}",
                               fullscreen_id, err);
                        error!("{:#?}", self);
                        panic!("Could not set the fullscreen container to be \
                                the active container!")
                    });
                return;
            },
            _ => {}
        }
        // TODO Change this algorithm when we improve the pathing system
        match self.tree[last_ix] {
            Container::View { handle, .. } => {
                handle.focus();
                self.active_container = Some(last_ix);
                return
            },
            Container::Container { .. } => {
                parent_ix = last_ix;
            },
            _ => {}
        }
        while self.tree.node_type(parent_ix)
            .expect("Node not part of the tree") != ContainerType::Workspace {
                if let Ok(view_ix) = self.tree.descendant_of_type(parent_ix,
                                                                  ContainerType::View) {
                match self.tree[view_ix]
                                    .get_handle().expect("view had no handle") {
                    Handle::View(view) => view.focus(),
                    _ => panic!("View had an output handle")
                }
                trace!("Active container set to view at {:?}", view_ix);
                let id = self.tree[view_ix].get_id();
                self.set_active_container(id)
                    .expect("Could not set active container");
                return;
            }
            parent_ix = self.tree.ancestor_of_type(parent_ix,
                                                    ContainerType::Container)
                .unwrap_or_else(|_| {
                    self.tree.ancestor_of_type(parent_ix, ContainerType::Workspace)
                        .expect("Container was not part of a workspace")
                });
        }
        // If this is reached, parent is workspace
        let container_ix = self.tree.children_of(parent_ix).get(0).cloned();
        if container_ix.is_none() {
            trace!("There were no other containers to focus on, \
                    focusing on nothing in particular!");
            return;
        }
        let container_ix = container_ix.unwrap();
        let root_c_children = self.tree.grounded_children(container_ix);
        if root_c_children.len() > 0 {
            // Only searches first child of root container, can't be floating view.
            let new_active_ix = self.tree.descendant_of_type(root_c_children[0],
                                                                ContainerType::View)
                .unwrap_or(root_c_children[0]);
            let id = self.tree[new_active_ix].get_id();
            self.set_active_container(id)
                .expect("Could not set active container");
            match self.tree[new_active_ix] {
                Container::View { ref handle, .. } => {
                    debug!("Focusing on {:?}", handle);
                    handle.focus();
                },
                Container::Container { .. } => {
                    debug!("No view found, focusing on nothing in workspace {:?}", parent_ix);
                    WlcView::root().focus();
                }
                _ => unreachable!()
            };
            return;
        } else {
            let floating_children = self.tree.floating_children(container_ix);
            for child_ix in floating_children {
                if let Ok(view_ix) = self.tree.descendant_of_type(child_ix,
                                                                    ContainerType::View) {
                    match self.tree[view_ix] {
                        Container::View { handle, id, .. } => {
                            debug!("Floating view found, focusing on {:#?}", handle);
                            handle.focus();
                            self.set_active_container(id)
                                .expect("Could not set active container");
                            return;
                        },
                        _ => unreachable!()
                    };
                }
            }
        }
        trace!("Active container set to container {:?}", container_ix);
        let id = self.tree[container_ix].get_id();
        self.set_active_container(id)
            .expect("Could not set active container");

        // Update focus to new container
        self.get_active_container().map(|con| match *con {
            Container::View { ref handle, .. } => handle.focus(),
            Container::Container { .. } => WlcView::root().focus(),
            _ => panic!("Active container not view or container!")
        });
    }

    /// If the currently focused view is floating, then the non-floating at the end of
    /// the path becomes the focused view. Otherwise, the first floating view becomes
    /// the focused view.
    ///
    /// If there is no currently focused view, does nothing.
    pub fn toggle_floating_focus(&mut self) -> CommandResult {
        let active_ix = try!(self.active_container.ok_or(TreeError::NoActiveContainer));
        let id; let floating;
        {
            let container = &self.tree[active_ix];
            id = container.get_id();
            floating = container.floating();
        }
        if let Some(fullscreen_id) = try!(self.in_fullscreen_workspace(id)) {
            return Err(TreeError::Focus(FocusError::BlockedByFullscreen(id, fullscreen_id)))
        }
        if floating {
            let root_ix = self.tree.root_ix();
            let new_ix = self.tree.follow_path(root_ix);
            match self.tree[new_ix].get_type() {
                ContainerType::View | ContainerType::Container  => {
                    try!(self.set_active_node(new_ix));
                    Ok(())
                },
                type_ => {
                    error!("Path lead to the wrong container, {:#?}\n{:#?}\n{:#?}",
                           active_ix, type_, self);
                    panic!("toggle_floating_focused: bad path");
                }
            }
        } else {
            // Current view is not floating, gotta focus on floating view
            let root_c_ix = self.root_container_ix()
                .expect("No root container ancestor of active container");
            let floating_children = self.tree.floating_children(root_c_ix);
            if floating_children.len() > 0 {
                try!(self.set_active_node(floating_children[0]));
            }
            Ok(())
        }
    }
}
<commit_msg>Fixed indents<commit_after>use super::super::commands::CommandResult;
use super::super::{LayoutTree, TreeError};
use super::super::core::Direction;
use super::super::core::container::{Container, ContainerType, Handle, Layout};

use petgraph::graph::NodeIndex;
use rustwlc::WlcView;
use uuid::Uuid;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum FocusError {
    /// Reached a container where we can keep climbing the tree no longer.
    ///
    /// Usually this is a workspace, because it doesn't make sense to move a
    /// container out of a workspace
    ReachedLimit(NodeIndex),
    /// Tried to focus on a container that was not a view.
    NotAView(Uuid),
    /// Tried to focus on a container (first one),
    /// but that container was superseded by a fullscreen container (second one)
    BlockedByFullscreen(Uuid, Uuid)
}

impl LayoutTree {
    /// Focuses on the container by the uuid, if it points to a View.
    /// Otherwise, an error is returned.
    pub fn focus_on(&mut self, uuid: Uuid) -> CommandResult {
        if let Some(fullscreen_id) = try!(self.in_fullscreen_workspace(uuid)) {
            if fullscreen_id != uuid {
                return Err(TreeError::Focus(FocusError::BlockedByFullscreen(uuid, fullscreen_id)))
            }
        }
        let container = try!(self.lookup(uuid));
        match *container {
            Container::View { handle, .. } => {
                handle.focus();
                Ok(())
            },
            _ => Err(TreeError::Focus(FocusError::NotAView(uuid)))
        }
    }
    /// Focus on the container relative to the active container.
    ///
    /// If Horizontal, left and right will move within siblings.
    /// If Vertical, up and down will move within siblings.
    /// Other wise, it moves to the next sibling of the parent container.
    ///
    /// If the edge of the children is hit, it does not wrap around,
    /// but moves between ancestor siblings.
    pub fn move_focus(&mut self, direction: Direction) -> CommandResult {
        if let Some(prev_active_ix) = self.active_container {
            let active_id = self.tree[prev_active_ix].get_id();
            if let Some(fullscreen_id) = try!(self.in_fullscreen_workspace(active_id)) {
                return Err(TreeError::Focus(
                    FocusError::BlockedByFullscreen(active_id, fullscreen_id)))
            }
            let new_active_ix = self.move_focus_recurse(prev_active_ix, direction)
                .unwrap_or(prev_active_ix);
            try!(self.set_active_node(new_active_ix));
            match self.tree[self.active_container.unwrap()] {
                Container::View { ref handle, .. } => handle.focus(),
                _ => warn!("move_focus returned a non-view, cannot focus")
            }
        } else {
            return Err(TreeError::NoActiveContainer)
        }
        self.validate();
        Ok(())
    }

    fn move_focus_recurse(&mut self, node_ix: NodeIndex, direction: Direction)
                          -> Result<NodeIndex, TreeError> {
        match self.tree[node_ix].get_type() {
            ContainerType::View | ContainerType::Container => { /* continue */ },
            _ => return Err(TreeError::UuidWrongType(self.tree[node_ix].get_id(),
                                                     vec!(ContainerType::View, ContainerType::Container)))
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Active ix had no parent");
        match self.tree[parent_ix] {
            Container::Container { layout, .. } => {
                match (layout, direction) {
                    (Layout::Horizontal, Direction::Left) |
                    (Layout::Horizontal, Direction::Right) |
                    (Layout::Vertical, Direction::Up) |
                    (Layout::Vertical, Direction::Down) => {
                        let siblings = self.tree.children_of(parent_ix);
                        let cur_index = siblings.iter().position(|node| {
                            *node == node_ix
                        }).expect("Could not find self in parent");
                        let maybe_new_index = match direction {
                            Direction::Right | Direction::Down => {
                                cur_index.checked_add(1)
                            }
                            Direction::Left  | Direction::Up => {
                                cur_index.checked_sub(1)
                            }
                        };
                        if maybe_new_index.is_some() &&
                            maybe_new_index.unwrap() < siblings.len() {
                                // There is a sibling to move to.
                                let new_index = maybe_new_index.unwrap();
                                let new_active_ix = siblings[new_index];
                                match self.tree[new_active_ix].get_type() {
                                    ContainerType::Container => {
                                        let path_ix = self.tree.follow_path(new_active_ix);
                                        // If the path wasn't complete, find the first view and focus on that
                                        let node_ix = try!(self.tree.descendant_of_type(path_ix, ContainerType::View)
                                                           .map_err(|err| TreeError::PetGraph(err)));
                                        let parent_ix = try!(self.tree.parent_of(node_ix)
                                                             .map_err(|err| TreeError::PetGraph(err)));
                                        match self.tree[node_ix].get_type() {
                                            ContainerType::View | ContainerType::Container => {},
                                            _ => panic!("Following path did not lead to a container or a view!")
                                        }
                                        trace!("Moving to different view {:?} in container {:?}",
                                                self.tree[node_ix], self.tree[parent_ix]);
                                        return Ok(node_ix);
                                    },
                                    ContainerType::View => {
                                        trace!("Moving to other view {:?}", self.tree[new_active_ix]);
                                        return Ok(new_active_ix)
                                    },
                                    _ => unreachable!()
                                };
                            }
                    },
                    _ => { /* We are moving out of siblings, recurse */ }
                }
            }
            Container::Workspace { .. } => {
                return Err(TreeError::Focus(FocusError::ReachedLimit(parent_ix)));
            }
            _ => unreachable!()
        }
        let parent_ix = self.tree.parent_of(node_ix)
            .expect("Node had no parent");
        return self.move_focus_recurse(parent_ix, direction);
    }

    /// Updates the current active container to be the next container or view
    /// to focus on after the previous view/container was moved/removed.
    ///
    /// A new view will tried to be set, starting with the children of the
    /// parent node. If a view cannot be found there, it starts climbing the
    /// tree until either a view is found or the workspace is (in which case
    /// it set the active container to the root container of the workspace)
    ///
    /// If there are siblings, the chosen node is the one with the lowest
    /// active count.
    ///
    /// If there is a fullscreen container in this workspace, that is focused on next,
    /// with the active path updated accordingly.
    pub fn focus_on_next_container(&mut self, mut parent_ix: NodeIndex) {
        let last_ix = self.tree.active_path().last()
            .expect("Active path did not lead anywhere").0;
        let id = self.tree[last_ix].get_id();
        match self.in_fullscreen_workspace(id) {
            Ok(Some(fullscreen_id)) => {
                self.set_active_container(fullscreen_id)
                    .unwrap_or_else(|err| {
                        error!("Could not set {:?} to be the active container, \
                                even though it's the fullscreen container! {:?}",
                               fullscreen_id, err);
                        error!("{:#?}", self);
                        panic!("Could not set the fullscreen container to be \
                                the active container!")
                    });
                return;
            },
            _ => {}
        }
        match self.tree[last_ix] {
            Container::View { handle, .. } => {
                handle.focus();
                self.active_container = Some(last_ix);
                return
            },
            Container::Container { .. } => {
                parent_ix = last_ix;
            },
            _ => {}
        }
        // TODO Change this algorithm when we improve the pathing system
        while self.tree.node_type(parent_ix)
            .expect("Node not part of the tree") != ContainerType::Workspace {
                if let Ok(view_ix) = self.tree.descendant_of_type(parent_ix,
                                                                  ContainerType::View) {
                    match self.tree[view_ix]
                                        .get_handle().expect("view had no handle") {
                        Handle::View(view) => view.focus(),
                        _ => panic!("View had an output handle")
                    }
                    trace!("Active container set to view at {:?}", view_ix);
                    let id = self.tree[view_ix].get_id();
                    self.set_active_container(id)
                        .expect("Could not set active container");
                    return;
                }
                parent_ix = self.tree.ancestor_of_type(parent_ix,
                                                       ContainerType::Container)
                    .unwrap_or_else(|_| {
                        self.tree.ancestor_of_type(parent_ix, ContainerType::Workspace)
                            .expect("Container was not part of a workspace")
                    });
        }
        // If this is reached, parent is workspace
        let container_ix = self.tree.children_of(parent_ix).get(0).cloned();
        if container_ix.is_none() {
            trace!("There were no other containers to focus on, \
                    focusing on nothing in particular!");
            return;
        }
        let container_ix = container_ix.unwrap();
        let root_c_children = self.tree.grounded_children(container_ix);
        if root_c_children.len() > 0 {
            // Only searches first child of root container, can't be floating view.
            let new_active_ix = self.tree.descendant_of_type(root_c_children[0],
                                                                ContainerType::View)
                .unwrap_or(root_c_children[0]);
            let id = self.tree[new_active_ix].get_id();
            self.set_active_container(id)
                .expect("Could not set active container");
            match self.tree[new_active_ix] {
                Container::View { ref handle, .. } => {
                    debug!("Focusing on {:?}", handle);
                    handle.focus();
                },
                Container::Container { .. } => {
                    debug!("No view found, focusing on nothing in workspace {:?}", parent_ix);
                    WlcView::root().focus();
                }
                _ => unreachable!()
            };
            return;
        } else {
            let floating_children = self.tree.floating_children(container_ix);
            for child_ix in floating_children {
                if let Ok(view_ix) = self.tree.descendant_of_type(child_ix,
                                                                    ContainerType::View) {
                    match self.tree[view_ix] {
                        Container::View { handle, id, .. } => {
                            debug!("Floating view found, focusing on {:#?}", handle);
                            handle.focus();
                            self.set_active_container(id)
                                .expect("Could not set active container");
                            return;
                        },
                        _ => unreachable!()
                    };
                }
            }
        }
        trace!("Active container set to container {:?}", container_ix);
        let id = self.tree[container_ix].get_id();
        self.set_active_container(id)
            .expect("Could not set active container");

        // Update focus to new container
        self.get_active_container().map(|con| match *con {
            Container::View { ref handle, .. } => handle.focus(),
            Container::Container { .. } => WlcView::root().focus(),
            _ => panic!("Active container not view or container!")
        });
    }

    /// If the currently focused view is floating, then the non-floating at the end of
    /// the path becomes the focused view. Otherwise, the first floating view becomes
    /// the focused view.
    ///
    /// If there is no currently focused view, does nothing.
    pub fn toggle_floating_focus(&mut self) -> CommandResult {
        let active_ix = try!(self.active_container.ok_or(TreeError::NoActiveContainer));
        let id; let floating;
        {
            let container = &self.tree[active_ix];
            id = container.get_id();
            floating = container.floating();
        }
        if let Some(fullscreen_id) = try!(self.in_fullscreen_workspace(id)) {
            return Err(TreeError::Focus(FocusError::BlockedByFullscreen(id, fullscreen_id)))
        }
        if floating {
            let root_ix = self.tree.root_ix();
            let new_ix = self.tree.follow_path(root_ix);
            match self.tree[new_ix].get_type() {
                ContainerType::View | ContainerType::Container  => {
                    try!(self.set_active_node(new_ix));
                    Ok(())
                },
                type_ => {
                    error!("Path lead to the wrong container, {:#?}\n{:#?}\n{:#?}",
                           active_ix, type_, self);
                    panic!("toggle_floating_focused: bad path");
                }
            }
        } else {
            // Current view is not floating, gotta focus on floating view
            let root_c_ix = self.root_container_ix()
                .expect("No root container ancestor of active container");
            let floating_children = self.tree.floating_children(root_c_ix);
            if floating_children.len() > 0 {
                try!(self.set_active_node(floating_children[0]));
            }
            Ok(())
        }
    }
}
<|endoftext|>


<commit_before>//! This crate defines voxel data types and interfaces for interacting with voxels.

#![deny(missing_docs)]
#![deny(warnings)]

#![feature(main)]
#![feature(test)]
#![feature(unboxed_closures)]

extern crate cgmath;
extern crate collision;
#[macro_use]
extern crate log;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate test;

pub mod bounds;
pub mod brush;
pub mod field;
pub mod mosaic;
pub mod tree;

pub mod impls;

/// The interface provided by Voxels.
pub trait T<Material> {
  /// Apply a brush to this voxel.
  fn brush<Mosaic>(
    this: &mut Self,
    bounds: &bounds::T,
    brush: &mut brush::T<Mosaic>,
  ) where Mosaic: mosaic::T<Material>;
}
<commit_msg>Remove nightlyness<commit_after>//! This crate defines voxel data types and interfaces for interacting with voxels.

#![deny(missing_docs)]
#![deny(warnings)]

extern crate cgmath;
extern crate collision;
#[macro_use]
extern crate log;
extern crate serde;
#[macro_use]
extern crate serde_derive;

pub mod bounds;
pub mod brush;
pub mod field;
pub mod mosaic;
pub mod tree;

pub mod impls;

/// The interface provided by Voxels.
pub trait T<Material> {
  /// Apply a brush to this voxel.
  fn brush<Mosaic>(
    this: &mut Self,
    bounds: &bounds::T,
    brush: &mut brush::T<Mosaic>,
  ) where Mosaic: mosaic::T<Material>;
}
<|endoftext|>