<commit_before>use std::boxed::Box;
use std::cmp;
use std::collections::BTreeSet;
use std::ops::Range;

pub struct ItemList {
    clipping_range_max_len: usize,
    clipping_range_start: usize,
    highlighted_row: Option<usize>,
    line_indices: Box<Indices>,
    marked_line_indices: BTreeSet<usize>,
}

impl ItemList {
    pub fn new(clipping_range_max_len: usize) -> Self {
        assert!(clipping_range_max_len > 0);
        ItemList {
            clipping_range_max_len: clipping_range_max_len,
            clipping_range_start: 0,
            highlighted_row: None,
            line_indices: Box::new(0..0),
            marked_line_indices: BTreeSet::new(),
        }
    }

    pub fn highlighted_row(&self) -> Option<usize> {
        self.highlighted_row
    }

    pub fn len(&self) -> usize {
        self.line_indices.len()
    }

    pub fn line_indices_in_clipping_range(&self) -> Vec<usize> {
        self.line_indices.boxed_iter()
            .skip(self.clipping_range_start)
            .take(self.clipping_range_end())
            .collect()
    }

    pub fn selected_line_indices(&self) -> Vec<usize> {
        match self.marked_line_indices.len() {
            0 => {
                match self.highlighted_row {
                    None => Vec::new(),
                    Some(row) => {
                        let i = self.clipping_range_start + row;
                        vec![self.line_indices.at(i)]
                    }
                }
            }
            _ => self.marked_line_indices.iter().cloned().collect(),
        }
    }

    pub fn marked_rows(&self) -> Vec<usize> {
        self.line_indices_in_clipping_range().iter()
            .enumerate()
            .filter_map(|(i, idx)| {
                if self.marked_line_indices.contains(idx) { Some(i) } else { None }
            })
            .collect()
    }

    pub fn toggle_mark(&mut self) {
        if let Some(row) = self.highlighted_row {
            let i = self.clipping_range_start + row;
            let line_index = self.line_indices.at(i);
            if !self.marked_line_indices.remove(&line_index) {
                self.marked_line_indices.insert(line_index);
            }
        }
    }

    pub fn set_line_indices(&mut self, line_indices: Vec<usize>) {
        self.set_line_indices_with_box::<Vec<usize>>(Box::new(line_indices));
    }

    pub fn set_line_index_range(&mut self, range: Range<usize>) {
        self.set_line_indices_with_box::<Range<usize>>(Box::new(range));
    }

    pub fn move_highlight_backward(&mut self) {
        if let Some(row) = self.highlighted_row {
            if row == 0 {
                self.scroll_backward();
                return;
            }
            self.highlighted_row = Some(row - 1);
        }
    }

    pub fn move_highlight_forward(&mut self) {
        if let Some(row) = self.highlighted_row {
            if Some(row) == self.max_row() {
                self.scroll_forward();
                return;
            }
            self.highlighted_row = Some(row + 1);
        }
    }

    pub fn scroll_backward(&mut self) {
        if self.clipping_range_start > 0 {
            self.clipping_range_start -= 1;
        }
    }

    pub fn scroll_forward(&mut self) {
        if self.clipping_range_end() < self.len() {
            self.clipping_range_start += 1;
        }
    }

    fn set_line_indices_with_box<T: Indices>(&mut self, line_indices: Box<Indices>) {
        self.line_indices = line_indices;
        let overrun = self.clipping_range_end().saturating_sub(self.len());
        self.clipping_range_start = self.clipping_range_start.saturating_sub(overrun);
        match (self.highlighted_row, self.max_row()) {
            (Some(row), Some(max_row)) if row > max_row => {
                self.highlighted_row = Some(max_row);
            }
            (None, Some(_)) => {
                self.highlighted_row = Some(0);
            }
            (_, None) => {
                self.highlighted_row = None;
            }
            (_, _) => { }
        }
        debug_assert!(
            (self.highlighted_row.is_some() && self.max_row().is_some()) ||
            (self.highlighted_row.is_none() && self.max_row().is_none()));
    }

    fn clipping_range_end(&self) -> usize {
        self.clipping_range_start + self.clipping_range_len()
    }

    fn clipping_range_len(&self) -> usize {
        cmp::min(self.len(), self.clipping_range_max_len)
    }

    fn max_row(&self) -> Option<usize> {
        match self.clipping_range_len() {
            0 => None,
            i => Some(i - 1),
        }
    }
}

pub trait Indices {
    fn at(&self, i: usize) -> usize;
    fn boxed_iter<'a>(&'a self) -> Box<Iterator<Item=usize> + 'a>;
    fn len(&self) -> usize;
}

impl Indices for Range<usize> {
    fn at(&self, i: usize) -> usize {
        assert!(i < self.end);
        i
    }

    fn boxed_iter<'a>(&'a self) -> Box<Iterator<Item=usize> + 'a> {
        Box::new(self.clone())
    }

    fn len(&self) -> usize {
        <Self as ExactSizeIterator>::len(&self)
    }
}

impl Indices for Vec<usize> {
    fn at(&self, i: usize) -> usize {
        unsafe { *self.get_unchecked(i) }
    }

    fn boxed_iter<'a>(&'a self) -> Box<Iterator<Item=usize> + 'a> {
        Box::new(self.iter().map(|i| *i))
    }

    fn len(&self) -> usize {
        Vec::len(&self)
    }
}
<commit_msg>Use cloned() instead of map()<commit_after>use std::boxed::Box;
use std::cmp;
use std::collections::BTreeSet;
use std::ops::Range;

pub struct ItemList {
    clipping_range_max_len: usize,
    clipping_range_start: usize,
    highlighted_row: Option<usize>,
    line_indices: Box<Indices>,
    marked_line_indices: BTreeSet<usize>,
}

impl ItemList {
    pub fn new(clipping_range_max_len: usize) -> Self {
        assert!(clipping_range_max_len > 0);
        ItemList {
            clipping_range_max_len: clipping_range_max_len,
            clipping_range_start: 0,
            highlighted_row: None,
            line_indices: Box::new(0..0),
            marked_line_indices: BTreeSet::new(),
        }
    }

    pub fn highlighted_row(&self) -> Option<usize> {
        self.highlighted_row
    }

    pub fn len(&self) -> usize {
        self.line_indices.len()
    }

    pub fn line_indices_in_clipping_range(&self) -> Vec<usize> {
        self.line_indices.boxed_iter()
            .skip(self.clipping_range_start)
            .take(self.clipping_range_end())
            .collect()
    }

    pub fn selected_line_indices(&self) -> Vec<usize> {
        match self.marked_line_indices.len() {
            0 => {
                match self.highlighted_row {
                    None => Vec::new(),
                    Some(row) => {
                        let i = self.clipping_range_start + row;
                        vec![self.line_indices.at(i)]
                    }
                }
            }
            _ => self.marked_line_indices.iter().cloned().collect(),
        }
    }

    pub fn marked_rows(&self) -> Vec<usize> {
        self.line_indices_in_clipping_range().iter()
            .enumerate()
            .filter_map(|(i, idx)| {
                if self.marked_line_indices.contains(idx) { Some(i) } else { None }
            })
            .collect()
    }

    pub fn toggle_mark(&mut self) {
        if let Some(row) = self.highlighted_row {
            let i = self.clipping_range_start + row;
            let line_index = self.line_indices.at(i);
            if !self.marked_line_indices.remove(&line_index) {
                self.marked_line_indices.insert(line_index);
            }
        }
    }

    pub fn set_line_indices(&mut self, line_indices: Vec<usize>) {
        self.set_line_indices_with_box::<Vec<usize>>(Box::new(line_indices));
    }

    pub fn set_line_index_range(&mut self, range: Range<usize>) {
        self.set_line_indices_with_box::<Range<usize>>(Box::new(range));
    }

    pub fn move_highlight_backward(&mut self) {
        if let Some(row) = self.highlighted_row {
            if row == 0 {
                self.scroll_backward();
                return;
            }
            self.highlighted_row = Some(row - 1);
        }
    }

    pub fn move_highlight_forward(&mut self) {
        if let Some(row) = self.highlighted_row {
            if Some(row) == self.max_row() {
                self.scroll_forward();
                return;
            }
            self.highlighted_row = Some(row + 1);
        }
    }

    pub fn scroll_backward(&mut self) {
        if self.clipping_range_start > 0 {
            self.clipping_range_start -= 1;
        }
    }

    pub fn scroll_forward(&mut self) {
        if self.clipping_range_end() < self.len() {
            self.clipping_range_start += 1;
        }
    }

    fn set_line_indices_with_box<T: Indices>(&mut self, line_indices: Box<Indices>) {
        self.line_indices = line_indices;
        let overrun = self.clipping_range_end().saturating_sub(self.len());
        self.clipping_range_start = self.clipping_range_start.saturating_sub(overrun);
        match (self.highlighted_row, self.max_row()) {
            (Some(row), Some(max_row)) if row > max_row => {
                self.highlighted_row = Some(max_row);
            }
            (None, Some(_)) => {
                self.highlighted_row = Some(0);
            }
            (_, None) => {
                self.highlighted_row = None;
            }
            (_, _) => { }
        }
        debug_assert!(
            (self.highlighted_row.is_some() && self.max_row().is_some()) ||
            (self.highlighted_row.is_none() && self.max_row().is_none()));
    }

    fn clipping_range_end(&self) -> usize {
        self.clipping_range_start + self.clipping_range_len()
    }

    fn clipping_range_len(&self) -> usize {
        cmp::min(self.len(), self.clipping_range_max_len)
    }

    fn max_row(&self) -> Option<usize> {
        match self.clipping_range_len() {
            0 => None,
            i => Some(i - 1),
        }
    }
}

pub trait Indices {
    fn at(&self, i: usize) -> usize;
    fn boxed_iter<'a>(&'a self) -> Box<Iterator<Item=usize> + 'a>;
    fn len(&self) -> usize;
}

impl Indices for Range<usize> {
    fn at(&self, i: usize) -> usize {
        assert!(i < self.end);
        i
    }

    fn boxed_iter<'a>(&'a self) -> Box<Iterator<Item=usize> + 'a> {
        Box::new(self.clone())
    }

    fn len(&self) -> usize {
        <Self as ExactSizeIterator>::len(&self)
    }
}

impl Indices for Vec<usize> {
    fn at(&self, i: usize) -> usize {
        unsafe { *self.get_unchecked(i) }
    }

    fn boxed_iter<'a>(&'a self) -> Box<Iterator<Item=usize> + 'a> {
        Box::new(self.iter().cloned())
    }

    fn len(&self) -> usize {
        Vec::len(&self)
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::io::stdout;

use lister::Lister;
use error::Result;
use error::ResultExt;

use libimagstore::store::FileLockEntry;

use prettytable::Table;
use prettytable::cell::Cell;
use prettytable::row::Row;

pub struct TableLister<F: Fn(&FileLockEntry) -> Vec<String>> {
    line_generator: F,
    header: Option<Vec<String>>,

    with_idx: bool,
}

impl<F: Fn(&FileLockEntry) -> Vec<String>> TableLister<F> {

    pub fn new(gen: F) -> TableLister<F> {
        TableLister {
            line_generator: gen,
            header: None,
            with_idx: true,
        }
    }

    pub fn with_header(mut self, hdr: Vec<String>) -> TableLister<F> {
        self.header = Some(hdr);
        self
    }

    pub fn with_idx(mut self, b: bool) -> TableLister<F> {
        self.with_idx = b;
        self
    }

}

impl<F: Fn(&FileLockEntry) -> Vec<String>> Lister for TableLister<F> {

    fn list<'b, I: Iterator<Item = FileLockEntry<'b>>>(&self, entries: I) -> Result<()> {
        use error::ListErrorKind as LEK;
        use error::ListError as LE;

        let mut table = Table::new();
        let mut header_len : Option<usize> = None;
        match self.header {
            Some(ref s) => {
                debug!("We have a header... preparing");
                let mut cells : Vec<Cell> = s.iter().map(|s| Cell::new(s)).collect();
                if self.with_idx {
                    cells.insert(0, Cell::new("#"));
                }
                table.set_titles(Row::new(cells));
                header_len = Some(s.len());
            },
            None => {
                debug!("No header for table found... continuing without");
            },
        }

        entries.enumerate().fold(Ok(table), |table, (i, entry)| {
            table.and_then(|mut table| {
                let mut v = (self.line_generator)(&entry);
                {
                    let v_len = v.len();
                    if header_len.is_none() {
                        header_len = Some(v_len);
                    }
                    if header_len.map(|l| v_len > l).unwrap_or(false) {
                        return Err(LE::from_kind(LEK::FormatError));
                    }
                    while header_len.map(|l| v.len() != l).unwrap_or(false) {
                        v.push(String::from(""));
                    }
                }

                if self.with_idx {
                    v.insert(0, format!("{}", i));
                }

                table.add_row(v.iter().map(|s| Cell::new(s)).collect());
                Ok(table)
            })
        })
        .and_then(|tbl| {
            let mut io = stdout();
            tbl.print(&mut io).chain_err(|| LEK::IOError)
        })
    }

}
<commit_msg>Add flag and check whether to print empty table<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::io::stdout;

use lister::Lister;
use error::Result;
use error::ResultExt;

use libimagstore::store::FileLockEntry;

use prettytable::Table;
use prettytable::cell::Cell;
use prettytable::row::Row;

pub struct TableLister<F: Fn(&FileLockEntry) -> Vec<String>> {
    line_generator: F,
    header: Option<Vec<String>>,

    with_idx: bool,
    print_empty: bool,
}

impl<F: Fn(&FileLockEntry) -> Vec<String>> TableLister<F> {

    pub fn new(gen: F) -> TableLister<F> {
        TableLister {
            line_generator: gen,
            header: None,
            with_idx: true,
            print_empty: false,
        }
    }

    pub fn with_header(mut self, hdr: Vec<String>) -> TableLister<F> {
        self.header = Some(hdr);
        self
    }

    pub fn with_idx(mut self, b: bool) -> TableLister<F> {
        self.with_idx = b;
        self
    }

    pub fn print_empty(mut self, b: bool) -> TableLister<F> {
        self.print_empty = b;
        self
    }

}

impl<F: Fn(&FileLockEntry) -> Vec<String>> Lister for TableLister<F> {

    fn list<'b, I: Iterator<Item = FileLockEntry<'b>>>(&self, entries: I) -> Result<()> {
        use error::ListErrorKind as LEK;
        use error::ListError as LE;

        let mut table = Table::new();
        let mut header_len : Option<usize> = None;
        match self.header {
            Some(ref s) => {
                debug!("We have a header... preparing");
                let mut cells : Vec<Cell> = s.iter().map(|s| Cell::new(s)).collect();
                if self.with_idx {
                    cells.insert(0, Cell::new("#"));
                }
                table.set_titles(Row::new(cells));
                header_len = Some(s.len());
            },
            None => {
                debug!("No header for table found... continuing without");
            },
        }

        let mut entries_added = 0;

        entries.enumerate().fold(Ok(table), |table, (i, entry)| {
            table.and_then(|mut table| {
                let mut v = (self.line_generator)(&entry);
                {
                    let v_len = v.len();
                    if header_len.is_none() {
                        header_len = Some(v_len);
                    }
                    if header_len.map(|l| v_len > l).unwrap_or(false) {
                        return Err(LE::from_kind(LEK::FormatError));
                    }
                    while header_len.map(|l| v.len() != l).unwrap_or(false) {
                        v.push(String::from(""));
                    }
                }

                if self.with_idx {
                    v.insert(0, format!("{}", i));
                }

                table.add_row(v.iter().map(|s| Cell::new(s)).collect());
                entries_added += 1;
                Ok(table)
            })
        })
        .and_then(|tbl| {
            if entries_added != 0 && !self.print_empty {
                let mut io = stdout();
                tbl.print(&mut io).chain_err(|| LEK::IOError)
            } else {
                Ok(())
            }
        })
    }

}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::{mem};

// Bounded package merge algorithm, based on the paper
// "A Fast and Space-Economical Algorithm for Length-Limited Coding
// Jyrki Katajainen, Alistair Moffat, Andrew Turpin".

#[derive(Debug, Clone)]
struct Node {
    weight: usize,
    leaf_counts: Vec<usize>,
}

impl Node {
    fn new(weight: usize, initial_count: usize, capacity: usize) -> Node {
        let mut n = Node {
            weight: weight,
            leaf_counts: Vec::with_capacity(capacity),
        };
        n.leaf_counts.push(initial_count);
        n
    }
}

#[derive(Debug)]
struct Leaf {
    weight: usize,
    count: usize,
}
impl PartialEq for Leaf {
    fn eq(&self, other: &Self) -> bool {
        self.weight == other.weight
    }
}
impl Eq for Leaf { }
impl Ord for Leaf {
    fn cmp(&self, other: &Self) -> Ordering {
        self.weight.cmp(&other.weight)
    }
}
impl PartialOrd for Leaf {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(Debug, Clone)]
struct List {
    lookahead1: Node,
    lookahead2: Node,
    next_leaf_index: usize,
}

/// Calculates the bitlengths for the Huffman tree, based on the counts of each
/// symbol.
pub fn length_limited_code_lengths(frequencies: &[usize], max_bits: usize) -> Vec<u32> {
    let num_freqs = frequencies.len();
    let mut result = vec![0; num_freqs];

    // Count used symbols and place them in the leaves.
    let mut leaves: Vec<_> = frequencies.iter()
        .enumerate()
        .filter(|&(_, &freq)| freq != 0)
        .map(|(i, &freq)| Leaf { weight: freq, count: i })
        .collect();

    let num_symbols = leaves.len();

    // Short circuit some special cases

    // TODO:
    // if ((1 << maxbits) < numsymbols) {
    //   free(leaves);
    //   return 1;  /* Error, too few maxbits to represent symbols. */
    // }

    if num_symbols == 0 {
        // There are no non-zero frequencies.
        return result;
    }
    if num_symbols == 1 {
        result[leaves[0].count] = 1;
        return result;
    }
    if num_symbols == 2 {
        result[leaves[0].count] = 1;
        result[leaves[1].count] = 1;
        return result;
    }

    // Sort the leaves from least frequent to most frequent.
    leaves.sort();

    let max_num_leaves = 2 * num_symbols - 2;
    let mut lists = vec![
        List {
            lookahead1: Node::new(leaves[0].weight, 1, max_num_leaves),
            lookahead2: Node::new(leaves[1].weight, 2, max_num_leaves),
            next_leaf_index: 2,
        };
        max_bits
    ];

    // In the last list, 2 * numsymbols - 2 active chains need to be created. Two
    // are already created in the initialization. Each boundary_pm run creates one.
    let num_boundary_pm_runs = max_num_leaves - 2;
    for _ in 0..num_boundary_pm_runs {
        boundary_pm_toplevel(&mut lists[..], &leaves);
    }

    let mut a = lists.pop().unwrap().lookahead2.leaf_counts.into_iter().rev().peekable();

    let mut bitlength_value = 1;
    while let Some(leaf_count) = a.next() {
        let next_count = *a.peek().unwrap_or(&0);
        for leaf in &leaves[next_count..leaf_count] {
            result[leaf.count] = bitlength_value;
        }
        bitlength_value += 1;
    }

    result
}

fn lowest_list(lists: &mut [List], leaves: &[Leaf]) {
    // We're in the lowest list, just add another leaf to the lookaheads
    // There will always be more leaves to be added on level 0 so this is safe.
    let mut current_list = &mut lists[0];
    let next_leaf = &leaves[current_list.next_leaf_index];
    current_list.lookahead2.weight = next_leaf.weight;

    current_list.lookahead2.leaf_counts[0] = current_list.lookahead1.leaf_counts.last().unwrap() + 1;
    current_list.next_leaf_index += 1;
}

fn next_leaf(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let mut current_list = &mut lists[current_list_index];

    // The next leaf goes next; counting itself makes the leaf_count increase by one.
    current_list.lookahead2.weight = leaves[current_list.next_leaf_index].weight;
    current_list.lookahead2.leaf_counts.clear();
    current_list.lookahead2.leaf_counts.extend_from_slice(&current_list.lookahead1.leaf_counts);
    let last_index = current_list.lookahead2.leaf_counts.len() - 1;
    current_list.lookahead2.leaf_counts[last_index] += 1;
    current_list.next_leaf_index += 1;
}

fn next_tree(weight_sum: usize, lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    {
        let (head, tail) = lists.split_at_mut(current_list_index);
        let prev_list = head.last_mut().unwrap();
        let current_list = tail.first_mut().unwrap();

        let previous_list_leaf_counts = &prev_list.lookahead2.leaf_counts;

        // Make a tree from the lookaheads from the previous list; that goes next.
        // This is not a leaf node, so the leaf count stays the same.
        current_list.lookahead2.weight = weight_sum;
        current_list.lookahead2.leaf_counts.clear();

        current_list.lookahead2.leaf_counts.extend_from_slice(previous_list_leaf_counts);
        current_list.lookahead2.leaf_counts.push(*current_list.lookahead1.leaf_counts.last().unwrap());
    }

    // The previous list needs two new lookahead nodes.
    boundary_pm(lists, leaves, current_list_index - 1);
    boundary_pm(lists, leaves, current_list_index - 1);
}

fn boundary_pm_toplevel(lists: &mut [List], leaves: &[Leaf]) {
    let last_index = lists.len() - 1;
    boundary_pm(lists, leaves, last_index);
}

fn boundary_pm(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let next_leaf_index = lists[current_list_index].next_leaf_index;
    let num_symbols = leaves.len();

    if current_list_index == 0 && next_leaf_index == num_symbols {
        // We've added all the leaves to the lowest list, so we're done here
        return;
    }

    mem::swap(&mut lists[current_list_index].lookahead1, &mut lists[current_list_index].lookahead2);

    if current_list_index == 0 {
        lowest_list(lists, leaves);
    } else {
        // We're at a list other than the lowest list.
        let weight_sum = {
            let previous_list = &lists[current_list_index - 1];
            previous_list.lookahead1.weight + previous_list.lookahead2.weight
        };

        if next_leaf_index < num_symbols && weight_sum > leaves[next_leaf_index].weight {
            next_leaf(lists, leaves, current_list_index);
        } else {
            next_tree(weight_sum, lists, leaves, current_list_index);
        }
    }
}

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

    #[test]
    fn test_from_paper_3() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 3);
        let answer = vec![3, 3, 3, 3, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn test_from_paper_4() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 4);
        let answer = vec![4, 4, 3, 2, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn max_bits_7() {
        let input = [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn max_bits_15() {
        let input = [0, 0, 0, 0, 0, 0, 18, 0, 6, 0, 12, 2, 14, 9, 27, 15, 23, 15, 17, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 15);
        let answer = vec! [0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 4, 6, 4, 4, 3, 4, 3, 3, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn no_frequencies() {
        let input = [0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_one_frequency() {
        let input = [0, 10, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 1, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_two_frequencies() {
        let input = [0, 0, 0, 0, 252, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }
}
<commit_msg>Rename result to bit_lengths to be more like the C code<commit_after>use std::cmp::Ordering;
use std::{mem};

// Bounded package merge algorithm, based on the paper
// "A Fast and Space-Economical Algorithm for Length-Limited Coding
// Jyrki Katajainen, Alistair Moffat, Andrew Turpin".

#[derive(Debug, Clone)]
struct Node {
    weight: usize,
    leaf_counts: Vec<usize>,
}

impl Node {
    fn new(weight: usize, initial_count: usize, capacity: usize) -> Node {
        let mut n = Node {
            weight: weight,
            leaf_counts: Vec::with_capacity(capacity),
        };
        n.leaf_counts.push(initial_count);
        n
    }
}

#[derive(Debug)]
struct Leaf {
    weight: usize,
    count: usize,
}
impl PartialEq for Leaf {
    fn eq(&self, other: &Self) -> bool {
        self.weight == other.weight
    }
}
impl Eq for Leaf { }
impl Ord for Leaf {
    fn cmp(&self, other: &Self) -> Ordering {
        self.weight.cmp(&other.weight)
    }
}
impl PartialOrd for Leaf {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(Debug, Clone)]
struct List {
    lookahead1: Node,
    lookahead2: Node,
    next_leaf_index: usize,
}

/// Calculates the bitlengths for the Huffman tree, based on the counts of each
/// symbol.
pub fn length_limited_code_lengths(frequencies: &[usize], max_bits: usize) -> Vec<u32> {
    let num_freqs = frequencies.len();
    let mut bit_lengths = vec![0; num_freqs];

    // Count used symbols and place them in the leaves.
    let mut leaves: Vec<_> = frequencies.iter()
        .enumerate()
        .filter(|&(_, &freq)| freq != 0)
        .map(|(i, &freq)| Leaf { weight: freq, count: i })
        .collect();

    let num_symbols = leaves.len();

    // Short circuit some special cases

    // TODO:
    // if ((1 << maxbits) < numsymbols) {
    //   free(leaves);
    //   return 1;  /* Error, too few maxbits to represent symbols. */
    // }

    if num_symbols == 0 {
        // There are no non-zero frequencies.
        return bit_lengths;
    }
    if num_symbols == 1 {
        bit_lengths[leaves[0].count] = 1;
        return bit_lengths;
    }
    if num_symbols == 2 {
        bit_lengths[leaves[0].count] = 1;
        bit_lengths[leaves[1].count] = 1;
        return bit_lengths;
    }

    // Sort the leaves from least frequent to most frequent.
    leaves.sort();

    let max_num_leaves = 2 * num_symbols - 2;
    let mut lists = vec![
        List {
            lookahead1: Node::new(leaves[0].weight, 1, max_num_leaves),
            lookahead2: Node::new(leaves[1].weight, 2, max_num_leaves),
            next_leaf_index: 2,
        };
        max_bits
    ];

    // In the last list, 2 * numsymbols - 2 active chains need to be created. Two
    // are already created in the initialization. Each boundary_pm run creates one.
    let num_boundary_pm_runs = max_num_leaves - 2;
    for _ in 0..num_boundary_pm_runs {
        boundary_pm_toplevel(&mut lists[..], &leaves);
    }

    let mut a = lists.pop().unwrap().lookahead2.leaf_counts.into_iter().rev().peekable();

    let mut bitlength_value = 1;
    while let Some(leaf_count) = a.next() {
        let next_count = *a.peek().unwrap_or(&0);
        for leaf in &leaves[next_count..leaf_count] {
            bit_lengths[leaf.count] = bitlength_value;
        }
        bitlength_value += 1;
    }

    bit_lengths
}

fn lowest_list(lists: &mut [List], leaves: &[Leaf]) {
    // We're in the lowest list, just add another leaf to the lookaheads
    // There will always be more leaves to be added on level 0 so this is safe.
    let mut current_list = &mut lists[0];
    let next_leaf = &leaves[current_list.next_leaf_index];
    current_list.lookahead2.weight = next_leaf.weight;

    current_list.lookahead2.leaf_counts[0] = current_list.lookahead1.leaf_counts.last().unwrap() + 1;
    current_list.next_leaf_index += 1;
}

fn next_leaf(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let mut current_list = &mut lists[current_list_index];

    // The next leaf goes next; counting itself makes the leaf_count increase by one.
    current_list.lookahead2.weight = leaves[current_list.next_leaf_index].weight;
    current_list.lookahead2.leaf_counts.clear();
    current_list.lookahead2.leaf_counts.extend_from_slice(&current_list.lookahead1.leaf_counts);
    let last_index = current_list.lookahead2.leaf_counts.len() - 1;
    current_list.lookahead2.leaf_counts[last_index] += 1;
    current_list.next_leaf_index += 1;
}

fn next_tree(weight_sum: usize, lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    {
        let (head, tail) = lists.split_at_mut(current_list_index);
        let prev_list = head.last_mut().unwrap();
        let current_list = tail.first_mut().unwrap();

        let previous_list_leaf_counts = &prev_list.lookahead2.leaf_counts;

        // Make a tree from the lookaheads from the previous list; that goes next.
        // This is not a leaf node, so the leaf count stays the same.
        current_list.lookahead2.weight = weight_sum;
        current_list.lookahead2.leaf_counts.clear();

        current_list.lookahead2.leaf_counts.extend_from_slice(previous_list_leaf_counts);
        current_list.lookahead2.leaf_counts.push(*current_list.lookahead1.leaf_counts.last().unwrap());
    }

    // The previous list needs two new lookahead nodes.
    boundary_pm(lists, leaves, current_list_index - 1);
    boundary_pm(lists, leaves, current_list_index - 1);
}

fn boundary_pm_toplevel(lists: &mut [List], leaves: &[Leaf]) {
    let last_index = lists.len() - 1;
    boundary_pm(lists, leaves, last_index);
}

fn boundary_pm(lists: &mut [List], leaves: &[Leaf], current_list_index: usize) {
    let next_leaf_index = lists[current_list_index].next_leaf_index;
    let num_symbols = leaves.len();

    if current_list_index == 0 && next_leaf_index == num_symbols {
        // We've added all the leaves to the lowest list, so we're done here
        return;
    }

    mem::swap(&mut lists[current_list_index].lookahead1, &mut lists[current_list_index].lookahead2);

    if current_list_index == 0 {
        lowest_list(lists, leaves);
    } else {
        // We're at a list other than the lowest list.
        let weight_sum = {
            let previous_list = &lists[current_list_index - 1];
            previous_list.lookahead1.weight + previous_list.lookahead2.weight
        };

        if next_leaf_index < num_symbols && weight_sum > leaves[next_leaf_index].weight {
            next_leaf(lists, leaves, current_list_index);
        } else {
            next_tree(weight_sum, lists, leaves, current_list_index);
        }
    }
}

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

    #[test]
    fn test_from_paper_3() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 3);
        let answer = vec![3, 3, 3, 3, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn test_from_paper_4() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 4);
        let answer = vec![4, 4, 3, 2, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn max_bits_7() {
        let input = [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn max_bits_15() {
        let input = [0, 0, 0, 0, 0, 0, 18, 0, 6, 0, 12, 2, 14, 9, 27, 15, 23, 15, 17, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 15);
        let answer = vec! [0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 4, 6, 4, 4, 3, 4, 3, 3, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn no_frequencies() {
        let input = [0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_one_frequency() {
        let input = [0, 10, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = vec![0, 1, 0];
        assert_eq!(output, answer);
    }

    #[test]
    fn only_two_frequencies() {
        let input = [0, 0, 0, 0, 252, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        let output = length_limited_code_lengths(&input, 7);
        let answer = [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        assert_eq!(output, answer);
    }
}
<|endoftext|>


<commit_before>
use lang;
use util;

/// A basic block is a list of instructions which
/// end with a single terminator instruction.
#[derive(Clone,Debug)]
pub struct Block<V>
{
    id: util::Id,

    name: String,
    body: Vec<V>,
}

impl<V> Block<V>
    where V: lang::Value
{
    /// Creates a new basic block.
    pub fn new<N>(name: N,
                  body: Vec<V>) -> Self
        where N: Into<String> {
        Block {
            id: util::Id::next(),
            name: name.into(),
            body: body,
        }
    }

    /// Creates a basic block with no contained instructions.
    pub fn empty<N>(name: N) -> Self
        where N: Into<String> {
        Block::new(name, Vec::new())
    }

    /// Appends a value to the basic block.
    pub fn append_value<T>(&mut self, value: T)
        where T: Into<V> {
        self.body.push(value.into());
    }

    /// Gets the name of the block.
    pub fn name(&self) -> &str { &self.name }

    /// Flattens the values in the block.
    pub fn flatten(self) -> Self {
        let mut block = Block {
            id: self.id.clone(),
            name: self.name.clone(),
            body: Vec::new(),
        };

        for value in self.body {
            let new_value = value.flatten(&mut block);
            block.append_value(new_value);
        }

        block
    }

    /// Gets the last instruction in the block.
    /// Panics if the block is empty, or the last value it is not a terminator.
    pub fn terminator(&self) -> &V {
        let last = self.body.last().expect("the basic block is empty");

        assert!(last.is_terminator(), "the basic block is not terminated");
        last
    }

    /// Gets the ID of the block.
    pub fn id(&self) -> util::Id { self.id }

    /// Gets the values that the block contains.
    pub fn values(&self) -> ::std::slice::Iter<V> {
        self.body.iter()
    }

    /// Gets the values that the block contains as mutable.
    pub fn values_mut(&mut self) -> ::std::slice::IterMut<V> {
        self.body.iter_mut()
    }

    /// Sets the values that the block contains.
    pub fn with_values<I>(mut self, values: I) -> Self
        where I: Iterator<Item=V> {

        self.body = values.collect();
        self
    }

    /// Performs a mapping on the values that the block contains.
    pub fn map_values<F>(mut self, f: F) -> Self
        where F: FnMut(V) -> V {
        self.body = self.body.into_iter().map(f).collect();
        self
    }

    /// Filters values out of the basic block.
    pub fn filter<F>(mut self, mut f: F) -> Self
        where F: FnMut(&V) -> bool {
        self.body = self.body.into_iter()
                             .filter(|a| f(a))
                             .collect();
        self
    }
}

<commit_msg>Added custom basic block iterator<commit_after>
use lang;
use util;

/// A basic block is a list of instructions which
/// end with a single terminator instruction.
#[derive(Clone,Debug)]
pub struct Block<V>
{
    id: util::Id,

    name: String,
    body: Vec<V>,
}

impl<V> Block<V>
    where V: lang::Value
{
    /// Creates a new basic block.
    pub fn new<N>(name: N,
                  body: Vec<V>) -> Self
        where N: Into<String> {
        Block {
            id: util::Id::next(),
            name: name.into(),
            body: body,
        }
    }

    /// Creates a basic block with no contained instructions.
    pub fn empty<N>(name: N) -> Self
        where N: Into<String> {
        Block::new(name, Vec::new())
    }

    /// Appends a value to the basic block.
    pub fn append_value<T>(&mut self, value: T)
        where T: Into<V> {
        self.body.push(value.into());
    }

    /// Gets the name of the block.
    pub fn name(&self) -> &str { &self.name }

    /// Flattens the values in the block.
    pub fn flatten(self) -> Self {
        let mut block = Block {
            id: self.id.clone(),
            name: self.name.clone(),
            body: Vec::new(),
        };

        for value in self.body {
            let new_value = value.flatten(&mut block);
            block.append_value(new_value);
        }

        block
    }

    /// Gets the last instruction in the block.
    /// Panics if the block is empty, or the last value it is not a terminator.
    pub fn terminator(&self) -> &V {
        let last = self.body.last().expect("the basic block is empty");

        assert!(last.is_terminator(), "the basic block is not terminated");
        last
    }

    /// Gets the ID of the block.
    pub fn id(&self) -> util::Id { self.id }

    /// Gets the values that the block contains.
    pub fn values(&self) -> ::std::slice::Iter<V> {
        self.body.iter()
    }

    /// Gets the values that the block contains as mutable.
    pub fn values_mut(&mut self) -> values::ValuesMut<V> {
        values::ValuesMut::new(self)
    }

    /// Sets the values that the block contains.
    pub fn with_values<I>(mut self, values: I) -> Self
        where I: Iterator<Item=V> {

        self.body = values.collect();
        self
    }

    /// Performs a mapping on the values that the block contains.
    pub fn map_values<F>(mut self, f: F) -> Self
        where F: FnMut(V) -> V {
        self.body = self.body.into_iter().map(f).collect();
        self
    }

    /// Filters values out of the basic block.
    pub fn filter<F>(mut self, mut f: F) -> Self
        where F: FnMut(&V) -> bool {
        self.body = self.body.into_iter()
                             .filter(|a| f(a))
                             .collect();
        self
    }
}

pub mod values
{
    use super::Block;
    use lang;

    pub struct ValuesMut<'a, V: lang::Value+'a>
    {
        block: &'a mut Block<V>,
        cur_idx: usize,
    }

    impl<'a,V> ValuesMut<'a,V>
        where V: lang::Value
    {
        pub fn new(block: &'a mut Block<V>) -> Self {
            ValuesMut {
                block: block,
                cur_idx: 0,
            }
        }

        pub fn insert_before(&mut self, value: V) {
            self.block.body.insert(self.cur_idx, value);
            self.cur_idx += 1;
        }

        pub fn insert_after(&mut self, value: V) {
            self.block.body.insert(self.cur_idx+1, value);
        }
    }

    impl<'a,V> Iterator for ValuesMut<'a,V>
        where V: lang::Value
    {
        type Item = &'a mut V;

        fn next(&mut self) -> Option<&'a mut V> {
            let next: Option<&mut V> = self.block.body.get_mut(self.cur_idx);

            if next.is_some() {
                self.cur_idx += 1;
            }
            // transmute the lifetime.
            unsafe {::std::mem::transmute(next) }
        }

        fn size_hint(&self) -> (usize,Option<usize>) {
            let len = self.block.body.len();
            (len, Some(len))
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::os::unix::io::FromRawFd;
use std::io::Read;
use std::io;
use std::io::{Error};
use std::mem;

use libc::{pid_t};

#[allow(dead_code, non_camel_case_types)]
mod hw_breakpoint;
#[allow(dead_code, non_camel_case_types)]
mod perf_event;

use ::AbstractPerfCounter;
use x86::perfcnt::intel::description::{IntelPerformanceCounterDescription, Tuple};

const IOCTL: usize = 16;
const PERF_EVENT_OPEN: usize = 298;

fn perf_event_open(hw_event: perf_event::perf_event_attr,
                       pid: perf_event::__kernel_pid_t,
                       cpu:  ::libc::c_int,
                       group_fd:  ::libc::c_int,
                       flags:  ::libc::c_int) -> isize {
    unsafe {
        syscall!(PERF_EVENT_OPEN, &hw_event as *const perf_event::perf_event_attr as usize, pid, cpu, group_fd, flags) as isize
    }
}

fn ioctl(fd: ::libc::c_int, request: u64, value: ::libc::c_int) -> isize {
    unsafe {
        syscall!(IOCTL, fd, request, value) as isize
    }
}

fn read_counter(fd: ::libc::c_int) -> Result<u64, io::Error> {
    unsafe {
        let mut f = File::from_raw_fd(fd);
        let mut value: [u8; 8] = Default::default();
        try!(f.read(&mut value));
        Ok(mem::transmute::<[u8; 8], u64>(value))
    }
}

pub struct PerfCounterBuilderLinux {
    group: isize,
    pid: pid_t,
    cpu: isize,
    flags: usize,
    attrs: perf_event::perf_event_attr,
}

impl Default for PerfCounterBuilderLinux {
    fn default () -> PerfCounterBuilderLinux {
        PerfCounterBuilderLinux {
            group: -1,
            pid: 0,
            cpu: -1,
            flags: 0,
            attrs: Default::default()
        }
    }
}

impl PerfCounterBuilderLinux {

    pub fn from_raw_intel_counter_description(counter: &IntelPerformanceCounterDescription) -> PerfCounterBuilderLinux {
        let mut pc: PerfCounterBuilderLinux = Default::default();
        let mut config: u64 = 0;

        match counter.event_code {
            Tuple::One(code) =>  config |= (code as u64) << 0,
            Tuple::Two(_, _) => unreachable!() // NYI
        };
        match counter.umask {
            Tuple::One(code) =>  config |= (code as u64) << 8,
            Tuple::Two(_, _) => unreachable!() // NYI
        };
        config |= (counter.counter_mask as u64) << 24;

        if counter.edge_detect {
            config |= 1 << 18;
        }
        if counter.any_thread {
            config |= 1 << 21;
        }
        if counter.invert {
            config |= 1 << 23;
        }

        pc.attrs._type = perf_event::PERF_TYPE_RAW;
        pc.attrs.config = config;
        pc
    }

    /// Set counter group.
    pub fn set_group<'a>(&'a mut self, group_fd: isize) -> &'a mut PerfCounterBuilderLinux {
        self.group = group_fd;
        self
    }

    /// Sets PERF_FLAG_FD_OUTPUT
    ///
    /// This flag re-routes the output from an event to the group leader.
    pub fn set_flag_fd_output<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.flags |= 0x0; //PERF_FLAG_FD_OUTPUT;
        self
    }

    /// Sets PERF_FLAG_PID_CGROUP
    ///
    /// This flag activates per-container system-wide monitoring.  A
    /// container is an abstraction that isolates a set of resources for
    /// finer grain control (CPUs, memory, etc.).   In  this  mode,  the
    /// event  is  measured  only if the thread running on the monitored
    /// CPU belongs to the designated container (cgroup).
    pub fn set_flag_pid_cgroup<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.flags |= 0x0; //PERF_FLAG_PID_CGROUP;
        self
    }

    /// Add a sample period.
    pub fn set_sample_period<'a>(&'a mut self, period: u64) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.sample_period_freq = period;
        self
    }

    /// Add a sample frequency.
    pub fn set_sample_frequency<'a>(&'a mut self, frequency: u64) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.sample_period_freq = frequency;
        self.attrs.settings.insert(perf_event::EVENT_ATTR_FREQ);
        self
    }

    /// The counter starts out disabled.
    pub fn disable<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_DISABLED);
        self
    }

    /// This counter should count events of child tasks as well as the task specified.
    pub fn inherit<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_INHERIT);
        self
    }

    /// The pinned bit specifies that the counter should always be on the CPU if at all possible.
    /// It applies only to  hardware counters and only to group leaders.
    pub fn pinned<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_PINNED);
        self
    }

    /// The counter is exclusive i.e., when this counter's group is on the CPU,
    /// it should be the only group using the CPU's counters.
    pub fn exclusive<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_EXCLUSIVE);
        self
    }

    /// The counter excludes events that happen in user space.
    pub fn exclude_user<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_EXCLUDE_USER);
        self
    }

    /// The counter excludes events that happen in the kernel.
    pub fn exclude_kernel<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_EXCLUDE_KERNEL);
        self
    }

    /// The counter excludes events that happen in the hypervisor.
    pub fn exclude_hv<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_EXCLUDE_HV);
        self
    }

    /// The counter doesn't count when the CPU is idle.
    pub fn exclude_idle<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_EXCLUDE_IDLE);
        self
    }

    /// Enables recording of exec mmap events.
    pub fn enable_mmap<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_MMAP);
        self
    }

    /// The counter will save event counts on context switch for inherited tasks.
    /// This is meaningful only if the inherit field is set.
    pub fn inherit_stat<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_INHERIT_STAT);
        self
    }

    /// The counter is automatically enabled after a call to exec.
    pub fn enable_on_exec<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_ENABLE_ON_EXEC);
        self
    }

    /// fork/exit notifications are included in the ring buffer.
    pub fn enable_task_notification<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_TASK);
        self
    }

    /// The counter has  a  sampling  interrupt happen when we cross the wakeup_watermark
    /// boundary.  Otherwise interrupts happen after wakeup_events samples.
    pub fn enable_watermark<'a>(&'a mut self, watermark_events: u32) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_WATERMARK);
        self.attrs.wakeup_events_watermark = watermark_events;
        self
    }

    /// Sampled IP counter can have arbitrary skid.
    pub fn set_ip_sample_arbitrary_skid<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_SAMPLE_IP_ARBITRARY_SKID);
        self
    }

    /// Sampled IP counter requested to have constant skid.
    pub fn set_ip_sample_constant_skid<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_SAMPLE_IP_CONSTANT_SKID);
        self
    }

    /// Sampled IP counter requested to have 0 skid.
    pub fn set_ip_sample_req_zero_skid<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_SAMPLE_IP_REQ_ZERO_SKID);
        self
    }

    /// The counterpart of enable_mmap, but enables including data mmap events in the ring-buffer.
    pub fn enable_mmap_data<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_MMAP_DATA);
        self
    }

    /// Sampled IP counter must have 0 skid.
    pub fn set_ip_sample_zero_skid<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_SAMPLE_IP_ZERO_SKID);
        self
    }

    /// Measure for all PIDs on the core.
    pub fn for_all_pids<'a>(&'a mut self) ->  &'a mut PerfCounterBuilderLinux {
        self.pid = -1;
        self
    }

    /// Measure for a specific PID.
    pub fn for_pid<'a>(&'a mut self, pid: i32) -> &'a mut PerfCounterBuilderLinux {
        self.pid = pid;
        self
    }

    /// Pin counter to CPU.
    pub fn on_cpu<'a>(&'a mut self, cpu: isize) -> &'a mut PerfCounterBuilderLinux {
        self.cpu = cpu;
        self
    }

    /// Measure on all CPUs.
    pub fn on_all_cpus<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.cpu = -1;
        self
    }

    /// Instantiate the performance counter.
    pub fn finish(&self) -> Result<PerfCounter, io::Error> {
        let flags = 0;
        let fd = perf_event_open(self.attrs, self.pid, self.cpu as i32, self.group as i32, flags) as ::libc::c_int;
        if fd < 0 {
            // TODO: Our syscall invocation probably does not set errno?
            return Err(Error::last_os_error());
        }

        Ok(PerfCounter { fd: fd })
    }
}

pub struct PerfCounter {
    fd: ::libc::c_int
}

impl AbstractPerfCounter for PerfCounter {

    fn reset(&self) -> Result<(), io::Error> {
        let ret = ioctl(self.fd, perf_event::PERF_EVENT_IOC_RESET, 0);
        if ret == -1 {
            return Err(Error::last_os_error());
        }
        Ok(())
    }

    fn start(&self) -> Result<(), io::Error> {
        let ret = ioctl(self.fd, perf_event::PERF_EVENT_IOC_ENABLE, 0);
        if ret == -1 {
            return Err(Error::last_os_error());
        }
        Ok(())
    }

    fn stop(&self) -> Result<(), io::Error> {
        let ret = ioctl(self.fd, perf_event::PERF_EVENT_IOC_DISABLE, 0);
        if ret == -1 {
            return Err(Error::last_os_error());
        }
        Ok(())
    }

    fn read(&self) -> Result<u64, io::Error> {
        read_counter(self.fd)
    }
}
<commit_msg>Added Linux generic hardware counters.<commit_after>use std::fs::File;
use std::os::unix::io::FromRawFd;
use std::io::Read;
use std::io;
use std::io::{Error};
use std::mem;

use libc::{pid_t};

#[allow(dead_code, non_camel_case_types)]
mod hw_breakpoint;
#[allow(dead_code, non_camel_case_types)]
mod perf_event;

use ::AbstractPerfCounter;
use x86::perfcnt::intel::description::{IntelPerformanceCounterDescription, Tuple};

const IOCTL: usize = 16;
const PERF_EVENT_OPEN: usize = 298;

fn perf_event_open(hw_event: perf_event::perf_event_attr,
                       pid: perf_event::__kernel_pid_t,
                       cpu:  ::libc::c_int,
                       group_fd:  ::libc::c_int,
                       flags:  ::libc::c_int) -> isize {
    unsafe {
        syscall!(PERF_EVENT_OPEN, &hw_event as *const perf_event::perf_event_attr as usize, pid, cpu, group_fd, flags) as isize
    }
}

fn ioctl(fd: ::libc::c_int, request: u64, value: ::libc::c_int) -> isize {
    unsafe {
        syscall!(IOCTL, fd, request, value) as isize
    }
}

fn read_counter(fd: ::libc::c_int) -> Result<u64, io::Error> {
    unsafe {
        let mut f = File::from_raw_fd(fd);
        let mut value: [u8; 8] = Default::default();
        try!(f.read(&mut value));
        Ok(mem::transmute::<[u8; 8], u64>(value))
    }
}

pub struct PerfCounterBuilderLinux {
    group: isize,
    pid: pid_t,
    cpu: isize,
    flags: usize,
    attrs: perf_event::perf_event_attr,
}

impl Default for PerfCounterBuilderLinux {
    fn default () -> PerfCounterBuilderLinux {
        PerfCounterBuilderLinux {
            group: -1,
            pid: 0,
            cpu: -1,
            flags: 0,
            attrs: Default::default()
        }
    }
}

pub enum HardwareCounterType {
    /// Total cycles.  Be wary of what happens during CPU frequency scaling.
    CountHWCPUCycles = perf_event::PERF_COUNT_HW_CPU_CYCLES as isize,

    /// Retired instructions.  Be careful, these can be affected by various issues, most notably hardware interrupt counts.
    CountHWInstructions = perf_event::PERF_COUNT_HW_INSTRUCTIONS as isize,

    /// Cache  accesses.  Usually this indicates Last Level Cache accesses but this may vary depending on your CPU. This may include prefetches and
    CountHWCacheReferences = perf_event::PERF_COUNT_HW_CACHE_REFERENCES as isize,

    /// Cache misses.  Usually this indicates Last Level Cache misses; this is intended to be used  in  conjunction with the
    CountHWCacheMisses = perf_event::PERF_COUNT_HW_CACHE_MISSES as isize,

    /// Retired branch instructions.  Prior to Linux 2.6.34, this used the wrong event on AMD processors.
    CountHWBranchInstructions = perf_event::PERF_COUNT_HW_BRANCH_INSTRUCTIONS as isize,

    /// Mispredicted branch instructions.
    CountHWBranchMisses = perf_event::PERF_COUNT_HW_BRANCH_MISSES as isize,

    /// Bus cycles, which can be different from total cycles.
    CountHWBusCycles = perf_event::PERF_COUNT_HW_BUS_CYCLES as isize,

    /// Stalled cycles during issue. (Since Linux 3.0)
    CountHWStalledCyclesFrontend = perf_event::PERF_COUNT_HW_STALLED_CYCLES_FRONTEND as isize,

    /// Stalled cycles during retirement. (Since Linux 3.0)
    CountHWStalledCyclesBackend = perf_event::PERF_COUNT_HW_STALLED_CYCLES_BACKEND as isize,

    /// Total cycles; not affected by CPU frequency scaling. (Since Linux 3.3)
    CountHWRefCPUCycles = perf_event::PERF_COUNT_HW_REF_CPU_CYCLES as isize,
}

impl PerfCounterBuilderLinux {

    /// Instantiate a generic hardware performance counter as defined by the Linux interface.
    pub fn from_type_hardware_counter(counter: HardwareCounterType) -> PerfCounterBuilderLinux {
        let mut pc: PerfCounterBuilderLinux = Default::default();

        pc.attrs._type = perf_event::PERF_TYPE_HARDWARE;
        pc.attrs.config = counter as u64;
        pc
    }

    /// Instantiate a H/W performance counter using a counter as described in Intels SDM.
    pub fn from_raw_intel_counter_description(counter: &IntelPerformanceCounterDescription) -> PerfCounterBuilderLinux {
        let mut pc: PerfCounterBuilderLinux = Default::default();
        let mut config: u64 = 0;

        match counter.event_code {
            Tuple::One(code) =>  config |= (code as u64) << 0,
            Tuple::Two(_, _) => unreachable!() // NYI
        };
        match counter.umask {
            Tuple::One(code) =>  config |= (code as u64) << 8,
            Tuple::Two(_, _) => unreachable!() // NYI
        };
        config |= (counter.counter_mask as u64) << 24;

        if counter.edge_detect {
            config |= 1 << 18;
        }
        if counter.any_thread {
            config |= 1 << 21;
        }
        if counter.invert {
            config |= 1 << 23;
        }

        pc.attrs._type = perf_event::PERF_TYPE_RAW;
        pc.attrs.config = config;
        pc
    }

    /// Set counter group.
    pub fn set_group<'a>(&'a mut self, group_fd: isize) -> &'a mut PerfCounterBuilderLinux {
        self.group = group_fd;
        self
    }

    /// Sets PERF_FLAG_FD_OUTPUT
    ///
    /// This flag re-routes the output from an event to the group leader.
    pub fn set_flag_fd_output<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.flags |= 0x0; //PERF_FLAG_FD_OUTPUT;
        self
    }

    /// Sets PERF_FLAG_PID_CGROUP
    ///
    /// This flag activates per-container system-wide monitoring.  A
    /// container is an abstraction that isolates a set of resources for
    /// finer grain control (CPUs, memory, etc.).   In  this  mode,  the
    /// event  is  measured  only if the thread running on the monitored
    /// CPU belongs to the designated container (cgroup).
    pub fn set_flag_pid_cgroup<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.flags |= 0x0; //PERF_FLAG_PID_CGROUP;
        self
    }

    /// Add a sample period.
    pub fn set_sample_period<'a>(&'a mut self, period: u64) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.sample_period_freq = period;
        self
    }

    /// Add a sample frequency.
    pub fn set_sample_frequency<'a>(&'a mut self, frequency: u64) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.sample_period_freq = frequency;
        self.attrs.settings.insert(perf_event::EVENT_ATTR_FREQ);
        self
    }

    /// The counter starts out disabled.
    pub fn disable<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_DISABLED);
        self
    }

    /// This counter should count events of child tasks as well as the task specified.
    pub fn inherit<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_INHERIT);
        self
    }

    /// The pinned bit specifies that the counter should always be on the CPU if at all possible.
    /// It applies only to  hardware counters and only to group leaders.
    pub fn pinned<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_PINNED);
        self
    }

    /// The counter is exclusive i.e., when this counter's group is on the CPU,
    /// it should be the only group using the CPU's counters.
    pub fn exclusive<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_EXCLUSIVE);
        self
    }

    /// The counter excludes events that happen in user space.
    pub fn exclude_user<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_EXCLUDE_USER);
        self
    }

    /// The counter excludes events that happen in the kernel.
    pub fn exclude_kernel<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_EXCLUDE_KERNEL);
        self
    }

    /// The counter excludes events that happen in the hypervisor.
    pub fn exclude_hv<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_EXCLUDE_HV);
        self
    }

    /// The counter doesn't count when the CPU is idle.
    pub fn exclude_idle<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_EXCLUDE_IDLE);
        self
    }

    /// Enables recording of exec mmap events.
    pub fn enable_mmap<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_MMAP);
        self
    }

    /// The counter will save event counts on context switch for inherited tasks.
    /// This is meaningful only if the inherit field is set.
    pub fn inherit_stat<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_INHERIT_STAT);
        self
    }

    /// The counter is automatically enabled after a call to exec.
    pub fn enable_on_exec<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_ENABLE_ON_EXEC);
        self
    }

    /// fork/exit notifications are included in the ring buffer.
    pub fn enable_task_notification<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_TASK);
        self
    }

    /// The counter has  a  sampling  interrupt happen when we cross the wakeup_watermark
    /// boundary.  Otherwise interrupts happen after wakeup_events samples.
    pub fn enable_watermark<'a>(&'a mut self, watermark_events: u32) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_WATERMARK);
        self.attrs.wakeup_events_watermark = watermark_events;
        self
    }

    /// Sampled IP counter can have arbitrary skid.
    pub fn set_ip_sample_arbitrary_skid<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_SAMPLE_IP_ARBITRARY_SKID);
        self
    }

    /// Sampled IP counter requested to have constant skid.
    pub fn set_ip_sample_constant_skid<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_SAMPLE_IP_CONSTANT_SKID);
        self
    }

    /// Sampled IP counter requested to have 0 skid.
    pub fn set_ip_sample_req_zero_skid<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_SAMPLE_IP_REQ_ZERO_SKID);
        self
    }

    /// The counterpart of enable_mmap, but enables including data mmap events in the ring-buffer.
    pub fn enable_mmap_data<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_MMAP_DATA);
        self
    }

    /// Sampled IP counter must have 0 skid.
    pub fn set_ip_sample_zero_skid<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.attrs.settings.insert(perf_event::EVENT_ATTR_SAMPLE_IP_ZERO_SKID);
        self
    }

    /// Measure for all PIDs on the core.
    pub fn for_all_pids<'a>(&'a mut self) ->  &'a mut PerfCounterBuilderLinux {
        self.pid = -1;
        self
    }

    /// Measure for a specific PID.
    pub fn for_pid<'a>(&'a mut self, pid: i32) -> &'a mut PerfCounterBuilderLinux {
        self.pid = pid;
        self
    }

    /// Pin counter to CPU.
    pub fn on_cpu<'a>(&'a mut self, cpu: isize) -> &'a mut PerfCounterBuilderLinux {
        self.cpu = cpu;
        self
    }

    /// Measure on all CPUs.
    pub fn on_all_cpus<'a>(&'a mut self) -> &'a mut PerfCounterBuilderLinux {
        self.cpu = -1;
        self
    }

    /// Instantiate the performance counter.
    pub fn finish(&self) -> Result<PerfCounter, io::Error> {
        let flags = 0;
        let fd = perf_event_open(self.attrs, self.pid, self.cpu as i32, self.group as i32, flags) as ::libc::c_int;
        if fd < 0 {
            // TODO: Our syscall invocation probably does not set errno?
            return Err(Error::last_os_error());
        }

        Ok(PerfCounter { fd: fd })
    }
}

pub struct PerfCounter {
    fd: ::libc::c_int
}

impl AbstractPerfCounter for PerfCounter {

    fn reset(&self) -> Result<(), io::Error> {
        let ret = ioctl(self.fd, perf_event::PERF_EVENT_IOC_RESET, 0);
        if ret == -1 {
            return Err(Error::last_os_error());
        }
        Ok(())
    }

    fn start(&self) -> Result<(), io::Error> {
        let ret = ioctl(self.fd, perf_event::PERF_EVENT_IOC_ENABLE, 0);
        if ret == -1 {
            return Err(Error::last_os_error());
        }
        Ok(())
    }

    fn stop(&self) -> Result<(), io::Error> {
        let ret = ioctl(self.fd, perf_event::PERF_EVENT_IOC_DISABLE, 0);
        if ret == -1 {
            return Err(Error::last_os_error());
        }
        Ok(())
    }

    fn read(&self) -> Result<u64, io::Error> {
        read_counter(self.fd)
    }
}
<|endoftext|>


<commit_before>use time::SteadyTime;

use std::ops::Add;
use std::time::Duration;

/// The current time
///
/// This value is similar to (and directly derived from) the
/// `time::SteadyTime`.  But it has three important properties:
///
/// 1. It has a millisecond precision
/// 2. It's size is 8 bytes (SteadyTime is 16 bytes)
/// 3. It supports math with `std::time::Duration` (more future-proof)
///
/// The size of the value is important because we are going to have a lot of
/// timeouts and lots of timestamps stored inside the state machines.
///
/// Precision of millisecond is good enough, and even better for our use case
/// as it allows faster comparison and more frequent matches.
///
/// Warning: when adding a duration that is not a multiple of a millisecond
/// we truncate (i.e. floor) the duration value. We may change this in future.
/// Note that for timeouts this works well enough, as mio already bumps the
/// timeout to at least a millisecond ahead.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time(u64);

impl Add<Duration> for Time {
    type Output = Time;
    fn add(self, rhs: Duration) -> Time {
        Time(self.0 + rhs.as_secs()*1000 + (rhs.subsec_nanos()/1000000) as u64)
    }
}

impl Time {
    /// Zero time value, should be used only as a starting point for unit
    /// tests
    pub fn zero() -> Time {
        // In fact we don't care actual value, but the 1 allows us to
        // implement NonZero in the future
        Time(1)
    }
}

pub fn make_time(base: SteadyTime, now: SteadyTime) -> Time {
    Time((now - base).num_milliseconds() as u64)
}

pub fn diff_ms(now: Time, event: Time) -> u64 {
    if event.0 > now.0 {
        event.0 - now.0
    } else {
        0
    }
}

#[cfg(test)]
mod test {
    use super::Time;
    use std::time::Duration;

    #[test]
    fn test_add_duration() {
        let tm = Time::zero();
        assert_eq!(tm + Duration::new(10, 0), Time(10001));
        assert_eq!(tm + Duration::from_millis(150), Time(151));
        assert_eq!(tm + Duration::from_millis(12345), Time(12346));
        assert_eq!(tm + Duration::new(5, 0) + Duration::from_millis(20),
                   Time(5021));
    }

}
<commit_msg>Use 1-based Time not zero-based<commit_after>use time::SteadyTime;

use std::ops::Add;
use std::time::Duration;

/// The current time
///
/// This value is similar to (and directly derived from) the
/// `time::SteadyTime`.  But it has three important properties:
///
/// 1. It has a millisecond precision
/// 2. It's size is 8 bytes (SteadyTime is 16 bytes)
/// 3. It supports math with `std::time::Duration` (more future-proof)
///
/// The size of the value is important because we are going to have a lot of
/// timeouts and lots of timestamps stored inside the state machines.
///
/// Precision of millisecond is good enough, and even better for our use case
/// as it allows faster comparison and more frequent matches.
///
/// Warning: when adding a duration that is not a multiple of a millisecond
/// we truncate (i.e. floor) the duration value. We may change this in future.
/// Note that for timeouts this works well enough, as mio already bumps the
/// timeout to at least a millisecond ahead.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time(u64);

impl Add<Duration> for Time {
    type Output = Time;
    fn add(self, rhs: Duration) -> Time {
        Time(self.0 + rhs.as_secs()*1000 + (rhs.subsec_nanos()/1000000) as u64)
    }
}

impl Time {
    /// Zero time value, should be used only as a starting point for unit
    /// tests
    pub fn zero() -> Time {
        // In fact we don't care actual value, but the 1 allows us to
        // implement NonZero in the future
        Time(1)
    }
}

pub fn make_time(base: SteadyTime, now: SteadyTime) -> Time {
    Time((now - base).num_milliseconds() as u64
         // Time starts with 1 not with zero
         + 1)
}

pub fn diff_ms(now: Time, event: Time) -> u64 {
    if event.0 > now.0 {
        event.0 - now.0
    } else {
        0
    }
}

#[cfg(test)]
mod test {
    use super::Time;
    use std::time::Duration;

    #[test]
    fn test_add_duration() {
        let tm = Time::zero();
        assert_eq!(tm + Duration::new(10, 0), Time(10001));
        assert_eq!(tm + Duration::from_millis(150), Time(151));
        assert_eq!(tm + Duration::from_millis(12345), Time(12346));
        assert_eq!(tm + Duration::new(5, 0) + Duration::from_millis(20),
                   Time(5021));
    }

}
<|endoftext|>


<commit_before>//! Spans represent periods of time in the execution of a program.

/// Identifies a span within the context of a process.
///
/// Span IDs are used primarily to determine of two handles refer to the same
/// span, without requiring the comparison of the span's fields.
///
/// They are generated by [`Subscriber`](::Subscriber)s for each span as it is
/// created, through the [`new_id`](::Subscriber::new_span_id) trait
/// method. See the documentation for that method for more information on span
/// ID generation.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Span(u64);

// ===== impl Id =====

impl Span {
    /// Constructs a new span ID from the given `u64`.
    pub fn from_u64(u: u64) -> Self {
        Span(u)
    }
}
<commit_msg>trace: Allow `Span` IDs to be converted back to `u64`s (#910)<commit_after>//! Spans represent periods of time in the execution of a program.

/// Identifies a span within the context of a process.
///
/// Span IDs are used primarily to determine if two handles refer to the same
/// span, without requiring the comparison of the span's fields.
///
/// They are generated by [`Subscriber`](::Subscriber)s for each span as it is
/// created, through the [`new_id`](::Subscriber::new_span_id) trait
/// method. See the documentation for that method for more information on span
/// ID generation.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Span(u64);

// ===== impl Id =====

impl Span {
    /// Constructs a new span ID from the given `u64`.
    pub fn from_u64(u: u64) -> Self {
        Span(u)
    }

    /// Returns the span's ID as a  `u64`.
    pub fn into_u64(&self) -> u64 {
        self.0
    }
}
<|endoftext|>


<commit_before>//! Shared mathematical utility functions.

/// Cut value to be inside given range
///
/// ```
/// use image::math::utils;
///
/// assert_eq!(utils::clamp(-5, 0, 10),  0);
/// assert_eq!(utils::clamp( 6, 0, 10),  6);
/// assert_eq!(utils::clamp(15, 0, 10), 10);
/// ```
#[inline]
pub fn clamp<N>(a: N, min: N, max: N) -> N
where N: PartialOrd {
    match () {
        () if a < min => min,
        () if a > max => max,
        _ => a
    }
}
<commit_msg>Simplify clamp call<commit_after>//! Shared mathematical utility functions.

/// Cut value to be inside given range
///
/// ```
/// use image::math::utils;
///
/// assert_eq!(utils::clamp(-5, 0, 10),  0);
/// assert_eq!(utils::clamp( 6, 0, 10),  6);
/// assert_eq!(utils::clamp(15, 0, 10), 10);
/// ```
#[inline]
pub fn clamp<N>(a: N, min: N, max: N) -> N
where N: PartialOrd {
    if a < min { return min }
    if a > max { return max }
    a
}
<|endoftext|>


<commit_before>#![crate_id="CSVProvider#0.1-pre"]
#![crate_type="dylib"]

// why doesn't "lib" work?

// rustc 0.11.0-pre (b47f2226a25654c5b781d27a91f2fa5274b3a347 2014-06-28 14:31:37 +0000)

#![feature(globs, macro_rules, quote, managed_boxes, plugin_registrar)]

#![allow(unused_imports)]
//#![allow(unused_variable)]
#![allow(uppercase_variables)]
#![allow(unnecessary_parens)]

extern crate syntax;
extern crate rustc;

use syntax::ast::{
   Name,
   TokenTree,
   Expr,
   ExprLit,
   ExprVec,
   LitStr,
   Ident,
   DUMMY_NODE_ID,
   MutImmutable
};
use syntax::codemap::Span;
use syntax::ext::base::{
   SyntaxExtension,
   BasicMacroExpander,
   ExtCtxt,
   MacResult,
   MacPat,
   MacItem,
   DummyResult,
   MacExpr,
   NormalTT
};
use std::gc::Gc;
use syntax::ext::quote::{
   //expand_parse_call
};
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::{InternedString, COMMA, EOF};

use std::io;
use std::io::fs;
use std::os;
use std::str;
use std::io::Process;
use syntax::ast;
use syntax::ast::Name;

use syntax::util::small_vector::SmallVector;

use std::collections::HashMap;
use std::gc::{Gc, GC};

use rustc::plugin::Registry;

#[plugin_registrar]
pub fn macro_registrar(reg: &mut Registry) {
   reg.register_macro("ProvideCSV_labels", provide_csv_given_labels);
}

#[deriving(Clone)]
struct Entry {
   str: InternedString,
   expr: Gc<Expr>
}

// see https://github.com/sfackler/syntax-ext-talk/blob/gh-pages/simple-ext/lib.rs
fn parse_entries(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
   let mut parser = parse::new_parser_from_tts(
       cx.parse_sess(),
       cx.cfg(),
       tts.iter()
          .map(|x| (*x).clone())
          .collect()
   );

   let mut entries: Vec<Entry> = Vec::new();

   let mut error = false;
   while parser.token != EOF {
      let entry = parser.parse_expr();

      let entry_str = match entry.node {
         ExprLit(lit) => {
            match lit.node {
               LitStr(ref s, _) => s.clone(),
               _ => {
                  cx.span_err(entry.span, "expected string literal (1)");
                  error = true;
                  InternedString::new("")
               }
            }
         }
         _ => {
                cx.span_err(entry.span, "expected string literal (2)");
                error = true;
                InternedString::new("")
         }
      };

      entries.push(Entry { str: entry_str, expr: entry });

      if !parser.eat(&COMMA) && parser.token != EOF {
         cx.span_err(parser.span, "expected `,`");
         return None;
      }
    }

   if error {
      return None;
   }

   Some(entries)
}

pub struct MacItems {
   items: Vec<Gc<ast::Item>>
}
impl MacItems {
   pub fn new(items: Vec<Gc<ast::Item>>) -> Box<MacResult> {
      box MacItems { items: items } as Box<MacResult>
   }
}
impl MacResult for MacItems {
   fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
      Some(SmallVector::many(self.items.clone()))
   }
}

fn parse_csv_row<'a>(raw: &'a str, expected_columns: Option<uint>) -> str::StrSplits<'a> {
   let mut it = raw.split_str(",");

   // take a pulse
   let _whatever = it.map(|xx| {
      println!("iterating over row elements: {}", xx.to_string());
      return xx;
   });

   match expected_columns {
      Some(count) => {
         if (count == it.count()) {
            println!("parse_csv_row: matching length expected");
         } else {
            println!("parse_csv_row: wrong length!");
         }
      },
      None => (),
   }

   return it;
}

fn provide_csv_given_labels(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult> {
   let mut entries = match parse_entries(cx, tts) {
      Some(entries) => entries,
      None => return DummyResult::expr(sp),
   };

   let raw_name   : Entry = entries.shift().expect("should be given a type name");
   let raw_path   : Entry = entries.shift().expect("should be given a CSV file path");
   let raw_labels : Entry = entries.shift().expect("should be given column labels");

   let name   : InternedString = raw_name.str;
   let path   : InternedString = raw_path.str;
   let labels : InternedString = raw_labels.str;

   println!("provide_csv_given_labels: name:   {}", name);
   println!("provide_csv_given_labels: path:   {}", path);
   println!("provide_csv_given_labels: labels: {}", labels);

   // PENDING
   // read the CSV and try to get the type of data in it
   // create a type with
   //  * this name,
   //  * these labeled columns,
   //  * discovered type of data
   //  * a constructor which reads the whole file

   fn interned_to_ident(xx: InternedString) -> Ident {
      let yy: String = format!("{}", xx);
      let zz: &str = yy.as_slice();
      return token::str_to_ident(zz);
   }

   fn interned_to_ident_with_suffix(xx: InternedString, suff: &str) -> Ident {
      let yy: String = format!("{}{}", xx, suff);
      let zz: &str = yy.as_slice();
      return token::str_to_ident(zz);
   }

   let MyCsv    = interned_to_ident(name.clone());
   let MyCsvRow = interned_to_ident_with_suffix(name, "Row");
   let col0     = interned_to_ident(labels.clone());

   println!("Parsing given labels...");

   let labels1 = format!("{}", labels);
   let labels_iter = parse_csv_row(labels1.as_slice(), None);

   println!("Defining items in the CSV provider...");

/*
   fn mut_ref_cx<'a>(context: &'a mut ExtCtxt) -> &'a mut ExtCtxt {
        let &ExtCtxt(ref mut context_prime) = context;
        return context_prime;
   }
*/

/*
   pub fn expand_quote_item(
      cx: &ExtCtxt,
      sp: Span,
      tts: &[ast::TokenTree])
      -> Box<base::MacResult>
   {
      let expanded = expand_parse_call(cx, sp, "parse_item_with_outer_attributes", vec!(), tts);
      base::MacExpr::new(expanded)
   }
*/

   let icx : &ExtCtxt = cx;  // an immutable borrow

   // TODO: iterate through call columns
   let col = quote_item!(icx,
      pub $col0: String
   ).expect("column parsing");

   let item0 = quote_item!(icx,
      pub struct $MyCsvRow {
         $col,
      }
   );

   let item1: Option<Gc<syntax::ast::Item>> = quote_item!(icx,
      pub struct $MyCsv {
         pub data: Vec<$MyCsvRow>,
      }
   );

   let item2: Option<Gc<syntax::ast::Item>> = quote_item!(icx,
      impl $MyCsv {
         pub fn new() -> $MyCsv {
            println!("HMMMMMM.");
            return $MyCsv {
               data: (vec![
                  $MyCsvRow { $col0: "zero".to_string() },
                  $MyCsvRow { $col0:  "one".to_string() },
                  $MyCsvRow { $col0:  "two".to_string() },
               ]),
            };
         }
      }
   );

   let items = vec![item0.expect("Should be able to make struct MyCsvRow"),
                    item1.expect("Should be able to make struct MyCsv."),
                    item2.expect("Should be able to implement MyCsv.")];

   println!("OK");

   return MacItems::new(items);
}

<commit_msg>cleanup<commit_after>#![crate_id="CSVProvider#0.1-pre"]
#![crate_type="dylib"]

// why doesn't "lib" work?

// rustc 0.11.0-pre (b47f2226a25654c5b781d27a91f2fa5274b3a347 2014-06-28 14:31:37 +0000)

#![feature(globs, macro_rules, quote, managed_boxes, plugin_registrar)]

#![allow(unused_imports)]
//#![allow(unused_variable)]
#![allow(uppercase_variables)]
#![allow(unnecessary_parens)]

extern crate syntax;
extern crate rustc;

use syntax::ast::{
   Name,
   TokenTree,
   Expr,
   ExprLit,
   ExprVec,
   LitStr,
   Ident,
   DUMMY_NODE_ID,
   MutImmutable
};
use syntax::codemap::Span;
use syntax::ext::base::{
   SyntaxExtension,
   BasicMacroExpander,
   ExtCtxt,
   MacResult,
   MacPat,
   MacItem,
   DummyResult,
   MacExpr,
   NormalTT
};
use std::gc::Gc;
use syntax::ext::quote::{
   //expand_parse_call
};
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::{InternedString, COMMA, EOF};

use std::io;
use std::io::fs;
use std::os;
use std::str;
use std::io::Process;
use syntax::ast;
use syntax::ast::Name;

use syntax::util::small_vector::SmallVector;

use std::collections::HashMap;
use std::gc::{Gc, GC};

use rustc::plugin::Registry;

#[plugin_registrar]
pub fn macro_registrar(reg: &mut Registry) {
   reg.register_macro("ProvideCSV_labels", provide_csv_given_labels);
}

#[deriving(Clone)]
struct Entry {
   str: InternedString,
   expr: Gc<Expr>
}

// see https://github.com/sfackler/syntax-ext-talk/blob/gh-pages/simple-ext/lib.rs
fn parse_entries(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
   let mut parser = parse::new_parser_from_tts(
       cx.parse_sess(),
       cx.cfg(),
       tts.iter()
          .map(|x| (*x).clone())
          .collect()
   );

   let mut entries: Vec<Entry> = Vec::new();

   let mut error = false;
   while parser.token != EOF {
      let entry = parser.parse_expr();

      let entry_str = match entry.node {
         ExprLit(lit) => {
            match lit.node {
               LitStr(ref s, _) => s.clone(),
               _ => {
                  cx.span_err(entry.span, "expected string literal (1)");
                  error = true;
                  InternedString::new("")
               }
            }
         }
         _ => {
                cx.span_err(entry.span, "expected string literal (2)");
                error = true;
                InternedString::new("")
         }
      };

      entries.push(Entry { str: entry_str, expr: entry });

      if !parser.eat(&COMMA) && parser.token != EOF {
         cx.span_err(parser.span, "expected `,`");
         return None;
      }
    }

   if error {
      return None;
   }

   Some(entries)
}

pub struct MacItems {
   items: Vec<Gc<ast::Item>>
}
impl MacItems {
   pub fn new(items: Vec<Gc<ast::Item>>) -> Box<MacResult> {
      box MacItems { items: items } as Box<MacResult>
   }
}
impl MacResult for MacItems {
   fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
      Some(SmallVector::many(self.items.clone()))
   }
}

fn parse_csv_row<'a>(raw: &'a str, expected_columns: Option<uint>) -> str::StrSplits<'a> {
   let mut it = raw.split_str(",");

   // take a pulse
   let _whatever = it.map(|xx| {
      println!("iterating over row elements: {}", xx.to_string());
      return xx;
   });

   match expected_columns {
      Some(count) => {
         if (count == it.count()) {
            println!("parse_csv_row: matching length expected");
         } else {
            println!("parse_csv_row: wrong length!");
         }
      },
      None => (),
   }

   return it;
}

fn provide_csv_given_labels(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult> {
   let mut entries = match parse_entries(cx, tts) {
      Some(entries) => entries,
      None => return DummyResult::expr(sp),
   };

   let icx : &ExtCtxt = cx;  // an immutable borrow

   let raw_name   : Entry = entries.shift().expect("should be given a type name");
   let raw_path   : Entry = entries.shift().expect("should be given a CSV file path");
   let raw_labels : Entry = entries.shift().expect("should be given column labels");

   let name   : InternedString = raw_name.str;
   let path   : InternedString = raw_path.str;
   let labels : InternedString = raw_labels.str;

   println!("provide_csv_given_labels: name:   {}", name);
   println!("provide_csv_given_labels: path:   {}", path);
   println!("provide_csv_given_labels: labels: {}", labels);

   // PENDING
   // read the CSV and try to get the type of data in it
   // create a type with
   //  * this name,
   //  * these labeled columns,
   //  * discovered type of data
   //  * a constructor which reads the whole file

   fn interned_to_ident(xx: InternedString) -> Ident {
      let yy: String = format!("{}", xx);
      let zz: &str = yy.as_slice();
      return token::str_to_ident(zz);
   }

   fn interned_to_ident_with_suffix(xx: InternedString, suff: &str) -> Ident {
      let yy: String = format!("{}{}", xx, suff);
      let zz: &str = yy.as_slice();
      return token::str_to_ident(zz);
   }

   let MyCsv    = interned_to_ident(name.clone());
   let MyCsvRow = interned_to_ident_with_suffix(name, "Row");
   let col0     = interned_to_ident(labels.clone());

   println!("Parsing given labels...");

   let labels1 = format!("{}", labels);
   let labels_iter = parse_csv_row(labels1.as_slice(), None);

   println!("Defining items in the CSV provider...");

   // TODO: iterate through call columns
   let col = quote_item!(icx,
      pub $col0: String
   ).expect("column parsing");

   let item0 = quote_item!(icx,
      pub struct $MyCsvRow {
         $col,
      }
   );

   let item1: Option<Gc<syntax::ast::Item>> = quote_item!(icx,
      pub struct $MyCsv {
         pub data: Vec<$MyCsvRow>,
      }
   );

   let item2: Option<Gc<syntax::ast::Item>> = quote_item!(icx,
      impl $MyCsv {
         pub fn new() -> $MyCsv {
            println!("HMMMMMM.");
            return $MyCsv {
               data: (vec![
                  $MyCsvRow { $col0: "zero".to_string() },
                  $MyCsvRow { $col0:  "one".to_string() },
                  $MyCsvRow { $col0:  "two".to_string() },
               ]),
            };
         }
      }
   );

   let items = vec![item0.expect("Should be able to make struct MyCsvRow"),
                    item1.expect("Should be able to make struct MyCsv."),
                    item2.expect("Should be able to implement MyCsv.")];

   println!("OK");

   return MacItems::new(items);
}

<|endoftext|>