<commit_before>//! A data structure for tracking source positions in language implementations, inspired by the
//! [CodeMap type in rustc's libsyntax](https://github.com/rust-lang/rust/blob/master/src/libsyntax/codemap.rs).
//!
//! The `CodeMap` tracks all source files and maps positions within them to linear indexes as if all
//! source files were concatenated. This allows a source position to be represented by a small
//! 32-bit `Pos` indexing into the `CodeMap`, under the assumption that the total amount of parsed
//! source code will not exceed 4GiB. The `CodeMap` can look up the source file, line, and column
//! of a `Pos` or `Span`, as well as provide source code snippets for error reporting.
//!
//! # Example
//! ```
//! use codemap::CodeMap;
//! let mut codemap = CodeMap::new();
//! let file = codemap.add_file("test.rs".to_string(), "fn test(){\n    println!(\"Hello\");\n}\n".to_string());
//! let string_literal_span = file.span.subspan(24, 31);
//!
//! let location = codemap.look_up_span(string_literal_span);
//! assert_eq!(location.file.name(), "test.rs");
//! assert_eq!(location.begin.line, 1);
//! assert_eq!(location.begin.column, 13);
//! assert_eq!(location.end.line, 1);
//! assert_eq!(location.end.column, 20);
//! ```

use std::cmp::{self, Ordering};
use std::ops::{Add, Sub, Deref};
use std::fmt;
use std::sync::Arc;
use std::hash::{Hash, Hasher};

/// A small, `Copy`, value representing a position in a `CodeMap`'s file.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct Pos(u32);

impl Add<u64> for Pos {
    type Output = Pos;
    fn add(self, other: u64) -> Pos {
        Pos(self.0 + other as u32)
    }
}

impl Sub<Pos> for Pos {
    type Output = u64;
    fn sub(self, other: Pos) -> u64 {
        (self.0 - other.0) as u64
    }
}

/// A range of text within a CodeMap.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct Span {
    /// The position in the codemap representing the first byte of the span.
    low: Pos,

    /// The position after the last byte of the span.
    high: Pos,
}

impl Span {
    /// Makes a span from offsets relative to the start of this span.
    ///
    /// # Panics
    ///   * If `end < begin`
    ///   * If `end` is beyond the length of the span
    pub fn subspan(&self, begin: u64, end: u64) -> Span {
        assert!(end >= begin);
        assert!(self.low + end <= self.high);
        Span {
            low: self.low + begin,
            high: self.low + end,
        }
    }

    /// Checks if a span is contained within this span.
    pub fn contains(&self, other: Span) -> bool {
        self.low <= other.low && self.high >= other.high
    }

    /// The position in the codemap representing the first byte of the span.
    pub fn low(&self) -> Pos {
        self.low
    }

    /// The position after the last byte of the span.
    pub fn high(&self) -> Pos {
        self.high
    }

    /// The length in bytes of the text of the span
    pub fn len(&self) -> u64 {
        self.high - self.low
    }

    /// Create a span that encloses both `self` and `other`.
    pub fn merge(&self, other: Span) -> Span {
        Span {
            low: cmp::min(self.low, other.low),
            high: cmp::max(self.high, other.high),
        }
    }
}

/// Associate a Span with a value of arbitrary type (e.g. an AST node).
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
pub struct Spanned<T> {
    pub node: T,
    pub span: Span,
}

impl<T> Deref for Spanned<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.node
    }
}

/// A data structure recording source code files for position lookup.
#[derive(Default)]
pub struct CodeMap {
    files: Vec<Arc<File>>,
    _allow_priv: ()
}

impl CodeMap {
    /// Creates an empty `CodeMap`.
    pub fn new() -> CodeMap {
        Default::default()
    }

    /// Adds a file with the given name and contents.
    ///
    /// Use the returned `File` and its `.span` property to create `Spans`
    /// representing substrings of the file.
    pub fn add_file(&mut self, name: String, source: String) -> Arc<File> {
        let low = self.end_pos() + 1;
        let high = low + source.len() as u64;
        let mut lines = vec![low];
        lines.extend(source.match_indices('\n').map(|(p, _)| { low + (p + 1) as u64 }));

        let file = Arc::new(File {
            span: Span { low: low, high: high },
            name: name,
            source: source,
            lines: lines,
        });

        self.files.push(file.clone());
        file
    }

    fn end_pos(&self) -> Pos {
        self.files.last().map(|x| x.span.high).unwrap_or(Pos(0))
    }

    /// Looks up the `File` that contains the specified position.
    pub fn find_file(&self, pos: Pos) -> &Arc<File> {
        self.files.binary_search_by(|file| {
            if file.span.high < pos {
                Ordering::Less
            } else if file.span.low > pos {
                Ordering::Greater
            } else {
                Ordering::Equal
            }
        }).ok().map(|i| &self.files[i]).expect("Mapping unknown source location")
    }

    /// Gets the file, line, and column represented by a `Pos`.
    pub fn look_up_pos(&self, pos: Pos) -> Loc {
        let file = self.find_file(pos);
        let position = file.find_line_col(pos);
        Loc { file: file.clone(), position }
    }

    /// Gets the file and its line and column ranges represented by a `Span`.
    pub fn look_up_span(&self, span: Span) -> SpanLoc {
        let file = self.find_file(span.low);
        let begin = file.find_line_col(span.low);
        let end = file.find_line_col(span.high);
        SpanLoc { file: file.clone(), begin, end }
    }
}

/// A `CodeMap`'s record of a source file.
pub struct File {
    /// The span representing the entire file.
    pub span: Span,

    /// The filename as it would be displayed in an error message.
    name: String,

    /// Contents of the file.
    source: String,

    /// Byte positions of line beginnings.
    lines: Vec<Pos>,
}

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

    /// Gets the line number of a Pos.
    ///
    /// The lines are 0-indexed (first line is numbered 0)
    ///
    /// # Panics
    ///
    ///  * If `pos` is not within this file's span
    pub fn find_line(&self, pos: Pos) -> usize {
        assert!(pos >= self.span.low);
        assert!(pos <= self.span.high);
        (match self.lines.binary_search(&pos) {
            Ok(i) => i,
            Err(i) => i - 1,
        })
    }

    /// Gets the line and column of a Pos.
    ///
    /// # Panics
    ///
    /// * If `pos` is not with this file's span
    /// * If `pos` points to a byte in the middle of a UTF-8 character
    pub fn find_line_col(&self, pos: Pos) -> LineCol {
        let line = self.find_line(pos);
        let line_span = self.line_span(line);
        let byte_col = pos - line_span.low;
        let col = self.source_slice(line_span)[..byte_col as usize].chars().count();

        LineCol{ line: line, column: col }
    }

    /// Gets the full source text of the file
    pub fn source(&self) -> &str {
        &self.source
    }

    /// Gets the source text of a Span.
    ///
    /// # Panics
    ///
    ///   * If `span` is not entirely within this file.
    pub fn source_slice(&self, span: Span) -> &str {
        assert!(self.span.contains(span));
        &self.source[((span.low - self.span.low) as usize)..((span.high - self.span.low) as usize)]
    }

    /// Gets the span representing a line by line number.
    ///
    /// The line number is 0-indexed (first line is numbered 0). The returned span includes the
    /// line terminator.
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn line_span(&self, line: usize) -> Span {
        assert!(line < self.lines.len());
        Span {
            low: self.lines[line],
            high: *self.lines.get(line + 1).unwrap_or(&self.span.high)
        }
    }

    /// Gets the source text of a line.
    ///
    /// The string returned does not include the terminating \r or \n characters.
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn source_line(&self, line: usize) -> &str {
        self.source_slice(self.line_span(line)).trim_right_matches(&['\n', '\r'][..])
    }

    /// Gets the number of lines in the file
    pub fn num_lines(&self) -> usize {
        self.lines.len()
    }
}

impl fmt::Debug for File {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "File({:?})", self.name)
    }
}

impl PartialEq for File {
    /// Compares by identity
    fn eq(&self, other: &File) -> bool {
        self as *const _ == other as *const _
    }
}

impl Eq for File {}

impl Hash for File {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.span.hash(hasher);
    }
}

/// A line and column.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct LineCol {
    /// The line number within the file (0-indexed).
    pub line: usize,

    /// The column within the line (0-indexed).
    pub column: usize,
}

/// A file, and a line and column within it.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Loc {
    pub file: Arc<File>,
    pub position: LineCol,
}

impl fmt::Display for Loc {
    /// Formats the location as `filename:line:column`, with a 1-indexed
    /// line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}:{}:{}", self.file.name, self.position.line+1, self.position.column+1)
    }
}

/// A file, and a line and column range within it.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct SpanLoc {
    pub file: Arc<File>,
    pub begin: LineCol,
    pub end: LineCol,
}

impl fmt::Display for SpanLoc {
    /// Formats the span as `filename:start_line:start_column: end_line:end_column`,
    /// or if the span is zero-length, `filename:line:column`, with a 1-indexed line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.begin == self.end {
            write!(f, "{}:{}:{}", self.file.name, self.begin.line+1, self.begin.column+1)
        } else {
            write!(f, "{}:{}:{}: {}:{}", self.file.name, self.begin.line+1, self.begin.column+1, self.end.line+1, self.end.column+1)
        }
    }
}

#[test]
fn test_codemap() {
    let mut codemap = CodeMap::new();
    let f1 = codemap.add_file("test1.rs".to_string(), "abcd\nefghij\nqwerty".to_string());
    let f2 = codemap.add_file("test2.rs".to_string(), "foo\nbar".to_string());

    assert_eq!(codemap.find_file(f1.span.low()).name(), "test1.rs");
    assert_eq!(codemap.find_file(f1.span.high()).name(), "test1.rs");
    assert_eq!(codemap.find_file(f2.span.low()).name(), "test2.rs");
    assert_eq!(codemap.find_file(f2.span.high()).name(), "test2.rs");

    let x = f1.span.subspan(5, 10);
    let f = codemap.find_file(x.low);
    assert_eq!(f.name, "test1.rs");
    assert_eq!(f.find_line_col(f.span.low()), LineCol { line: 0, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 4), LineCol { line: 0, column: 4 });
    assert_eq!(f.find_line_col(f.span.low() + 5), LineCol { line: 1, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 16), LineCol { line: 2, column: 4 });

    let x = f2.span.subspan(4, 7);
    assert_eq!(codemap.find_file(x.low()).name(), "test2.rs");
    assert_eq!(codemap.find_file(x.high()).name(), "test2.rs");
}

#[test]
fn test_issue2() {
    let mut codemap = CodeMap::new();
    let content = "a \nxyz\r\n";
    let file = codemap.add_file("<test>".to_owned(), content.to_owned());

    let span = file.span.subspan(2, 3);
    assert_eq!(codemap.look_up_span(span), SpanLoc {
        file: file.clone(),
        begin: LineCol { line: 0, column: 2 },
        end: LineCol { line: 1, column: 0 }
    });

    assert_eq!(file.source_line(0), "a ");
    assert_eq!(file.source_line(1), "xyz");
    assert_eq!(file.source_line(2), "");
}

#[test]
fn test_multibyte() {
    let mut codemap = CodeMap::new();
    let content = "65°00′N 18°00′W 汉语\n🔬";
    let file = codemap.add_file("<test>".to_owned(), content.to_owned());

    assert_eq!(codemap.look_up_pos(file.span.low() + 21), Loc { file: file.clone(), position: LineCol { line: 0, column: 15 } });
    assert_eq!(codemap.look_up_pos(file.span.low() + 28), Loc { file: file.clone(), position: LineCol { line: 0, column: 18 } });
    assert_eq!(codemap.look_up_pos(file.span.low() + 33), Loc { file: file.clone(), position: LineCol { line: 1, column: 1 } });
}
<commit_msg>Replace deprecated trim_right_matches with trim_end_matches<commit_after>//! A data structure for tracking source positions in language implementations, inspired by the
//! [CodeMap type in rustc's libsyntax](https://github.com/rust-lang/rust/blob/master/src/libsyntax/codemap.rs).
//!
//! The `CodeMap` tracks all source files and maps positions within them to linear indexes as if all
//! source files were concatenated. This allows a source position to be represented by a small
//! 32-bit `Pos` indexing into the `CodeMap`, under the assumption that the total amount of parsed
//! source code will not exceed 4GiB. The `CodeMap` can look up the source file, line, and column
//! of a `Pos` or `Span`, as well as provide source code snippets for error reporting.
//!
//! # Example
//! ```
//! use codemap::CodeMap;
//! let mut codemap = CodeMap::new();
//! let file = codemap.add_file("test.rs".to_string(), "fn test(){\n    println!(\"Hello\");\n}\n".to_string());
//! let string_literal_span = file.span.subspan(24, 31);
//!
//! let location = codemap.look_up_span(string_literal_span);
//! assert_eq!(location.file.name(), "test.rs");
//! assert_eq!(location.begin.line, 1);
//! assert_eq!(location.begin.column, 13);
//! assert_eq!(location.end.line, 1);
//! assert_eq!(location.end.column, 20);
//! ```

use std::cmp::{self, Ordering};
use std::ops::{Add, Sub, Deref};
use std::fmt;
use std::sync::Arc;
use std::hash::{Hash, Hasher};

/// A small, `Copy`, value representing a position in a `CodeMap`'s file.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct Pos(u32);

impl Add<u64> for Pos {
    type Output = Pos;
    fn add(self, other: u64) -> Pos {
        Pos(self.0 + other as u32)
    }
}

impl Sub<Pos> for Pos {
    type Output = u64;
    fn sub(self, other: Pos) -> u64 {
        (self.0 - other.0) as u64
    }
}

/// A range of text within a CodeMap.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct Span {
    /// The position in the codemap representing the first byte of the span.
    low: Pos,

    /// The position after the last byte of the span.
    high: Pos,
}

impl Span {
    /// Makes a span from offsets relative to the start of this span.
    ///
    /// # Panics
    ///   * If `end < begin`
    ///   * If `end` is beyond the length of the span
    pub fn subspan(&self, begin: u64, end: u64) -> Span {
        assert!(end >= begin);
        assert!(self.low + end <= self.high);
        Span {
            low: self.low + begin,
            high: self.low + end,
        }
    }

    /// Checks if a span is contained within this span.
    pub fn contains(&self, other: Span) -> bool {
        self.low <= other.low && self.high >= other.high
    }

    /// The position in the codemap representing the first byte of the span.
    pub fn low(&self) -> Pos {
        self.low
    }

    /// The position after the last byte of the span.
    pub fn high(&self) -> Pos {
        self.high
    }

    /// The length in bytes of the text of the span
    pub fn len(&self) -> u64 {
        self.high - self.low
    }

    /// Create a span that encloses both `self` and `other`.
    pub fn merge(&self, other: Span) -> Span {
        Span {
            low: cmp::min(self.low, other.low),
            high: cmp::max(self.high, other.high),
        }
    }
}

/// Associate a Span with a value of arbitrary type (e.g. an AST node).
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
pub struct Spanned<T> {
    pub node: T,
    pub span: Span,
}

impl<T> Deref for Spanned<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.node
    }
}

/// A data structure recording source code files for position lookup.
#[derive(Default)]
pub struct CodeMap {
    files: Vec<Arc<File>>,
    _allow_priv: ()
}

impl CodeMap {
    /// Creates an empty `CodeMap`.
    pub fn new() -> CodeMap {
        Default::default()
    }

    /// Adds a file with the given name and contents.
    ///
    /// Use the returned `File` and its `.span` property to create `Spans`
    /// representing substrings of the file.
    pub fn add_file(&mut self, name: String, source: String) -> Arc<File> {
        let low = self.end_pos() + 1;
        let high = low + source.len() as u64;
        let mut lines = vec![low];
        lines.extend(source.match_indices('\n').map(|(p, _)| { low + (p + 1) as u64 }));

        let file = Arc::new(File {
            span: Span { low: low, high: high },
            name: name,
            source: source,
            lines: lines,
        });

        self.files.push(file.clone());
        file
    }

    fn end_pos(&self) -> Pos {
        self.files.last().map(|x| x.span.high).unwrap_or(Pos(0))
    }

    /// Looks up the `File` that contains the specified position.
    pub fn find_file(&self, pos: Pos) -> &Arc<File> {
        self.files.binary_search_by(|file| {
            if file.span.high < pos {
                Ordering::Less
            } else if file.span.low > pos {
                Ordering::Greater
            } else {
                Ordering::Equal
            }
        }).ok().map(|i| &self.files[i]).expect("Mapping unknown source location")
    }

    /// Gets the file, line, and column represented by a `Pos`.
    pub fn look_up_pos(&self, pos: Pos) -> Loc {
        let file = self.find_file(pos);
        let position = file.find_line_col(pos);
        Loc { file: file.clone(), position }
    }

    /// Gets the file and its line and column ranges represented by a `Span`.
    pub fn look_up_span(&self, span: Span) -> SpanLoc {
        let file = self.find_file(span.low);
        let begin = file.find_line_col(span.low);
        let end = file.find_line_col(span.high);
        SpanLoc { file: file.clone(), begin, end }
    }
}

/// A `CodeMap`'s record of a source file.
pub struct File {
    /// The span representing the entire file.
    pub span: Span,

    /// The filename as it would be displayed in an error message.
    name: String,

    /// Contents of the file.
    source: String,

    /// Byte positions of line beginnings.
    lines: Vec<Pos>,
}

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

    /// Gets the line number of a Pos.
    ///
    /// The lines are 0-indexed (first line is numbered 0)
    ///
    /// # Panics
    ///
    ///  * If `pos` is not within this file's span
    pub fn find_line(&self, pos: Pos) -> usize {
        assert!(pos >= self.span.low);
        assert!(pos <= self.span.high);
        (match self.lines.binary_search(&pos) {
            Ok(i) => i,
            Err(i) => i - 1,
        })
    }

    /// Gets the line and column of a Pos.
    ///
    /// # Panics
    ///
    /// * If `pos` is not with this file's span
    /// * If `pos` points to a byte in the middle of a UTF-8 character
    pub fn find_line_col(&self, pos: Pos) -> LineCol {
        let line = self.find_line(pos);
        let line_span = self.line_span(line);
        let byte_col = pos - line_span.low;
        let col = self.source_slice(line_span)[..byte_col as usize].chars().count();

        LineCol{ line: line, column: col }
    }

    /// Gets the full source text of the file
    pub fn source(&self) -> &str {
        &self.source
    }

    /// Gets the source text of a Span.
    ///
    /// # Panics
    ///
    ///   * If `span` is not entirely within this file.
    pub fn source_slice(&self, span: Span) -> &str {
        assert!(self.span.contains(span));
        &self.source[((span.low - self.span.low) as usize)..((span.high - self.span.low) as usize)]
    }

    /// Gets the span representing a line by line number.
    ///
    /// The line number is 0-indexed (first line is numbered 0). The returned span includes the
    /// line terminator.
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn line_span(&self, line: usize) -> Span {
        assert!(line < self.lines.len());
        Span {
            low: self.lines[line],
            high: *self.lines.get(line + 1).unwrap_or(&self.span.high)
        }
    }

    /// Gets the source text of a line.
    ///
    /// The string returned does not include the terminating \r or \n characters.
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn source_line(&self, line: usize) -> &str {
        self.source_slice(self.line_span(line)).trim_end_matches(&['\n', '\r'][..])
    }

    /// Gets the number of lines in the file
    pub fn num_lines(&self) -> usize {
        self.lines.len()
    }
}

impl fmt::Debug for File {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "File({:?})", self.name)
    }
}

impl PartialEq for File {
    /// Compares by identity
    fn eq(&self, other: &File) -> bool {
        self as *const _ == other as *const _
    }
}

impl Eq for File {}

impl Hash for File {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.span.hash(hasher);
    }
}

/// A line and column.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct LineCol {
    /// The line number within the file (0-indexed).
    pub line: usize,

    /// The column within the line (0-indexed).
    pub column: usize,
}

/// A file, and a line and column within it.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Loc {
    pub file: Arc<File>,
    pub position: LineCol,
}

impl fmt::Display for Loc {
    /// Formats the location as `filename:line:column`, with a 1-indexed
    /// line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}:{}:{}", self.file.name, self.position.line+1, self.position.column+1)
    }
}

/// A file, and a line and column range within it.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct SpanLoc {
    pub file: Arc<File>,
    pub begin: LineCol,
    pub end: LineCol,
}

impl fmt::Display for SpanLoc {
    /// Formats the span as `filename:start_line:start_column: end_line:end_column`,
    /// or if the span is zero-length, `filename:line:column`, with a 1-indexed line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.begin == self.end {
            write!(f, "{}:{}:{}", self.file.name, self.begin.line+1, self.begin.column+1)
        } else {
            write!(f, "{}:{}:{}: {}:{}", self.file.name, self.begin.line+1, self.begin.column+1, self.end.line+1, self.end.column+1)
        }
    }
}

#[test]
fn test_codemap() {
    let mut codemap = CodeMap::new();
    let f1 = codemap.add_file("test1.rs".to_string(), "abcd\nefghij\nqwerty".to_string());
    let f2 = codemap.add_file("test2.rs".to_string(), "foo\nbar".to_string());

    assert_eq!(codemap.find_file(f1.span.low()).name(), "test1.rs");
    assert_eq!(codemap.find_file(f1.span.high()).name(), "test1.rs");
    assert_eq!(codemap.find_file(f2.span.low()).name(), "test2.rs");
    assert_eq!(codemap.find_file(f2.span.high()).name(), "test2.rs");

    let x = f1.span.subspan(5, 10);
    let f = codemap.find_file(x.low);
    assert_eq!(f.name, "test1.rs");
    assert_eq!(f.find_line_col(f.span.low()), LineCol { line: 0, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 4), LineCol { line: 0, column: 4 });
    assert_eq!(f.find_line_col(f.span.low() + 5), LineCol { line: 1, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 16), LineCol { line: 2, column: 4 });

    let x = f2.span.subspan(4, 7);
    assert_eq!(codemap.find_file(x.low()).name(), "test2.rs");
    assert_eq!(codemap.find_file(x.high()).name(), "test2.rs");
}

#[test]
fn test_issue2() {
    let mut codemap = CodeMap::new();
    let content = "a \nxyz\r\n";
    let file = codemap.add_file("<test>".to_owned(), content.to_owned());

    let span = file.span.subspan(2, 3);
    assert_eq!(codemap.look_up_span(span), SpanLoc {
        file: file.clone(),
        begin: LineCol { line: 0, column: 2 },
        end: LineCol { line: 1, column: 0 }
    });

    assert_eq!(file.source_line(0), "a ");
    assert_eq!(file.source_line(1), "xyz");
    assert_eq!(file.source_line(2), "");
}

#[test]
fn test_multibyte() {
    let mut codemap = CodeMap::new();
    let content = "65°00′N 18°00′W 汉语\n🔬";
    let file = codemap.add_file("<test>".to_owned(), content.to_owned());

    assert_eq!(codemap.look_up_pos(file.span.low() + 21), Loc { file: file.clone(), position: LineCol { line: 0, column: 15 } });
    assert_eq!(codemap.look_up_pos(file.span.low() + 28), Loc { file: file.clone(), position: LineCol { line: 0, column: 18 } });
    assert_eq!(codemap.look_up_pos(file.span.low() + 33), Loc { file: file.clone(), position: LineCol { line: 1, column: 1 } });
}
<|endoftext|>


<commit_before>extern crate libc;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate gpg_error;
extern crate libgcrypt_sys as ffi;

use std::ffi::CString;
use std::mem;
use std::ptr;
use std::result;
use std::sync::{Mutex, MutexGuard};

pub use gpg_error as error;
pub use error::{Error, Result};
pub use buffer::Buffer;

#[macro_use]
mod utils;
mod buffer;
pub mod rand;
pub mod mpi;
pub mod sexp;
pub mod pkey;
pub mod cipher;
pub mod digest;
pub mod mac;
pub mod kdf;

lazy_static! {
    static ref CONTROL_LOCK: Mutex<()> = Mutex::new(());
}

pub struct Initializer {
    _lock: MutexGuard<'static, ()>,
}

impl Initializer {
    pub fn check_version<S: Into<String>>(&mut self, version: S) -> bool {
        let version = match CString::new(version.into()) {
            Ok(v) => v,
            Err(..) => return false,
        };
        unsafe {
            !ffi::gcry_check_version(version.as_ptr()).is_null()
        }
    }

    pub fn enable_quick_random(&mut self) -> &mut Self {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_ENABLE_QUICK_RANDOM, 0);
        }
        self
    }

    pub fn disable_secmem(&mut self) -> &mut Self {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_DISABLE_SECMEM, 0);
        }
        self
    }

    pub fn enable_secmem(&mut self, amt: usize) -> Result<&mut Self> {
        unsafe {
            return_err!(ffi::gcry_control(ffi::GCRYCTL_INIT_SECMEM, amt as libc::c_int));
        }
        Ok(self)
    }

    pub fn finish(self)  -> Token {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_INITIALIZATION_FINISHED, 0);
        }
        Token(0)
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Token(isize);

impl Token {
    pub fn is_fips_mode_active(&self) -> bool {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_FIPS_MODE_P, 0) != 0
        }
    }

    pub fn check_version<S: Into<String>>(&self, version: S) -> bool {
        let version = match CString::new(version.into()) {
            Ok(v) => v,
            Err(..) => return false,
        };
        unsafe {
            !ffi::gcry_check_version(version.as_ptr()).is_null()
        }
    }

    pub fn version(&self) -> &'static str {
        unsafe {
            utils::from_cstr(ffi::gcry_check_version(ptr::null())).unwrap()
        }
    }

    pub fn run_self_tests(&self) -> bool {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_SELFTEST, 0) == 0
        }
    }

    pub fn destroy_secmem(&self) {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_TERM_SECMEM, 0);
        }
    }
}

pub fn is_initialized() -> bool {
    unsafe {
        ffi::gcry_control(ffi::GCRYCTL_INITIALIZATION_FINISHED_P, 0) != 0
    }
}

pub fn init() -> result::Result<Initializer, Token> {
    let lock = CONTROL_LOCK.lock().unwrap();
    if !is_initialized() {
        unsafe {
            if cfg!(unix) {
                ffi::gcry_control(ffi::GCRYCTL_SET_THREAD_CBS, ffi::gcry_threads_pthread_shim());
            }
            ffi::gcry_check_version(ptr::null());
        }
        Ok(Initializer { _lock: lock })
    } else {
        Err(Token(0))
    }
}

pub unsafe trait Wrapper {
    type Raw: Copy;

    unsafe fn from_raw(raw: Self::Raw) -> Self;
    fn as_raw(&self) -> Self::Raw;
    fn into_raw(self) -> Self::Raw where Self: Sized {
        let raw = self.as_raw();
        mem::forget(self);
        raw
    }
}
<commit_msg>Add documentation on initialization<commit_after>//! ## Initialization
//! The library **must** be initialized using the [result](struct.Initializer.html)
//! from [``gcrypt::init``](fn.init.html) before
//! using any other function in the library or wrapper. More information on initialization
//! can be found in the libgcrypt
//! [documentation](https://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html#Initializing-the-library).
//!
//! An example:
//!
//! ```rust
//! let token = gcrypt::init().map(|mut x| {
//!     x.disable_secmem();
//!     x.finish()
//! }).unwrap_or_else(|x| x);
//! ```

extern crate libc;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate gpg_error;
extern crate libgcrypt_sys as ffi;

use std::ffi::CString;
use std::mem;
use std::ptr;
use std::result;
use std::sync::{Mutex, MutexGuard};

pub use gpg_error as error;
pub use error::{Error, Result};
pub use buffer::Buffer;

#[macro_use]
mod utils;
mod buffer;
pub mod rand;
pub mod mpi;
pub mod sexp;
pub mod pkey;
pub mod cipher;
pub mod digest;
pub mod mac;
pub mod kdf;

lazy_static! {
    static ref CONTROL_LOCK: Mutex<()> = Mutex::new(());
}

pub struct Initializer {
    _lock: MutexGuard<'static, ()>,
}

impl Initializer {
    pub fn check_version<S: Into<String>>(&mut self, version: S) -> bool {
        let version = match CString::new(version.into()) {
            Ok(v) => v,
            Err(..) => return false,
        };
        unsafe {
            !ffi::gcry_check_version(version.as_ptr()).is_null()
        }
    }

    pub fn enable_quick_random(&mut self) -> &mut Self {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_ENABLE_QUICK_RANDOM, 0);
        }
        self
    }

    pub fn disable_secmem(&mut self) -> &mut Self {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_DISABLE_SECMEM, 0);
        }
        self
    }

    pub fn enable_secmem(&mut self, amt: usize) -> Result<&mut Self> {
        unsafe {
            return_err!(ffi::gcry_control(ffi::GCRYCTL_INIT_SECMEM, amt as libc::c_int));
        }
        Ok(self)
    }

    pub fn finish(self)  -> Token {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_INITIALIZATION_FINISHED, 0);
        }
        Token(0)
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Token(isize);

impl Token {
    pub fn is_fips_mode_active(&self) -> bool {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_FIPS_MODE_P, 0) != 0
        }
    }

    pub fn check_version<S: Into<String>>(&self, version: S) -> bool {
        let version = match CString::new(version.into()) {
            Ok(v) => v,
            Err(..) => return false,
        };
        unsafe {
            !ffi::gcry_check_version(version.as_ptr()).is_null()
        }
    }

    pub fn version(&self) -> &'static str {
        unsafe {
            utils::from_cstr(ffi::gcry_check_version(ptr::null())).unwrap()
        }
    }

    pub fn run_self_tests(&self) -> bool {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_SELFTEST, 0) == 0
        }
    }

    pub fn destroy_secmem(&self) {
        unsafe {
            ffi::gcry_control(ffi::GCRYCTL_TERM_SECMEM, 0);
        }
    }
}

pub fn is_initialized() -> bool {
    unsafe {
        ffi::gcry_control(ffi::GCRYCTL_INITIALIZATION_FINISHED_P, 0) != 0
    }
}

pub fn init() -> result::Result<Initializer, Token> {
    let lock = CONTROL_LOCK.lock().unwrap();
    if !is_initialized() {
        unsafe {
            if cfg!(unix) {
                ffi::gcry_control(ffi::GCRYCTL_SET_THREAD_CBS, ffi::gcry_threads_pthread_shim());
            }
            ffi::gcry_check_version(ptr::null());
        }
        Ok(Initializer { _lock: lock })
    } else {
        Err(Token(0))
    }
}

pub unsafe trait Wrapper {
    type Raw: Copy;

    unsafe fn from_raw(raw: Self::Raw) -> Self;
    fn as_raw(&self) -> Self::Raw;
    fn into_raw(self) -> Self::Raw where Self: Sized {
        let raw = self.as_raw();
        mem::forget(self);
        raw
    }
}
<|endoftext|>


<commit_before>#![warn(missing_docs)]

//! A `Pinboard` is a shared, mutable, eventually consistent, lock-free data-structure.  This
//! allows multiple threads to communicate in a decoupled way by publishing data to the pinboard
//! which other threads can then read in an eventually consistent way.
//!
//! This is not a silver bullet though, there are various limitations of `Pinboard` that trade off
//! the nice behaviour described above.
//!
//! * Eventual consistency:
//!     * Writes from one thread are not guaranteed to be seen by reads from another thread
//!     * Writes from one thread can overwrite writes from another thread
//! * No in-place mutation:
//!     * The only write primitive completely overwrites the data on the `Pinboard`
//! * Requires `Clone`:
//!     * All reads return a clone of the data, decoupling the lifetime of the read value from the
//!     data stored in the global reference.

extern crate crossbeam;

use crossbeam::epoch::{Atomic, Owned, pin};
use std::sync::atomic::Ordering::*;

use std::ops::Deref;

/// An instance of a `Pinboard`, holds a shared, mutable, eventually-consistent reference to a `T`.
pub struct Pinboard<T: Clone>(Atomic<T>);

impl<T: Clone> Pinboard<T> {
    /// Create a new `Pinboard` instance holding the given value.
    pub fn new(t: T) -> Pinboard<T> {
        let t = Owned::new(t);
        let p = Pinboard::default();
        p.0.store(Some(t), Release);
        p
    }

    /// Update the value stored in the `Pinboard`.
    pub fn set(&self, t: T) {
        let guard = pin();
        let t = Owned::new(t);
        if let Some(t) = self.0.swap(Some(t), Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Clear out the `Pinboard` so its no longer holding any data.
    pub fn clear(&self) {
        let guard = pin();
        if let Some(t) = self.0.swap(None, Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    pub fn read(&self) -> Option<T> {
        let guard = pin();
        let t = self.0.load(Acquire, &guard);
        t.map(|t| -> &T { t.deref() }).cloned()
    }
}

impl<T: Clone> Default for Pinboard<T> {
    fn default() -> Pinboard<T> {
        Pinboard(Atomic::null())
    }
}

impl<T: Clone> Drop for Pinboard<T> {
    fn drop(&mut self) {
        // Make sure any stored data is marked for deletion
        self.clear();
    }
}

impl<T: Clone> From<Option<T>> for Pinboard<T> {
    fn from(src: Option<T>) -> Pinboard<T> {
        src.map(Pinboard::new).unwrap_or_default()
    }
}

/// An wrapper around a `Pinboard` which provides the guarantee it is never empty.
pub struct NonEmptyPinboard<T: Clone>(Pinboard<T>);

impl<T: Clone> NonEmptyPinboard<T> {
    /// Create a new `NonEmptyPinboard` instance holding the given value.
    pub fn new(t: T) -> NonEmptyPinboard<T> {
        NonEmptyPinboard(Pinboard::new(t))
    }

    /// Update the value stored in the `NonEmptyPinboard`.
    #[inline]
    pub fn set(&self, t: T) {
        self.0.set(t)
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    #[inline]
    pub fn read(&self) -> T {
        // Unwrap the option returned by the inner `Pinboard`. This will never panic, because it's
        // impossible for this `Pinboard` to be empty (though it's not possible to prove this to the
        // compiler).
        match self.0.read() {
            Some(t) => t,
            None => unreachable!("Inner pointer was unexpectedly null"),
        }
    }
}

macro_rules! debuggable {
    ($struct:ident, $trait:ident) => {
        impl<T: Clone> ::std::fmt::$trait for $struct<T> where T: ::std::fmt::$trait {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                write!(f, "{}(", stringify!($struct))?;
                ::std::fmt::$trait::fmt(&self.read(), f)?;
                write!(f, ")")
            }
        }
    }
}

debuggable!(Pinboard, Debug);
debuggable!(NonEmptyPinboard, Debug);
debuggable!(NonEmptyPinboard, Binary);
debuggable!(NonEmptyPinboard, Display);
debuggable!(NonEmptyPinboard, LowerExp);
debuggable!(NonEmptyPinboard, LowerHex);
debuggable!(NonEmptyPinboard, Octal);
debuggable!(NonEmptyPinboard, Pointer);
debuggable!(NonEmptyPinboard, UpperExp);
debuggable!(NonEmptyPinboard, UpperHex);

#[cfg(test)]
mod tests {
    use super::*;
    use std::fmt::Display;

    fn consume<T: Clone + Display>(t: &Pinboard<T>) {
        loop {
            match t.read() {
                Some(_) => {}
                None => break,
            }
            std::thread::sleep(std::time::Duration::from_millis(1));
        }
    }

    fn produce(t: &Pinboard<u32>) {
        for i in 1..100 {
            t.set(i);
            std::thread::sleep(std::time::Duration::from_millis(2));
        }
        t.clear();
    }

    fn check_debug<T: ::std::fmt::Debug>(_: T) {}

    #[test]
    fn it_works() {
        let t = Pinboard::<u32>::default();
        assert_eq!(None, t.read());
        t.set(3);
        assert_eq!(Some(3), t.read());
        t.clear();
        assert_eq!(None, t.read());
    }

    #[test]
    fn single_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn multi_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn single_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn multi_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn non_empty_pinboard() {
        let t = NonEmptyPinboard::<u32>::new(3);
        assert_eq!(3, t.read());
        t.set(4);
        assert_eq!(4, t.read());
    }

    #[test]
    fn debuggable() {
        let t = Pinboard::<i32>::new(3);
        check_debug(t);
        let t = NonEmptyPinboard::<i32>::new(2);
        check_debug(t);
    }
}
<commit_msg>Formatting<commit_after>#![warn(missing_docs)]

//! A `Pinboard` is a shared, mutable, eventually consistent, lock-free data-structure.  This
//! allows multiple threads to communicate in a decoupled way by publishing data to the pinboard
//! which other threads can then read in an eventually consistent way.
//!
//! This is not a silver bullet though, there are various limitations of `Pinboard` that trade off
//! the nice behaviour described above.
//!
//! * Eventual consistency:
//!     * Writes from one thread are not guaranteed to be seen by reads from another thread
//!     * Writes from one thread can overwrite writes from another thread
//! * No in-place mutation:
//!     * The only write primitive completely overwrites the data on the `Pinboard`
//! * Requires `Clone`:
//!     * All reads return a clone of the data, decoupling the lifetime of the read value from the
//!     data stored in the global reference.

extern crate crossbeam;

use crossbeam::epoch::{Atomic, Owned, pin};
use std::sync::atomic::Ordering::*;

use std::ops::Deref;

/// An instance of a `Pinboard`, holds a shared, mutable, eventually-consistent reference to a `T`.
pub struct Pinboard<T: Clone>(Atomic<T>);

impl<T: Clone> Pinboard<T> {
    /// Create a new `Pinboard` instance holding the given value.
    pub fn new(t: T) -> Pinboard<T> {
        let t = Owned::new(t);
        let p = Pinboard::default();
        p.0.store(Some(t), Release);
        p
    }

    /// Update the value stored in the `Pinboard`.
    pub fn set(&self, t: T) {
        let guard = pin();
        let t = Owned::new(t);
        if let Some(t) = self.0.swap(Some(t), Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Clear out the `Pinboard` so its no longer holding any data.
    pub fn clear(&self) {
        let guard = pin();
        if let Some(t) = self.0.swap(None, Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    pub fn read(&self) -> Option<T> {
        let guard = pin();
        let t = self.0.load(Acquire, &guard);
        t.map(|t| -> &T { t.deref() }).cloned()
    }
}

impl<T: Clone> Default for Pinboard<T> {
    fn default() -> Pinboard<T> {
        Pinboard(Atomic::null())
    }
}

impl<T: Clone> Drop for Pinboard<T> {
    fn drop(&mut self) {
        // Make sure any stored data is marked for deletion
        self.clear();
    }
}

impl<T: Clone> From<Option<T>> for Pinboard<T> {
    fn from(src: Option<T>) -> Pinboard<T> {
        src.map(Pinboard::new).unwrap_or_default()
    }
}

/// An wrapper around a `Pinboard` which provides the guarantee it is never empty.
pub struct NonEmptyPinboard<T: Clone>(Pinboard<T>);

impl<T: Clone> NonEmptyPinboard<T> {
    /// Create a new `NonEmptyPinboard` instance holding the given value.
    pub fn new(t: T) -> NonEmptyPinboard<T> {
        NonEmptyPinboard(Pinboard::new(t))
    }

    /// Update the value stored in the `NonEmptyPinboard`.
    #[inline]
    pub fn set(&self, t: T) {
        self.0.set(t)
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    #[inline]
    pub fn read(&self) -> T {
        // Unwrap the option returned by the inner `Pinboard`. This will never panic, because it's
        // impossible for this `Pinboard` to be empty (though it's not possible to prove this to the
        // compiler).
        match self.0.read() {
            Some(t) => t,
            None => unreachable!("Inner pointer was unexpectedly null"),
        }
    }
}

macro_rules! debuggable {
    ($struct:ident, $trait:ident) => {
        impl<T: Clone> ::std::fmt::$trait for $struct<T> where T: ::std::fmt::$trait {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                write!(f, "{}(", stringify!($struct))?;
                ::std::fmt::$trait::fmt(&self.read(), f)?;
                write!(f, ")")
            }
        }
    }
}

debuggable!(Pinboard, Debug);
debuggable!(NonEmptyPinboard, Debug);
debuggable!(NonEmptyPinboard, Binary);
debuggable!(NonEmptyPinboard, Display);
debuggable!(NonEmptyPinboard, LowerExp);
debuggable!(NonEmptyPinboard, LowerHex);
debuggable!(NonEmptyPinboard, Octal);
debuggable!(NonEmptyPinboard, Pointer);
debuggable!(NonEmptyPinboard, UpperExp);
debuggable!(NonEmptyPinboard, UpperHex);

#[cfg(test)]
mod tests {
    use super::*;
    use std::fmt::Display;

    fn consume<T: Clone + Display>(t: &Pinboard<T>) {
        loop {
            match t.read() {
                Some(_) => {}
                None => break,
            }
            std::thread::sleep(std::time::Duration::from_millis(1));
        }
    }

    fn produce(t: &Pinboard<u32>) {
        for i in 1..100 {
            t.set(i);
            std::thread::sleep(std::time::Duration::from_millis(2));
        }
        t.clear();
    }

    fn check_debug<T: ::std::fmt::Debug>(_: T) {}

    #[test]
    fn it_works() {
        let t = Pinboard::<u32>::default();
        assert_eq!(None, t.read());
        t.set(3);
        assert_eq!(Some(3), t.read());
        t.clear();
        assert_eq!(None, t.read());
    }

    #[test]
    fn single_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn multi_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn single_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn multi_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| produce(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
            scope.spawn(|| consume(&t));
        })
    }

    #[test]
    fn non_empty_pinboard() {
        let t = NonEmptyPinboard::<u32>::new(3);
        assert_eq!(3, t.read());
        t.set(4);
        assert_eq!(4, t.read());
    }

    #[test]
    fn debuggable() {
        let t = Pinboard::<i32>::new(3);
        check_debug(t);
        let t = NonEmptyPinboard::<i32>::new(2);
        check_debug(t);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
extern crate "rblas" as blas;
extern crate num;

mod default;

pub mod vec;
pub mod mat;

pub enum Trans<Tensor> {
	T(Tensor),
	H(Tensor),
}

impl<T> Trans<T> {
    pub fn into_inner(&self) -> &T {
        match self {
            &Trans::T(ref t) => t,
            &Trans::H(ref t) => t,
        }
    }
}
<commit_msg>Fix use identifier<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
extern crate rblas as blas;
extern crate num;

mod default;

pub mod vec;
pub mod mat;

pub enum Trans<Tensor> {
	T(Tensor),
	H(Tensor),
}

impl<T> Trans<T> {
    pub fn into_inner(&self) -> &T {
        match self {
            &Trans::T(ref t) => t,
            &Trans::H(ref t) => t,
        }
    }
}
<|endoftext|>


<commit_before>#![feature(vec_push_all)]

extern crate unicode_segmentation;
use unicode_segmentation::UnicodeSegmentation;

use std::rc::Rc;

// const SPLIT_LEN: usize = 10;
// const JOIN_LEN: usize = 5;
// const REBALANCE_RATIO: f32 = 1.2;

pub enum Rope {
    Leaf { base: Rc<String>,
           start: usize,
           end: usize,
           graphemes: usize },
    Concat { left: Rc<Rope>,
             right: Rc<Rope>,
             graphemes: usize },
}
impl Rope {
    /// Create a new rope leaf
    pub fn from_str(base: &str) -> Rope {
        let num_graphemes = count_grapheme_clusters(base);
        Rope::Leaf { base: Rc::new(String::from(base)),
                     start: 0,
                     end: base.len(),
                     graphemes: num_graphemes }
    }
    /// Gets the number of Unicode grapheme clusters in the children of this node
    pub fn num_graphemes(&self) -> usize {
        match *self {
            Rope::Leaf { graphemes, .. } => graphemes,
            Rope::Concat { graphemes, .. } => graphemes,
        }
    }
    /// Split a Rope after the nth grapheme
    pub fn split(&self, grapheme_index: usize) -> Option<(Rope, Rope)> {
        match *self {
            Rope::Leaf { ref base, start, end, .. } => {
                grapheme_byte_index(&base[start..end], grapheme_index)
                    .map(|byte_index| {
                        let left = Rope::Leaf { base: base.clone(),
                                                start: start,
                                                end: start+byte_index,
                                                graphemes: count_grapheme_clusters(&base[start..start+byte_index]) };
                        let right = Rope::Leaf { base: base.clone(),
                                                 start: start+byte_index,
                                                 end: end,
                                                 graphemes: count_grapheme_clusters(&base[start+byte_index..end]) };
                        (left, right)
                    })
            },
            Rope::Concat{ ref left, ref right, .. } => {
                // self is (left, right)
                if left.num_graphemes() >= grapheme_index {
                    // split left into (l1, l2), return (l1, concat(l2, right))
                    left.split(grapheme_index).map(|(l1, l2)| {
                        (l1, Rope::Concat { left: Rc::new(l2.clone()),
                                            right: right.clone(),
                                            graphemes: l2.num_graphemes() + right.num_graphemes() })
                    })
                } else {
                    // split right into (r1, r2), return (concat(left, r1), r2)
                    right.split(grapheme_index - left.num_graphemes()).map(|(r1, r2)| {
                        (Rope::Concat { left: left.clone(),
                                        right: Rc::new(r1.clone()),
                                        graphemes: left.num_graphemes() + r1.num_graphemes() },
                         r2)
                    })
                }
            }
        }
    }
    /// Collect the pieces of this Rope into a continuous String
    pub fn to_string(&self) -> String {
        let mut buf = String::with_capacity(self.num_graphemes());

        fn str_parts<'a>(root: &'a Rope) -> Vec<&'a str> {
            let mut v = vec![];
            match *root {
                Rope::Leaf { ref base, start, end, .. } => {
                    v.push( &base[start..end] );
                },
                Rope::Concat { ref left, ref right, .. } => {
                    v.push_all(&str_parts(&left));
                    v.push_all(&str_parts(&right));
                },
            }
            v
        }
        for part in str_parts(self).iter() {
            buf.push_str(part);
        }

        buf
    }
    /// Join two pieces into a Rope
    pub fn join(left: Rope, right: Rope) -> Rope {
        let graphemes = left.num_graphemes() + right.num_graphemes();
        Rope::Concat { left: Rc::new(left),
                       right: Rc::new(right),
                       graphemes: graphemes }
    }
    /// Insert a string into a Rope by splitting and joining nodes
    /// Returns a new Rope, leaving the original unchanged
    pub fn insert(&self, grapheme_index: usize, value: &str) -> Option<Rope> {
        self.split(grapheme_index).map(|(left, right)| {
            let left = Rope::join(left, Rope::from_str(value));
            Rope::join(left, right)
        })
    }
    /// Append a string to the Rope, returning a new instance and leaving the original unchanged
    pub fn append(&self, value: &str) -> Rope {
        Rope::join(self.clone(), Rope::from_str(value))
    }
    /// Remove a substring range from the Rope
    pub fn delete(&self, start_grapheme: usize, num_graphemes: usize) -> Option<Rope> {
        self.split(start_grapheme).map(|(head, middle)| {
            middle.split(num_graphemes).map(|(_, tail)| {
                Rope::join(head.clone(), tail.clone())
            })
        }).unwrap()
    }
}
impl Clone for Rope {
    fn clone(&self) -> Rope {
        match *self {
            Rope::Leaf { ref base, start, end, graphemes } => Rope::Leaf { base: base.clone(),
                                                                           start: start,
                                                                           end: end,
                                                                           graphemes: graphemes },
            Rope::Concat { ref left, ref right, graphemes } => Rope::Concat { left: left.clone(),
                                                                              right: right.clone(),
                                                                              graphemes: graphemes },
        }
    }
}
/// Count the number of unicode extended grapheme clusters in a string
/// This is O(n)
fn count_grapheme_clusters(s: &str) -> usize {
    UnicodeSegmentation::graphemes(s, true).collect::<Vec<&str>>().len()
}

/// Find the byte index of the nth grapheme cluster in a string
/// Returns None if the grapheme index is out of bounds
fn grapheme_byte_index(base: &str, nth_grapheme: usize) -> Option<usize> {
    UnicodeSegmentation::grapheme_indices(base, true)
        .nth(nth_grapheme).map(|(i, _)| i)
}

#[cfg(test)]
fn to_string_debug(root: &Rope) -> String {
    let mut buf = String::with_capacity(root.num_graphemes());

    fn str_parts<'a>(root: &'a Rope) -> Vec<&'a str> {
        let mut v = vec![];
        match *root {
            Rope::Leaf { ref base, start, end, .. } => {
                v.push( "<" );
                v.push( &base[start..end] );
                v.push( ">" );
            },
            Rope::Concat { ref left, ref right, .. } => {
                v.push( "(" );
                v.push_all(&str_parts(&left));
                v.push( "," );
                v.push_all(&str_parts(&right));
                v.push( ")" );
            },
        }
        v
    }
    for part in str_parts(root).iter() {
        buf.push_str(part);
    }

    buf
}

#[test]
fn test_count_grapheme_clusters() {
    // 11 bytes, 3 grapheme clusters
    let s = "a̐éö̲";
    assert_eq!(s.len(), 11);
    assert_eq!(count_grapheme_clusters(s), 3);
}

#[test]
fn test_create_leaf() {
    let leaf = Rope::from_str("a̐éö̲");
    assert_eq!(leaf.num_graphemes(), 3);
}

#[test]
fn test_split_leaf() {
    let leaf = Rope::from_str("a̐éö̲a̐éö̲");
    let (left, right) = leaf.split(3).unwrap();
    assert_eq!(left.num_graphemes(), right.num_graphemes());
    assert_eq!(left.to_string(), "a̐éö̲");
}

#[test]
fn test_create_rope() {
    let rope = Rope::from_str("The quick brown fox jumps over the lazy dog.");
    assert_eq!(rope.num_graphemes(), 44);
    assert_eq!(rope.to_string(), "The quick brown fox jumps over the lazy dog.");
}

#[test]
fn test_rope_operations() {
    let rope = Rope::from_str("The quick brown fox jumps over the lazy dog.");

    let (left, right) = rope.split(22).unwrap();
    assert_eq!(left.to_string(), "The quick brown fox ju");
    assert_eq!(right.to_string(), "mps over the lazy dog.");

    let rope2 = Rope::join(left, Rope::from_str("mps over the tiny wooden fence!"));
    assert_eq!(rope2.to_string(), "The quick brown fox jumps over the tiny wooden fence!");

    let rope3 = rope2.insert(10, "(and really very clever) ").unwrap();
    assert_eq!(rope3.to_string(), "The quick (and really very clever) brown fox jumps over the tiny wooden fence!");

    let rope4 = rope2.append(" One fish two fish, red fish blue fish.");
    assert_eq!(rope4.to_string(), "The quick brown fox jumps over the tiny wooden fence! One fish two fish, red fish blue fish.");

    let rope5 = rope4.delete(4, 6).expect("a").delete(14, 6).expect("b").insert(13, " hops").expect("c");

    println!("{}\n{}\n", rope.to_string(), to_string_debug(&rope));
    println!("{}\n{}\n", rope2.to_string(), to_string_debug(&rope2));
    println!("{}\n{}\n", rope3.to_string(), to_string_debug(&rope3));
    println!("{}\n{}\n", rope4.to_string(), to_string_debug(&rope4));
    println!("{}\n{}\n", rope5.to_string(), to_string_debug(&rope5));
}
<commit_msg>Fix splitting concat nodes on existing boundary<commit_after>#![feature(vec_push_all)]

extern crate unicode_segmentation;
use unicode_segmentation::UnicodeSegmentation;

use std::rc::Rc;

// const SPLIT_LEN: usize = 10;
// const JOIN_LEN: usize = 5;
// const REBALANCE_RATIO: f32 = 1.2;

pub enum Rope {
    Leaf { base: Rc<String>,
           start: usize,
           end: usize,
           graphemes: usize },
    Concat { left: Box<Rope>,
             right: Box<Rope>,
             graphemes: usize },
}
impl Rope {
    /// Create a new rope leaf
    pub fn from_str(base: &str) -> Rope {
        let num_graphemes = count_grapheme_clusters(base);
        Rope::Leaf { base: Rc::new(String::from(base)),
                     start: 0,
                     end: base.len(),
                     graphemes: num_graphemes }
    }
    /// Gets the number of Unicode grapheme clusters in the children of this node
    pub fn num_graphemes(&self) -> usize {
        match *self {
            Rope::Leaf { graphemes, .. } => graphemes,
            Rope::Concat { graphemes, .. } => graphemes,
        }
    }
    /// Split a Rope after the nth grapheme
    /// Returns None if grapheme index is 0 or out of bounds
    pub fn split(&self, grapheme_index: usize) -> Option<(Rope, Rope)> {
        if grapheme_index == 0 { return None };
        match *self {
            Rope::Leaf { ref base, start, end, .. } => {
                grapheme_byte_index(&base[start..end], grapheme_index)
                    .map(|byte_index| {
                        let left = Rope::Leaf { base: base.clone(),
                                                start: start,
                                                end: start+byte_index,
                                                graphemes: count_grapheme_clusters(&base[start..start+byte_index]) };
                        let right = Rope::Leaf { base: base.clone(),
                                                 start: start+byte_index,
                                                 end: end,
                                                 graphemes: count_grapheme_clusters(&base[start+byte_index..end]) };
                        (left, right)
                    })
            },
            Rope::Concat{ ref left, ref right, .. } => {
                // self is (left, right)
                let left_graphemes = left.num_graphemes();
                if left_graphemes == grapheme_index {
                    Some((*left.clone(), *right.clone()))
                } else if left_graphemes > grapheme_index {
                    // split left into (l1, l2), return (l1, concat(l2, right))
                    left.split(grapheme_index).map(|(l1, l2)| {
                        (l1, Rope::Concat { left: Box::new(l2.clone()),
                                            right: right.clone(),
                                            graphemes: l2.num_graphemes() + right.num_graphemes() })
                    })
                } else {
                    // split right into (r1, r2), return (concat(left, r1), r2)
                    right.split(grapheme_index - left_graphemes).map(|(r1, r2)| {
                        (Rope::Concat { left: left.clone(),
                                        right: Box::new(r1.clone()),
                                        graphemes: left_graphemes + r1.num_graphemes() },
                         r2)
                    })
                }
            }
        }
    }
    /// Collect the pieces of this Rope into a continuous String
    pub fn to_string(&self) -> String {
        let mut buf = String::with_capacity(self.num_graphemes());

        fn str_parts<'a>(root: &'a Rope) -> Vec<&'a str> {
            let mut v = vec![];
            match *root {
                Rope::Leaf { ref base, start, end, .. } => {
                    v.push( &base[start..end] );
                },
                Rope::Concat { ref left, ref right, .. } => {
                    v.push_all(&str_parts(&left));
                    v.push_all(&str_parts(&right));
                },
            }
            v
        }
        for part in str_parts(self).iter() {
            buf.push_str(part);
        }

        buf
    }
    /// Join two pieces into a Rope
    pub fn join(left: Rope, right: Rope) -> Rope {
        let graphemes = left.num_graphemes() + right.num_graphemes();
        Rope::Concat { left: Box::new(left),
                       right: Box::new(right),
                       graphemes: graphemes }
    }
    /// Insert a string into a Rope by splitting and joining nodes
    /// Returns a new Rope, leaving the original unchanged
    pub fn insert(&self, grapheme_index: usize, value: &str) -> Option<Rope> {
        self.split(grapheme_index).map(|(left, right)| {
            let left = Rope::join(left, Rope::from_str(value));
            Rope::join(left, right)
        })
    }
    /// Append a string to the Rope, returning a new instance and leaving the original unchanged
    pub fn append(&self, value: &str) -> Rope {
        Rope::join(self.clone(), Rope::from_str(value))
    }
    /// Remove a substring range from the Rope
    pub fn delete(&self, start_grapheme: usize, num_graphemes: usize) -> Option<Rope> {
        self.split(start_grapheme).map(|(head, middle)| {
            middle.split(num_graphemes).map(|(_, tail)| {
                Rope::join(head.clone(), tail.clone())
            })
        }).unwrap()
    }
}
impl Clone for Rope {
    fn clone(&self) -> Rope {
        match *self {
            Rope::Leaf { ref base, start, end, graphemes } => Rope::Leaf { base: base.clone(),
                                                                           start: start,
                                                                           end: end,
                                                                           graphemes: graphemes },
            Rope::Concat { ref left, ref right, graphemes } => Rope::Concat { left: left.clone(),
                                                                              right: right.clone(),
                                                                              graphemes: graphemes },
        }
    }
}
/// Count the number of unicode extended grapheme clusters in a string
/// This is O(n)
fn count_grapheme_clusters(s: &str) -> usize {
    UnicodeSegmentation::graphemes(s, true).collect::<Vec<&str>>().len()
}

/// Find the byte index of the nth grapheme cluster in a string
/// Returns None if the grapheme index is out of bounds
fn grapheme_byte_index(base: &str, nth_grapheme: usize) -> Option<usize> {
    UnicodeSegmentation::grapheme_indices(base, true)
        .nth(nth_grapheme).map(|(i, _)| i)
}

#[cfg(test)]
fn to_string_debug(root: &Rope) -> String {
    let mut buf = String::with_capacity(root.num_graphemes());

    fn str_parts<'a>(root: &'a Rope) -> Vec<&'a str> {
        let mut v = vec![];
        match *root {
            Rope::Leaf { ref base, start, end, .. } => {
                v.push( "<" );
                v.push( &base[start..end] );
                v.push( ">" );
            },
            Rope::Concat { ref left, ref right, .. } => {
                v.push( "(" );
                v.push_all(&str_parts(&left));
                v.push( "," );
                v.push_all(&str_parts(&right));
                v.push( ")" );
            },
        }
        v
    }
    for part in str_parts(root).iter() {
        buf.push_str(part);
    }

    buf
}

#[test]
fn test_count_grapheme_clusters() {
    // 11 bytes, 3 grapheme clusters
    let s = "a̐éö̲";
    assert_eq!(s.len(), 11);
    assert_eq!(count_grapheme_clusters(s), 3);
}

#[test]
fn test_create_leaf() {
    let leaf = Rope::from_str("a̐éö̲");
    assert_eq!(leaf.num_graphemes(), 3);
}

#[test]
fn test_split_leaf() {
    let leaf = Rope::from_str("a̐éö̲a̐éö̲");
    let (left, right) = leaf.split(3).unwrap();
    assert_eq!(left.num_graphemes(), right.num_graphemes());
    assert_eq!(left.to_string(), "a̐éö̲");
}

#[test]
fn test_create_rope() {
    let rope = Rope::from_str("The quick brown fox jumps over the lazy dog.");
    assert_eq!(rope.num_graphemes(), 44);
    assert_eq!(rope.to_string(), "The quick brown fox jumps over the lazy dog.");
}

#[test]
fn test_split_end() {
    let rope = Rope::from_str("abc");
    assert!(rope.split(3).is_none());
}

#[test]
fn test_split_start() {
    let rope = Rope::from_str("abc");
    assert!(rope.split(0).is_none());
}

#[test]
fn test_fraying() {
    let (a, b) = Rope::from_str("foo bar baz").split(4).expect("first split");
    let c = Rope::join(a, b);
    assert_eq!(c.to_string(), "foo bar baz");

    let (d, e) = c.split(4).expect("second split");
    let f = Rope::join(d, e);
    assert_eq!(f.to_string(), "foo bar baz");
}

#[test]
fn test_rope_operations() {
    let rope = Rope::from_str("The quick brown fox jumps over the lazy dog.");

    let (left, right) = rope.split(22).unwrap();
    assert_eq!(left.to_string(), "The quick brown fox ju");
    assert_eq!(right.to_string(), "mps over the lazy dog.");

    let rope2 = Rope::join(left, Rope::from_str("mps over the tiny wooden fence!"));
    assert_eq!(rope2.to_string(), "The quick brown fox jumps over the tiny wooden fence!");

    let rope3 = rope2.insert(10, "(and really very clever) ").unwrap();
    assert_eq!(rope3.to_string(), "The quick (and really very clever) brown fox jumps over the tiny wooden fence!");

    let rope4 = rope2.append(" One fish two fish, red fish blue fish.");
    assert_eq!(rope4.to_string(), "The quick brown fox jumps over the tiny wooden fence! One fish two fish, red fish blue fish.");

    let rope5 = rope4.delete(4, 6).expect("a").delete(14, 6).expect("b").insert(13, " hops").expect("c");

    println!("{}\n{}\n", rope.to_string(), to_string_debug(&rope));
    println!("{}\n{}\n", rope2.to_string(), to_string_debug(&rope2));
    println!("{}\n{}\n", rope3.to_string(), to_string_debug(&rope3));
    println!("{}\n{}\n", rope4.to_string(), to_string_debug(&rope4));
    println!("{}\n{}\n", rope5.to_string(), to_string_debug(&rope5));
}
<|endoftext|>


<commit_before>#![crate_id = "router"]
#![license = "MIT"]
//#![deny(missing_doc)]
#![deny(unused_result, unused_result, unnecessary_qualification,
        non_camel_case_types, unused_variable, unnecessary_typecast)]
#![feature(phase, globs)]

extern crate http;
extern crate iron;
extern crate regex;
#[phase(plugin, link)] extern crate log;
#[phase(plugin)] extern crate regex_macros;

#[cfg(test)] extern crate test;

pub use router::Router;
pub use router::params::Params;

mod router;

<commit_msg>(doc) Documented crate.<commit_after>#![crate_id = "router"]
#![license = "MIT"]
#![deny(missing_doc)]
#![deny(unused_result, unused_result, unnecessary_qualification,
        non_camel_case_types, unused_variable, unnecessary_typecast)]
#![feature(phase, globs)]

//! Router provides a fast router middleware for the Iron web framework.

extern crate http;
extern crate iron;
extern crate regex;
#[phase(plugin, link)] extern crate log;
#[phase(plugin)] extern crate regex_macros;

#[cfg(test)] extern crate test;

pub use router::Router;
pub use router::params::Params;

mod router;

<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(asm)]
#![feature(const_fn)]
#![feature(lang_items)]

#![feature(alloc)]
#![allow(unknown_lints)]
#![no_std]

extern crate alloc;
#[cfg(not(test))]
extern crate allocator;
extern crate spin;
#[macro_use]
extern crate collections;

#[macro_use]
pub mod linux;

pub mod cli;
pub mod dispatch_table;
pub mod gdt;
pub mod hash_map;
pub mod runtime;
pub mod vmx;

#[no_mangle]
pub extern "C" fn entry(_heap: *mut u8, _heap_size: u64, _: *mut u8, _: u64) -> u32 {
    unsafe {
        linux::printk(cstring!("Hello Linux!\n"));
    }

    #[cfg(feature = "runtime_tests")]
    runtime_tests();

    #[cfg(not(test))]
    allocator::init_global_allocator(_heap_size, _heap);
    0
}

#[cfg(feature = "runtime_tests")]
fn runtime_tests() {
    gdt::runtime_tests::test_load();
}
<commit_msg>Use lazy static crate<commit_after>#![feature(collections)]
#![feature(asm)]
#![feature(const_fn)]
#![feature(lang_items)]

#![feature(alloc)]
#![allow(unknown_lints)]
#![no_std]

extern crate alloc;
#[cfg(not(test))]
extern crate allocator;
extern crate spin;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate collections;

#[macro_use]
pub mod linux;

pub mod cli;
pub mod dispatch_table;
pub mod gdt;
pub mod hash_map;
pub mod runtime;
pub mod vmx;

#[no_mangle]
pub extern "C" fn entry(_heap: *mut u8, _heap_size: u64, _: *mut u8, _: u64) -> u32 {
    unsafe {
        linux::printk(cstring!("Hello Linux!\n"));
    }

    #[cfg(feature = "runtime_tests")]
    runtime_tests();

    #[cfg(not(test))]
    allocator::init_global_allocator(_heap_size, _heap);
    0
}

#[cfg(feature = "runtime_tests")]
fn runtime_tests() {
    gdt::runtime_tests::test_load();
}
<|endoftext|>


<commit_before>extern crate libinspire;

/// Re-export slog
///
/// Users of this library can, but don't have to use slog to build their own loggers
#[macro_use]
pub extern crate slog ;
extern crate slog_stdlog;

use slog::DrainExt;

extern crate regex;
use regex::Regex;

pub struct Inspirer {
    logger: slog::Logger,
    pub inspire: libinspire::Api,
}

#[derive(Debug,PartialEq)]
pub enum Sources<'a> {
    Inspire(libinspire::RecID<'a>),
    Ads,
    Arxiv,
    None,
}

impl Inspirer {
    /// Initialize 'Inspirer'
    ///
    /// Either provide a custom slog::Logger or default to the standard `log`
    /// crate.
    ///
    /// # Examples
    /// ```
    /// inspirer::Inspirer::init(None);
    /// ```
    pub fn init(logger: Option<slog::Logger>) -> Self {
        let logger = logger.unwrap_or_else(|| slog::Logger::root(slog_stdlog::StdLog.fuse(), o!()));

        Inspirer {
            logger: logger,
            // inspire: libinspire::Api::init(Some(logger)),
            inspire: libinspire::Api::init(None),
        }
    }

    /// The `aux2key` function extracts TeX keys from LaTeX .aux files. These can be for either
    /// BibTeX or BibLaTeX.
    ///
    /// # Examples
    ///
    /// ## bibtex
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{Abramovici:1992ah}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Abramovici:1992ah"));
    /// ```
    ///
    /// ## biber
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \abx@aux@cite{Cutler:1992tc}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Cutler:1992tc"));
    /// ```
    pub fn aux2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r"(\\citation|\\abx@aux@cite)\{([a-zA-Z]+:\d{4}[a-z]{2,3})\}")
            .unwrap();

        regex
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            .collect()
    }

    ///  The blg2key function extracts missing references from bibtex logs
    pub fn blg2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r#"(Warning--|WARN - )I didn't find a database entry for ["']([a-zA-Z]+:\d{4}[a-z]{2,3})["']"#)
            .unwrap();

        regex
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            .collect()
    }

    /// Fetch BibTeX entries
    pub fn bibtex(&self, key: &str) -> Option<String> {
        let key = self.classify(key);

        match key {
            Sources::Inspire(k) => {
                debug!(self.logger, "Got Inspire record"; "key" => k.id);
                self.inspire.fetch_bibtex_with_key(k)
            }
            _ => {
                // debug!(self.logger, "Unknown record source"; "key" => key);
                debug!(self.logger, "Unknown record source");
                None
            }
        }
    }

    /// Guess a likely source of BibTeX key
    ///
    /// # Examples
    /// ```
    /// extern crate inspirer;
    /// extern crate libinspire;
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// assert_eq!(
    ///     inspirer.classify("Randall:1999ee"),
    ///     inspirer::Sources::Inspire(libinspire::RecID::new("Randall:1999ee").unwrap())
    /// );
    /// ```
    pub fn classify<'a>(&self, s: &'a str) -> Sources<'a> {
        if libinspire::validate_recid(s) {
            debug!(self.logger, "Detected an Inspire record"; "key" => s);
            Sources::Inspire(libinspire::RecID::new(s).unwrap())
        } else {
            debug!(self.logger, "Unknown record type"; "key" => s);
            Sources::None
        }
    }
}

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

    #[test]
    fn test_aux_bibtex_0_citations() {
        let input = r"\relax ".to_string();

        let output: Vec<String> = Vec::new();
        assert_eq!(Inspirer::init(None).aux2key(input), output);
    }

    #[test]
    fn test_aux_bibtex_1_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah"]);
    }

    #[test]
    fn test_aux_bibtex_2_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}
            \citation{Thorne:1992sdb}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah", "Thorne:1992sdb"]);
    }
}
<commit_msg>Inspirer: no longer expose libinspire::Api as pub<commit_after>extern crate libinspire;

/// Re-export slog
///
/// Users of this library can, but don't have to use slog to build their own loggers
#[macro_use]
pub extern crate slog ;
extern crate slog_stdlog;

use slog::DrainExt;

extern crate regex;
use regex::Regex;

pub struct Inspirer {
    logger: slog::Logger,
    inspire: libinspire::Api,
}

#[derive(Debug,PartialEq)]
pub enum Sources<'a> {
    Inspire(libinspire::RecID<'a>),
    Ads,
    Arxiv,
    None,
}

impl Inspirer {
    /// Initialize 'Inspirer'
    ///
    /// Either provide a custom slog::Logger or default to the standard `log`
    /// crate.
    ///
    /// # Examples
    /// ```
    /// inspirer::Inspirer::init(None);
    /// ```
    pub fn init(logger: Option<slog::Logger>) -> Self {
        let logger = logger.unwrap_or_else(|| slog::Logger::root(slog_stdlog::StdLog.fuse(), o!()));

        Inspirer {
            logger: logger,
            // inspire: libinspire::Api::init(Some(logger)),
            inspire: libinspire::Api::init(None),
        }
    }

    /// The `aux2key` function extracts TeX keys from LaTeX .aux files. These can be for either
    /// BibTeX or BibLaTeX.
    ///
    /// # Examples
    ///
    /// ## bibtex
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{Abramovici:1992ah}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Abramovici:1992ah"));
    /// ```
    ///
    /// ## biber
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \abx@aux@cite{Cutler:1992tc}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Cutler:1992tc"));
    /// ```
    pub fn aux2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r"(\\citation|\\abx@aux@cite)\{([a-zA-Z]+:\d{4}[a-z]{2,3})\}")
            .unwrap();

        regex
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            .collect()
    }

    ///  The blg2key function extracts missing references from bibtex logs
    pub fn blg2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r#"(Warning--|WARN - )I didn't find a database entry for ["']([a-zA-Z]+:\d{4}[a-z]{2,3})["']"#)
            .unwrap();

        regex
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            .collect()
    }

    /// Fetch BibTeX entries
    pub fn bibtex(&self, key: &str) -> Option<String> {
        let key = self.classify(key);

        match key {
            Sources::Inspire(k) => {
                debug!(self.logger, "Got Inspire record"; "key" => k.id);
                self.inspire.fetch_bibtex_with_key(k)
            }
            _ => {
                // debug!(self.logger, "Unknown record source"; "key" => key);
                debug!(self.logger, "Unknown record source");
                None
            }
        }
    }

    /// Guess a likely source of BibTeX key
    ///
    /// # Examples
    /// ```
    /// extern crate inspirer;
    /// extern crate libinspire;
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// assert_eq!(
    ///     inspirer.classify("Randall:1999ee"),
    ///     inspirer::Sources::Inspire(libinspire::RecID::new("Randall:1999ee").unwrap())
    /// );
    /// ```
    pub fn classify<'a>(&self, s: &'a str) -> Sources<'a> {
        if libinspire::validate_recid(s) {
            debug!(self.logger, "Detected an Inspire record"; "key" => s);
            Sources::Inspire(libinspire::RecID::new(s).unwrap())
        } else {
            debug!(self.logger, "Unknown record type"; "key" => s);
            Sources::None
        }
    }
}

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

    #[test]
    fn test_aux_bibtex_0_citations() {
        let input = r"\relax ".to_string();

        let output: Vec<String> = Vec::new();
        assert_eq!(Inspirer::init(None).aux2key(input), output);
    }

    #[test]
    fn test_aux_bibtex_1_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah"]);
    }

    #[test]
    fn test_aux_bibtex_2_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}
            \citation{Thorne:1992sdb}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah", "Thorne:1992sdb"]);
    }
}
<|endoftext|>


<commit_before>//! par is a terminal interface for rendering progress bars
//!
//! #example
//! ```rust
//! use par::Bar;
//! fn main() {
//!     let bar = Bar::new(100);
//!     for i in 1..101 {
//!         bar.add(i);
//!         std::thread::sleep_ms(10);
//!     }
//!     bar.finish_print("done")
//! }
//! ```
extern crate capsize;
extern crate termsize;

use capsize::Capacity;
use std::io::{self, Read, Write};
use std::iter;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::default::Default;

static FORMAT: &'static str = "[=>_]";

/// Unit of display for progress counter
pub enum Units {
    /// No units
    None,
    /// formats units in humanized byte sizes
    Bytes
}

impl Default for Units {
    fn default() -> Units {
        Units::None
    }
}

/// Preference for reporting progress
pub enum Reporter {
    /// Report progress to stdout
    StdOut,
    /// Report progress to stderr
    StdErr,
    /// Report progress to a callback
    Callback(fn(String) -> ())
}

impl Default for Reporter {
    fn default() -> Reporter {
        Reporter::StdErr
    }
}

/// IO progress. Implementations for Read and Write are provided
pub struct IO<T> {
    inner: T,
    bar: Bar
}

impl <R: Read> IO<R> {
    pub fn new(read: R, bar: Bar) -> IO<R> {
        IO {
            inner: read,
            bar: bar
        }
    }
}

impl <R: Read> Read for IO<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let n = try!(self.inner.read(buf));
        self.bar.add(n);
        Ok(n)
    }
}

impl <W: Write> IO<W> {
    pub fn new(write: W, bar: Bar) -> IO<W> {
        IO {
            inner: write,
            bar: bar
        }
    }
}

impl <W: Write> Write for IO<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = buf.len();
        self.bar.add(n);
        Ok(n)
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

/// A bar of progress information
#[derive(Default)]
pub struct Bar {
    total: usize,
    /// show progress percent, defaults to true
    pub show_percent: bool,
    /// show progress counter. Defaults to true
    pub show_counter: bool,
    /// show main progress bar UI. Defaults to true
    pub show_bar: bool,
    /// an arbitrary string label to prefix display with
    pub prefix: String,
    /// preference for reporting progress
    pub reporter: Reporter,
    current: AtomicUsize,
    units: Units,
    bar_start: String,
    bar_current: String,
    bar_current_n: String,
    bar_empty: String,
    bar_end: String
}

impl Bar {
    /// creates a new bar with a target total size of `total`
    pub fn new(total: usize) -> Bar {
        let mut bar = Bar {
            total: total,
            show_percent: true,
            show_counter: true,
            show_bar: true,
            ..Default::default()
        };
        bar.format(FORMAT);
        bar
    }

    /// sets a custom format for display
    /// Example: bar.format("[=>_]")
    pub fn format(&mut self, spec: &str) {
        if spec.len() == 5 {
            let parts = spec.split("").collect::<Vec<&str>>();
            self.bar_start = parts[1].to_owned();
            self.bar_current = parts[2].to_owned();
            self.bar_current_n = parts[3].to_owned();
            self.bar_empty = parts[4].to_owned();
            self.bar_end = parts[5].to_owned();
        }
    }

    /// increment bar count by one
    pub fn incr(&self) -> usize {
        self.add(1)
    }

    /// add 1 to the bar count
    pub fn add(&self, delta: usize) -> usize {
        let prev = self.current.fetch_add(delta, Ordering::Relaxed);
        self.update();
        prev
    }

    /// sets the bar count to specified value
    pub fn set(&self, value: usize) {
        self.current.store(value, Ordering::Relaxed);
        self.update()
    }

    pub fn update(&self) {
        let current = self.current.load(Ordering::Relaxed);
        if current <= self.total {
            self.write(current)
        }
    }

    pub fn finish_print(&self, msg: &str) {
        println!("");
        println!("{}", msg)
    }

    fn width(&self) -> usize {
        termsize::get().map(|s|s.cols as usize).unwrap_or(80)
    }

    fn write(&self, current: usize) {
        fn repeat(what: &str, n: usize) -> String {
            iter::repeat(what).take(n).collect::<String>()
        }

        fn unit(value: usize, units: &Units) -> String {
            match *units {
                Units::None => value.to_string(),
                Units::Bytes => (value as i64).capacity()
            }
        }

        let width = self.width();

        let mut prefix = self.prefix.clone();
        let mut mid = String::new();
        let mut suffix = String::new();

        // counter
        if self.show_counter {
            prefix = prefix + &format!(
                "{} / {} ", unit(current, &self.units), unit(self.total, &self.units)
            );
        }

        // percent complete
        if self.show_percent {
            let percent = current as f64 / (self.total as f64 / 100_f64);
            suffix = suffix + &format!(
                " {:.*} %", 2, percent
            );
        }

        if self.show_bar {
            let size = width - (prefix.len() + suffix.len() + 3);
            if size > 0 {
                let cur_count = (
                    (current as f64 / self.total as f64) * size as f64
                ).ceil() as usize;
                let empt_count = size - cur_count;
                mid = self.bar_start.clone();
                if empt_count > 0 {
                    mid = mid + &repeat(self.bar_current.as_ref(), (cur_count - 1) as usize) +  &self.bar_current_n;
                } else {
                    mid = mid + &repeat(self.bar_current.as_ref(), cur_count as usize);
                }
                mid = mid + &repeat(self.bar_empty.as_ref(), (empt_count) as usize) + &self.bar_end
            }
        }
        let mut display = prefix + &mid + &suffix;
        if display.len() < width {
            let remaining = width - display.len();
            display = display + &repeat(" ", remaining);
        }

        match self.reporter {
            Reporter::StdErr => {
                let _ = write!(&mut std::io::stderr(), "\r{}", display);
            },
            Reporter::StdOut => {
                let _ = write!(&mut std::io::stderr(), "\r{}", display);
            },
            Reporter::Callback(cb) => {
                cb(display);
            }
        }
    }
}

#[test]
fn it_works() {
}
<commit_msg>improve docs<commit_after>//! par is a terminal interface for rendering progress bars
//!
//! #example
//! ```rust
//! use par::Bar;
//! fn main() {
//!     let bar = Bar::new(100);
//!     for i in 1..101 {
//!         bar.add(i);
//!         std::thread::sleep_ms(10);
//!     }
//!     bar.finish_print("done")
//! }
//! ```
extern crate capsize;
extern crate termsize;

use capsize::Capacity;
use std::io::{self, Read, Write};
use std::iter;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::default::Default;

static FORMAT: &'static str = "[=>_]";

/// Unit of display for progress counter
pub enum Units {
    /// No units
    None,
    /// format progress in humanized byte sizes
    Bytes
}

impl Default for Units {
    fn default() -> Units {
        Units::None
    }
}

/// Preference for reporting progress
pub enum Reporter {
    /// Report progress to stdout
    StdOut,
    /// Report progress to stderr
    StdErr,
    /// Report progress to a callback
    Callback(fn(String) -> ())
}

impl Default for Reporter {
    fn default() -> Reporter {
        Reporter::StdErr
    }
}

/// IO progress. Implementations for Read and Write are provided
pub struct IO<T> {
    inner: T,
    bar: Bar
}

impl <R: Read> IO<R> {
    pub fn new(read: R, bar: Bar) -> IO<R> {
        IO {
            inner: read,
            bar: bar
        }
    }
}

impl <R: Read> Read for IO<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let n = try!(self.inner.read(buf));
        self.bar.add(n);
        Ok(n)
    }
}

impl <W: Write> IO<W> {
    pub fn new(write: W, bar: Bar) -> IO<W> {
        IO {
            inner: write,
            bar: bar
        }
    }
}

impl <W: Write> Write for IO<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = buf.len();
        self.bar.add(n);
        Ok(n)
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

/// A bar of progress information
#[derive(Default)]
pub struct Bar {
    total: usize,
    /// show progress percent, defaults to true
    pub show_percent: bool,
    /// show progress counter. Defaults to true
    pub show_counter: bool,
    /// show main progress bar UI. Defaults to true
    pub show_bar: bool,
    /// an arbitrary string label to prefix display with
    pub prefix: String,
    /// preference for reporting progress
    pub reporter: Reporter,
    current: AtomicUsize,
    units: Units,
    bar_start: String,
    bar_current: String,
    bar_current_n: String,
    bar_empty: String,
    bar_end: String
}

impl Bar {
    /// creates a new bar with a target total size of `total`
    pub fn new(total: usize) -> Bar {
        let mut bar = Bar {
            total: total,
            show_percent: true,
            show_counter: true,
            show_bar: true,
            ..Default::default()
        };
        bar.format(FORMAT);
        bar
    }

    /// sets a custom format for display
    /// Example: bar.format("[=>_]")
    pub fn format(&mut self, spec: &str) {
        if spec.len() == 5 {
            let parts = spec.split("").collect::<Vec<&str>>();
            self.bar_start = parts[1].to_owned();
            self.bar_current = parts[2].to_owned();
            self.bar_current_n = parts[3].to_owned();
            self.bar_empty = parts[4].to_owned();
            self.bar_end = parts[5].to_owned();
        }
    }

    /// increment bar count by one
    pub fn incr(&self) -> usize {
        self.add(1)
    }

    /// add 1 to the bar count
    pub fn add(&self, delta: usize) -> usize {
        let prev = self.current.fetch_add(delta, Ordering::Relaxed);
        self.update();
        prev
    }

    /// sets the bar count to specified value
    pub fn set(&self, value: usize) {
        self.current.store(value, Ordering::Relaxed);
        self.update()
    }

    pub fn update(&self) {
        let current = self.current.load(Ordering::Relaxed);
        if current <= self.total {
            self.write(current)
        }
    }

    pub fn finish_print(&self, msg: &str) {
        println!("");
        println!("{}", msg)
    }

    fn width(&self) -> usize {
        termsize::get().map(|s|s.cols as usize).unwrap_or(80)
    }

    fn write(&self, current: usize) {
        fn repeat(what: &str, n: usize) -> String {
            iter::repeat(what).take(n).collect::<String>()
        }

        fn unit(value: usize, units: &Units) -> String {
            match *units {
                Units::None => value.to_string(),
                Units::Bytes => (value as i64).capacity()
            }
        }

        let width = self.width();

        let mut prefix = self.prefix.clone();
        let mut mid = String::new();
        let mut suffix = String::new();

        // counter
        if self.show_counter {
            prefix = prefix + &format!(
                "{} / {} ", unit(current, &self.units), unit(self.total, &self.units)
            );
        }

        // percent complete
        if self.show_percent {
            let percent = current as f64 / (self.total as f64 / 100_f64);
            suffix = suffix + &format!(
                " {:.*} %", 2, percent
            );
        }

        if self.show_bar {
            let size = width - (prefix.len() + suffix.len() + 3);
            if size > 0 {
                let cur_count = (
                    (current as f64 / self.total as f64) * size as f64
                ).ceil() as usize;
                let empt_count = size - cur_count;
                mid = self.bar_start.clone();
                if empt_count > 0 {
                    mid = mid + &repeat(self.bar_current.as_ref(), (cur_count - 1) as usize) +  &self.bar_current_n;
                } else {
                    mid = mid + &repeat(self.bar_current.as_ref(), cur_count as usize);
                }
                mid = mid + &repeat(self.bar_empty.as_ref(), (empt_count) as usize) + &self.bar_end
            }
        }
        let mut display = prefix + &mid + &suffix;
        if display.len() < width {
            let remaining = width - display.len();
            display = display + &repeat(" ", remaining);
        }

        match self.reporter {
            Reporter::StdErr => {
                let _ = write!(&mut std::io::stderr(), "\r{}", display);
            },
            Reporter::StdOut => {
                let _ = write!(&mut std::io::stderr(), "\r{}", display);
            },
            Reporter::Callback(cb) => {
                cb(display);
            }
        }
    }
}

#[test]
fn it_works() {
}
<|endoftext|>