<commit_before>// Reference: Section 7.4 "Hints" of ACLE

// CP15 instruction
#[cfg(not(any(
    // v8
    target_arch = "aarch64",
    // v7
    target_feature = "v7",
    // v6-M
    target_feature = "mclass"
)))]
mod cp15;

#[cfg(not(any(
    target_arch = "aarch64",
    target_feature = "v7",
    target_feature = "mclass"
)))]
pub use self::cp15::*;

// Dedicated instructions
macro_rules! dmb_dsb {
    ($A:ident) => {
        impl super::super::sealed::Dmb for $A {
            #[inline(always)]
            unsafe fn __dmb(&self) {
                super::dmb(super::arg::$A)
            }
        }

        impl super::super::sealed::Dsb for $A {
            #[inline(always)]
            unsafe fn __dsb(&self) {
                super::dsb(super::arg::$A)
            }
        }
    };
}

#[cfg(any(
    target_arch = "aarch64",
    target_feature = "v7",
    target_feature = "mclass"
))]
mod common;

#[cfg(any(
    target_arch = "aarch64",
    target_feature = "v7",
    target_feature = "mclass"
))]
pub use self::common::*;

#[cfg(any(target_arch = "aarch64", target_feature = "v7",))]
mod not_mclass;

#[cfg(any(target_arch = "aarch64", target_feature = "v7",))]
pub use self::not_mclass::*;

#[cfg(target_arch = "aarch64")]
mod v8;

#[cfg(target_arch = "aarch64")]
pub use self::v8::*;

/// Generates a DMB (data memory barrier) instruction or equivalent CP15 instruction.
///
/// DMB ensures the observed ordering of memory accesses. Memory accesses of the specified type
/// issued before the DMB are guaranteed to be observed (in the specified scope) before memory
/// accesses issued after the DMB.
///
/// For example, DMB should be used between storing data, and updating a flag variable that makes
/// that data available to another core.
///
/// The __dmb() intrinsic also acts as a compiler memory barrier of the appropriate type.
#[inline(always)]
pub unsafe fn __dmb<A>(arg: A)
where
    A: super::sealed::Dmb,
{
    arg.__dmb()
}

/// Generates a DSB (data synchronization barrier) instruction or equivalent CP15 instruction.
///
/// DSB ensures the completion of memory accesses. A DSB behaves as the equivalent DMB and has
/// additional properties. After a DSB instruction completes, all memory accesses of the specified
/// type issued before the DSB are guaranteed to have completed.
///
/// The __dsb() intrinsic also acts as a compiler memory barrier of the appropriate type.
#[inline(always)]
pub unsafe fn __dsb<A>(arg: A)
where
    A: super::sealed::Dsb,
{
    arg.__dsb()
}

/// Generates an ISB (instruction synchronization barrier) instruction or equivalent CP15
/// instruction.
///
/// This instruction flushes the processor pipeline fetch buffers, so that following instructions
/// are fetched from cache or memory.
///
/// An ISB is needed after some system maintenance operations. An ISB is also needed before
/// transferring control to code that has been loaded or modified in memory, for example by an
/// overlay mechanism or just-in-time code generator.  (Note that if instruction and data caches are
/// separate, privileged cache maintenance operations would be needed in order to unify the caches.)
///
/// The only supported argument for the __isb() intrinsic is 15, corresponding to the SY (full
/// system) scope of the ISB instruction.
#[inline(always)]
pub unsafe fn __isb<A>(arg: A)
where
    A: super::sealed::Isb,
{
    arg.__isb()
}

extern "C" {
    #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.dmb")]
    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.dmb")]
    fn dmb(_: i32);

    #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.dsb")]
    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.dsb")]
    fn dsb(_: i32);

    #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.isb")]
    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.isb")]
    fn isb(_: i32);
}

// we put these in a module to prevent weirdness with glob re-exports
mod arg {
    // See Section 7.3  Memory barriers of ACLE
    pub const SY: i32 = 15;
    pub const ST: i32 = 14;
    pub const LD: i32 = 13;
    pub const ISH: i32 = 11;
    pub const ISHST: i32 = 10;
    pub const ISHLD: i32 = 9;
    pub const NSH: i32 = 7;
    pub const NSHST: i32 = 6;
    pub const NSHLD: i32 = 5;
    pub const OSH: i32 = 3;
    pub const OSHST: i32 = 2;
    pub const OSHLD: i32 = 1;
}
<commit_msg>conditionally declare the dmb_dsb macro<commit_after>// Reference: Section 7.4 "Hints" of ACLE

// CP15 instruction
#[cfg(not(any(
    // v8
    target_arch = "aarch64",
    // v7
    target_feature = "v7",
    // v6-M
    target_feature = "mclass"
)))]
mod cp15;

#[cfg(not(any(
    target_arch = "aarch64",
    target_feature = "v7",
    target_feature = "mclass"
)))]
pub use self::cp15::*;

// Dedicated instructions
#[cfg(any(
    target_arch = "aarch64",
    target_feature = "v7",
    target_feature = "mclass"
))]
macro_rules! dmb_dsb {
    ($A:ident) => {
        impl super::super::sealed::Dmb for $A {
            #[inline(always)]
            unsafe fn __dmb(&self) {
                super::dmb(super::arg::$A)
            }
        }

        impl super::super::sealed::Dsb for $A {
            #[inline(always)]
            unsafe fn __dsb(&self) {
                super::dsb(super::arg::$A)
            }
        }
    };
}

#[cfg(any(
    target_arch = "aarch64",
    target_feature = "v7",
    target_feature = "mclass"
))]
mod common;

#[cfg(any(
    target_arch = "aarch64",
    target_feature = "v7",
    target_feature = "mclass"
))]
pub use self::common::*;

#[cfg(any(target_arch = "aarch64", target_feature = "v7",))]
mod not_mclass;

#[cfg(any(target_arch = "aarch64", target_feature = "v7",))]
pub use self::not_mclass::*;

#[cfg(target_arch = "aarch64")]
mod v8;

#[cfg(target_arch = "aarch64")]
pub use self::v8::*;

/// Generates a DMB (data memory barrier) instruction or equivalent CP15 instruction.
///
/// DMB ensures the observed ordering of memory accesses. Memory accesses of the specified type
/// issued before the DMB are guaranteed to be observed (in the specified scope) before memory
/// accesses issued after the DMB.
///
/// For example, DMB should be used between storing data, and updating a flag variable that makes
/// that data available to another core.
///
/// The __dmb() intrinsic also acts as a compiler memory barrier of the appropriate type.
#[inline(always)]
pub unsafe fn __dmb<A>(arg: A)
where
    A: super::sealed::Dmb,
{
    arg.__dmb()
}

/// Generates a DSB (data synchronization barrier) instruction or equivalent CP15 instruction.
///
/// DSB ensures the completion of memory accesses. A DSB behaves as the equivalent DMB and has
/// additional properties. After a DSB instruction completes, all memory accesses of the specified
/// type issued before the DSB are guaranteed to have completed.
///
/// The __dsb() intrinsic also acts as a compiler memory barrier of the appropriate type.
#[inline(always)]
pub unsafe fn __dsb<A>(arg: A)
where
    A: super::sealed::Dsb,
{
    arg.__dsb()
}

/// Generates an ISB (instruction synchronization barrier) instruction or equivalent CP15
/// instruction.
///
/// This instruction flushes the processor pipeline fetch buffers, so that following instructions
/// are fetched from cache or memory.
///
/// An ISB is needed after some system maintenance operations. An ISB is also needed before
/// transferring control to code that has been loaded or modified in memory, for example by an
/// overlay mechanism or just-in-time code generator.  (Note that if instruction and data caches are
/// separate, privileged cache maintenance operations would be needed in order to unify the caches.)
///
/// The only supported argument for the __isb() intrinsic is 15, corresponding to the SY (full
/// system) scope of the ISB instruction.
#[inline(always)]
pub unsafe fn __isb<A>(arg: A)
where
    A: super::sealed::Isb,
{
    arg.__isb()
}

extern "C" {
    #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.dmb")]
    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.dmb")]
    fn dmb(_: i32);

    #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.dsb")]
    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.dsb")]
    fn dsb(_: i32);

    #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.isb")]
    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.isb")]
    fn isb(_: i32);
}

// we put these in a module to prevent weirdness with glob re-exports
mod arg {
    // See Section 7.3  Memory barriers of ACLE
    pub const SY: i32 = 15;
    pub const ST: i32 = 14;
    pub const LD: i32 = 13;
    pub const ISH: i32 = 11;
    pub const ISHST: i32 = 10;
    pub const ISHLD: i32 = 9;
    pub const NSH: i32 = 7;
    pub const NSHST: i32 = 6;
    pub const NSHLD: i32 = 5;
    pub const OSH: i32 = 3;
    pub const OSHST: i32 = 2;
    pub const OSHLD: i32 = 1;
}
<|endoftext|>


<commit_before>extern crate core;

use core::option::Option;
use core::iter::Iterator;
use core::str::StrExt;

use asm;
use interrupt;

pub struct Console {
    position:u32
}

#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

static mut console: Console = Console {position: 0};

impl Console {
    pub fn init() -> &'static mut Console {
        interrupt::register_handler(on_keyboard_interrupt);
        unsafe {
            return &mut console;
        }
    }

    pub fn clear_screen(&self,background: Color) {
        let mut r = 0..80 * 25;
        loop {
            match r.next() {
                Option::Some(x) => {
                    unsafe {
                        *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
                    }
                },
                Option::None =>{break}
            }
        }
        self.move_cursor(0);
    }

    #[no_stack_check]
    pub fn print_string(&mut self,string: &str) {
        let mut bytes = string.chars();
        loop {
            match bytes.next() {
                Option::Some(x) => {
                    self.print_char(x);
                },
                Option::None =>{break}
            }
        }
    }

    pub fn print_char(&mut self,c: char) {
        if c == '\n' {
            self.position += 80;
            let col = self.position % 80;
            self.position -= col;
        } else {
            unsafe {
                *((0xb8000 + self.position*2) as *mut u8) = c as u8;
                *((0xb8000 + self.position*2 + 1) as *mut u8) = 0x0f;
            }
            self.position += 1;
        }
        self.update_cursor();
    }

    pub fn print_int(&mut self, number: u32) {
        let mut length = 0;
        let output:[u8;64] = [0;64];
        let mut left = number;
        loop {
            //TODO: Must be a better way to write to vector without bounds checking
            let output_addr:*const u8 = &output[0];
            let output_addr_u32:u32=output_addr as u32;
            unsafe {
                *((output_addr_u32 + length) as *mut u8) = (left % 10) as u8;
            }
            length += 1;
            left = left / 10;
            if left == 0 {
                break;
            }
        }
        loop {
            let c:char = (output[(length-1) as usize] + 0x30) as char;
            self.print_char(c);
            length -= 1;
            if length == 0 {
                break;
            }
        }
    }

    fn update_cursor(&self) {
        self.move_cursor(self.position);
    }

    fn move_cursor(&self,pos: u32) {
        asm::out8(0x3D4,15);
        asm::out8(0x3D5,(pos & 0xff) as u8);
        asm::out8(0x3D4,14);
        asm::out8(0x3D5,((pos >> 8) & 0xff) as u8);
    }
}

#[no_stack_check]
fn on_keyboard_interrupt() {
    let scancode = asm::in8(0x60);
    // Keydown
    if scancode & 0b10000000 == 0 {
        let c = scancode_to_char(scancode);
        unsafe {
            console.print_char(c);
        }
    }
}

fn scancode_to_char(scancode: u8) -> char {
    let mut charmap:[char;256] = ['?';256];
    charmap[0x2] = '1';
    charmap[0x3] = '2';
    charmap[0x4] = '3';
    charmap[0x5] = '4';
    charmap[0x6] = '5';
    charmap[0x7] = '6';
    charmap[0x8] = '7';
    charmap[0x9] = '8';
    charmap[0xA] = '9';
    charmap[0xB] = '0';
    charmap[0x1C] = '\n';

    return charmap[scancode as usize];
}
<commit_msg>Scroll up when bottom of terminal reached<commit_after>extern crate core;

use core::option::Option;
use core::iter::Iterator;
use core::str::StrExt;

use asm;
use interrupt;

pub struct Console {
    position:u32
}

#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

static mut console: Console = Console {position: 0};

impl Console {
    pub fn init() -> &'static mut Console {
        interrupt::register_handler(on_keyboard_interrupt);
        unsafe {
            return &mut console;
        }
    }

    pub fn clear_screen(&self,background: Color) {
        let mut r = 0..80 * 25;
        loop {
            match r.next() {
                Option::Some(x) => {
                    unsafe {
                        *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
                    }
                },
                Option::None =>{break}
            }
        }
        self.move_cursor(0);
    }

    #[no_stack_check]
    pub fn print_string(&mut self,string: &str) {
        let mut bytes = string.chars();
        loop {
            match bytes.next() {
                Option::Some(x) => {
                    self.print_char(x);
                },
                Option::None =>{break}
            }
        }
    }

    #[no_stack_check]
    pub fn print_char(&mut self,c: char) {
        if c == '\n' {
            let col = self.position % 80;
            self.position -= col;
            let current_row = self.current_row();
            if (current_row < 24) {
                self.position += 80;
            } else {
                // Scroll everything one row up.
                let mut r = 0..80 * 25;
                loop {
                    match r.next() {
                        Option::Some(x) => {
                            unsafe {
                                *((0xb8000 + x*2) as *mut u16) = *((0xb8000 + (x+80)*2) as *mut u16)
                            }
                        },
                        Option::None =>{break}
                    }
                }
            }
        } else {
            unsafe {
                *((0xb8000 + self.position*2) as *mut u8) = c as u8;
                *((0xb8000 + self.position*2 + 1) as *mut u8) = 0x0f;
            }
            self.position += 1;
        }
        self.update_cursor();
    }

    #[no_stack_check]
    pub fn print_int(&mut self, number: u32) {
        let mut length = 0;
        let output:[u8;64] = [0;64];
        let mut left = number;
        loop {
            //TODO: Must be a better way to write to vector without bounds checking
            let output_addr:*const u8 = &output[0];
            let output_addr_u32:u32=output_addr as u32;
            unsafe {
                *((output_addr_u32 + length) as *mut u8) = (left % 10) as u8;
            }
            length += 1;
            left = left / 10;
            if left == 0 {
                break;
            }
        }
        loop {
            let c:char = (output[(length-1) as usize] + 0x30) as char;
            self.print_char(c);
            length -= 1;
            if length == 0 {
                break;
            }
        }
    }

    fn update_cursor(&self) {
        self.move_cursor(self.position);
    }

    fn move_cursor(&self,pos: u32) {
        asm::out8(0x3D4,15);
        asm::out8(0x3D5,(pos & 0xff) as u8);
        asm::out8(0x3D4,14);
        asm::out8(0x3D5,((pos >> 8) & 0xff) as u8);
    }

    fn current_row(&self) -> u32 {
        return self.position / 80;
    }
}

#[no_stack_check]
fn on_keyboard_interrupt() {
    let scancode = asm::in8(0x60);
    // Keydown
    if scancode & 0b10000000 == 0 {
        let c = scancode_to_char(scancode);
        unsafe {
            console.print_char(c);
        }
    }
}

fn scancode_to_char(scancode: u8) -> char {
    let mut charmap:[char;256] = ['?';256];
    charmap[0x2] = '1';
    charmap[0x3] = '2';
    charmap[0x4] = '3';
    charmap[0x5] = '4';
    charmap[0x6] = '5';
    charmap[0x7] = '6';
    charmap[0x8] = '7';
    charmap[0x9] = '8';
    charmap[0xA] = '9';
    charmap[0xB] = '0';
    charmap[0x1C] = '\n';

    return charmap[scancode as usize];
}
<|endoftext|>


<commit_before>use event::Event;
use sass::selector::SassSelector;

use std::borrow::Cow;
use std::fmt;

#[derive(Clone)]
pub struct SassRule<'a> {
    pub selectors: Vec<SassSelector<'a>>,
    pub selectors_done: bool,
    pub children: Vec<Event<'a>>,
}

impl<'a> SassRule<'a> {
    pub fn new() -> SassRule<'a> {
        SassRule {
            selectors: Vec::new(),
            selectors_done: false,
            children: Vec::new(),
        }
    }

    pub fn expanded(&self) -> String {
        self.expanded_with_parent("")
    }

    pub fn expanded_with_parent(&self, parents: &str) -> String {
        let mut output = String::new();

        let selector_string = self.selectors.iter().map(|s| {
            match parents.len() {
                0 => (*s.name).to_string(),
                _ => format!("{} {}", parents, s.name),
            }
        }).collect::<Vec<_>>().connect(", ");

        let properties_string = self.children.iter().filter(|c| !c.is_child_rule() ).map(|c| {
            c.expanded()
        }).collect::<Vec<_>>().connect("\n");

        let child_rules_string = self.children.iter().filter(|c| c.is_child_rule() ).map(|c| {
            match c {
                &Event::ChildRule(ref rule) => rule.expanded_with_parent(&selector_string),
                _ => unreachable!(),
            }
        }).collect::<Vec<_>>().connect("\n");

        if properties_string.len() > 0 {
            output.push_str(&selector_string);
            output.push_str(" ");
            output.push_str(&format!("{{\n{}\n}}\n", properties_string));
            output.push_str(&child_rules_string);
        } else {
            output.push_str(&child_rules_string);
        }

        output
    }

    pub fn map_over_property_values<F>(self, f: &F) -> SassRule<'a>
        where F: Fn(Cow<'a, str>) -> Cow<'a, str>
    {
        let replacement_children = self.children.into_iter().map(|c|
            match c {
                Event::Property(name, value) => {
                    Event::Property(name, f(value))
                },
                Event::ChildRule(rule) => {
                    Event::ChildRule(rule.map_over_property_values(f))
                },
                other => other
            }
        ).collect();

        SassRule {
            children: replacement_children, ..self
        }
    }
}

impl<'a> fmt::Debug for SassRule<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let children = self.children.iter().map(|c| format!("{:?}", c)).collect::<Vec<_>>().connect("\n");
        let indented_children = children.split("\n").collect::<Vec<_>>().connect("\n  ");
        write!(f, "{:?} {{\n  {}\n}}", self.selectors, indented_children)
    }
}
<commit_msg>Remove a bit of duplication<commit_after>use event::Event;
use sass::selector::SassSelector;

use std::borrow::Cow;
use std::fmt;

#[derive(Clone)]
pub struct SassRule<'a> {
    pub selectors: Vec<SassSelector<'a>>,
    pub selectors_done: bool,
    pub children: Vec<Event<'a>>,
}

impl<'a> SassRule<'a> {
    pub fn new() -> SassRule<'a> {
        SassRule {
            selectors: Vec::new(),
            selectors_done: false,
            children: Vec::new(),
        }
    }

    pub fn expanded(&self) -> String {
        self.expanded_with_parent("")
    }

    pub fn expanded_with_parent(&self, parents: &str) -> String {
        let mut output = String::new();

        let selector_string = self.selectors.iter().map(|s| {
            match parents.len() {
                0 => (*s.name).to_string(),
                _ => format!("{} {}", parents, s.name),
            }
        }).collect::<Vec<_>>().connect(", ");

        let properties_string = self.children.iter().filter(|c| !c.is_child_rule() ).map(|c| {
            c.expanded()
        }).collect::<Vec<_>>().connect("\n");

        let child_rules_string = self.children.iter().filter(|c| c.is_child_rule() ).map(|c| {
            match c {
                &Event::ChildRule(ref rule) => rule.expanded_with_parent(&selector_string),
                _ => unreachable!(),
            }
        }).collect::<Vec<_>>().connect("\n");

        if properties_string.len() > 0 {
            output.push_str(&selector_string);
            output.push_str(" ");
            output.push_str(&format!("{{\n{}\n}}\n", properties_string));
        }
        output.push_str(&child_rules_string);

        output
    }

    pub fn map_over_property_values<F>(self, f: &F) -> SassRule<'a>
        where F: Fn(Cow<'a, str>) -> Cow<'a, str>
    {
        let replacement_children = self.children.into_iter().map(|c|
            match c {
                Event::Property(name, value) => {
                    Event::Property(name, f(value))
                },
                Event::ChildRule(rule) => {
                    Event::ChildRule(rule.map_over_property_values(f))
                },
                other => other
            }
        ).collect();

        SassRule {
            children: replacement_children, ..self
        }
    }
}

impl<'a> fmt::Debug for SassRule<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let children = self.children.iter().map(|c| format!("{:?}", c)).collect::<Vec<_>>().connect("\n");
        let indented_children = children.split("\n").collect::<Vec<_>>().connect("\n  ");
        write!(f, "{:?} {{\n  {}\n}}", self.selectors, indented_children)
    }
}
<|endoftext|>


<commit_before>use std::f64;
use std::iter;
use std::slice;

use num::traits::{cast, NumCast};
use itertools::Itertools;

use bio::stats::logprobs::{self, LogProb};

#[derive(Debug, Clone)]
pub struct CDF<T: PartialOrd> {
    inner: Vec<(T, LogProb)>
}

impl<T: PartialOrd> CDF<T> {
    /// Create CDF from given probability mass function (PMF). The PMF may contain duplicate values
    /// the probabilities of which are summed during generation of the CDF.
    pub fn from_pmf(mut entries: Vec<(T, LogProb)>) -> Self {
        entries.sort_by(|&(ref a, _), &(ref b, _)| a.partial_cmp(b).unwrap());
        let mut entries = entries.into_iter();
        let mut inner = vec![entries.next().unwrap()];
        for mut e in entries {
            let p = logprobs::add(inner.last().unwrap().1, e.1);
            if inner.last().unwrap().0 == e.0 {
                //println!("equal");
                inner.last_mut().unwrap().1 = p;
            }
            else {
                //println!("unequal");
                e.1 = p;
                inner.push(e);
            }
        }
        let mut cdf = CDF {
            inner: inner
        };

        if relative_eq!(cdf.total_prob(), 0.0) && cdf.total_prob() > 0.0 {
            cdf.inner.last_mut().unwrap().1 = 0.0;
        }

        cdf
    }

    /// Create CDF from iterator. This can be used to replace the values of a CDF.
    pub fn from_cdf<I: Iterator<Item = (T, LogProb)>>(entries: I) -> Self {
        CDF { inner: entries.collect_vec() }
    }

    pub fn sample(mut self, n: usize) -> Self {
        if self.inner.len() <= n {
            self
        }
        else {
            let s = self.inner.len() / (n - 1);
            let last = self.inner.pop().unwrap();
            let mut inner = self.inner.into_iter().step(s).collect_vec();
            inner.push(last);
            CDF {
                inner: inner
            }
        }
    }

    pub fn iter(&self) -> slice::Iter<(T, f64)>{
        self.inner.iter()
    }

    pub fn iter_pmf<'a>(&'a self) -> CDFPMFIter<'a, T> {
        fn cdf_to_pmf<'a, G>(last_prob: &mut LogProb, e: &'a (G, LogProb)) -> Option<(&'a G, LogProb)> {
            let &(ref value, cdf_prob) = e;
            let prob = logprobs::sub(cdf_prob, *last_prob);
            *last_prob = cdf_prob;
            Some((value, prob))
        }
        self.inner.iter().scan(f64::NEG_INFINITY, cdf_to_pmf)
    }

    /// Get cumulative probability for a given value. If the value is not present,
    /// return the probability of the previous value.
    pub fn get(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => self.inner[i].1,
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn get_pmf(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => if i > 0 { logprobs::sub(self.inner[i].1, self.inner[i - 1].1) } else { self.inner[0].1 },
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn total_prob(&self) -> LogProb {
        let &(_, prob) = self.inner.last().unwrap();
        prob
    }

    /// Return maximum a posteriori probability estimate (MAP).
    pub fn map(&self) -> &T {
        let mut max = self.iter_pmf().next().unwrap();
        for e in self.iter_pmf() {
            if e.1 >= max.1 {
                max = e;
            }
        }
        &max.0
    }

    pub fn credible_interval(&self) -> (&T, &T) {
        let lower = self.inner.binary_search_by(|&(_, p)| p.partial_cmp(&0.025f64.ln()).unwrap()).unwrap_or_else(|i| i);
        let upper = self.inner.binary_search_by(|&(_, p)| p.partial_cmp(&0.975f64.ln()).unwrap()).unwrap_or_else(|i| i - 1);

        (&self.inner[lower].0, &self.inner[upper].0)
    }

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

impl<T: NumCast + Clone + PartialOrd> CDF<T> {
    pub fn expected_value(&self) -> f64 {
        self.iter_pmf().map(|(value, prob)| {
            cast::<T, f64>(value.clone()).unwrap() * prob.exp()
        }).fold(0.0f64, |s, e| s + e)
    }

    pub fn variance(&self) -> f64 {
        let ev = self.expected_value();
        self.iter_pmf().map(|(value, prob)| {
                (cast::<T, f64>(value.clone()).unwrap() - ev).powi(2) * prob.exp()
        }).fold(0.0, |s, e| s + e)
    }

    pub fn standard_deviation(&self) -> f64 {
        self.variance().sqrt()
    }
}

pub type CDFPMFIter<'a, T> = iter::Scan<slice::Iter<'a, (T, LogProb)>, LogProb, fn(&mut LogProb, &'a (T, LogProb)) -> Option<(&'a T, LogProb)>>;

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

    use itertools::Itertools;

    #[test]
    fn test_cdf() {
        let mut pmf = vec![(0.0, 0.1f64.ln())];
        for i in 0..9 {
            pmf.push((i as f64, 0.1f64.ln()));
        }
        println!("{:?}", pmf);

        let cdf = CDF::from_pmf(pmf.clone());
        println!("{:?}", cdf);
        for &(value, prob) in pmf.iter().skip(2) {
            assert_ulps_eq!(prob, cdf.get_pmf(&value).unwrap(), epsilon = 0.0000000000001);
        }
        assert_relative_eq!(cdf.total_prob(), 1.0f64.ln());
        assert_relative_eq!(cdf.get(&1.0).unwrap(), 0.3f64.ln(), epsilon = 0.00000001);
    }
}
<commit_msg>Fix potential numerical instability issue.<commit_after>use std::f64;
use std::iter;
use std::slice;

use num::traits::{cast, NumCast};
use itertools::Itertools;

use bio::stats::logprobs::{self, LogProb};

#[derive(Debug, Clone)]
pub struct CDF<T: PartialOrd> {
    inner: Vec<(T, LogProb)>
}

impl<T: PartialOrd> CDF<T> {
    /// Create CDF from given probability mass function (PMF). The PMF may contain duplicate values
    /// the probabilities of which are summed during generation of the CDF.
    pub fn from_pmf(mut entries: Vec<(T, LogProb)>) -> Self {
        entries.sort_by(|&(ref a, _), &(ref b, _)| a.partial_cmp(b).unwrap());
        let mut entries = entries.into_iter();
        let mut inner = vec![entries.next().unwrap()];
        for mut e in entries {
            let p = logprobs::add(inner.last().unwrap().1, e.1);
            if inner.last().unwrap().0 == e.0 {
                inner.last_mut().unwrap().1 = p;
            }
            else {
                e.1 = p;
                inner.push(e);
            }
        }
        let mut cdf = CDF {
            inner: inner
        };

        if relative_eq!(cdf.total_prob(), 0.0) && cdf.total_prob() > 0.0 {
            cdf.inner.last_mut().unwrap().1 = 0.0;
        }

        cdf
    }

    /// Create CDF from iterator. This can be used to replace the values of a CDF.
    pub fn from_cdf<I: Iterator<Item = (T, LogProb)>>(entries: I) -> Self {
        CDF { inner: entries.collect_vec() }
    }

    pub fn sample(mut self, n: usize) -> Self {
        if self.inner.len() <= n {
            self
        }
        else {
            let s = self.inner.len() / (n - 1);
            let last = self.inner.pop().unwrap();
            let mut inner = self.inner.into_iter().step(s).collect_vec();
            inner.push(last);
            CDF {
                inner: inner
            }
        }
    }

    pub fn iter(&self) -> slice::Iter<(T, f64)>{
        self.inner.iter()
    }

    pub fn iter_pmf<'a>(&'a self) -> CDFPMFIter<'a, T> {
        fn cdf_to_pmf<'a, G>(last_prob: &mut LogProb, e: &'a (G, LogProb)) -> Option<(&'a G, LogProb)> {
            let &(ref value, cdf_prob) = e;
            // last_prob can't be bigger than cdf_prob. If it is
            // this must be to instability, hence we can set prob to -inf, i.e. 0.
            let prob = if cdf_prob < *last_prob { f64::NEG_INFINITY } else { logprobs::sub(cdf_prob, *last_prob) };
            *last_prob = cdf_prob;
            Some((value, prob))
        }
        self.inner.iter().scan(f64::NEG_INFINITY, cdf_to_pmf)
    }

    /// Get cumulative probability for a given value. If the value is not present,
    /// return the probability of the previous value.
    pub fn get(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => self.inner[i].1,
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn get_pmf(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => if i > 0 { logprobs::sub(self.inner[i].1, self.inner[i - 1].1) } else { self.inner[0].1 },
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn total_prob(&self) -> LogProb {
        let &(_, prob) = self.inner.last().unwrap();
        prob
    }

    /// Return maximum a posteriori probability estimate (MAP).
    pub fn map(&self) -> &T {
        let mut max = self.iter_pmf().next().unwrap();
        for e in self.iter_pmf() {
            if e.1 >= max.1 {
                max = e;
            }
        }
        &max.0
    }

    pub fn credible_interval(&self) -> (&T, &T) {
        let lower = self.inner.binary_search_by(|&(_, p)| p.partial_cmp(&0.025f64.ln()).unwrap()).unwrap_or_else(|i| i);
        let upper = self.inner.binary_search_by(|&(_, p)| p.partial_cmp(&0.975f64.ln()).unwrap()).unwrap_or_else(|i| i - 1);

        (&self.inner[lower].0, &self.inner[upper].0)
    }

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

impl<T: NumCast + Clone + PartialOrd> CDF<T> {
    pub fn expected_value(&self) -> f64 {
        self.iter_pmf().map(|(value, prob)| {
            cast::<T, f64>(value.clone()).unwrap() * prob.exp()
        }).fold(0.0f64, |s, e| s + e)
    }

    pub fn variance(&self) -> f64 {
        let ev = self.expected_value();
        self.iter_pmf().map(|(value, prob)| {
                (cast::<T, f64>(value.clone()).unwrap() - ev).powi(2) * prob.exp()
        }).fold(0.0, |s, e| s + e)
    }

    pub fn standard_deviation(&self) -> f64 {
        self.variance().sqrt()
    }
}

pub type CDFPMFIter<'a, T> = iter::Scan<slice::Iter<'a, (T, LogProb)>, LogProb, fn(&mut LogProb, &'a (T, LogProb)) -> Option<(&'a T, LogProb)>>;

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

    use itertools::Itertools;

    #[test]
    fn test_cdf() {
        let mut pmf = vec![(0.0, 0.1f64.ln())];
        for i in 0..9 {
            pmf.push((i as f64, 0.1f64.ln()));
        }
        println!("{:?}", pmf);

        let cdf = CDF::from_pmf(pmf.clone());
        println!("{:?}", cdf);
        for &(value, prob) in pmf.iter().skip(2) {
            assert_ulps_eq!(prob, cdf.get_pmf(&value).unwrap(), epsilon = 0.0000000000001);
        }
        assert_relative_eq!(cdf.total_prob(), 1.0f64.ln());
        assert_relative_eq!(cdf.get(&1.0).unwrap(), 0.3f64.ln(), epsilon = 0.00000001);
    }
}
<|endoftext|>


<commit_before>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::path::Path;
use std::result::Result;

use module::todo::TodoModule;

mod todo;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    fn mk(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub type ModuleResult = Result<(), ModuleError>;

pub trait Module {

    fn new(rt : &Runtime) -> Self;
    fn callnames() -> &'static [&'static str];
    fn name(&self) -> &'static str;

    fn execute(&self, rt : &Runtime) -> ModuleResult;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

}

pub mod file {

    use regex::Regex;

    pub struct ParserError {
        summary: String,
        parsertext: String,
        index: i32,
        explanation: Option<String>,
    }

    impl ParserError {
        fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError {
            ParserError {
                summary: String::from(sum),
                parsertext: text,
                index: idx,
                explanation: Some(String::from(expl)),
            }
        }

        fn short(sum: &'static str, text: String, idx: i32) -> ParserError {
            ParserError {
                summary: String::from(sum),
                parsertext: text,
                index: idx,
                explanation: None
            }
        }
    }

    pub mod header {

        pub enum FileHeaderSpec {
            Null,
            Bool,
            Integer,
            UInteger,
            Float,
            Text,
            Key { name: String, value_type: Box<FileHeaderSpec> },
            Array { allowed_types: Box<Vec<FileHeaderSpec>> },
        }

        pub enum FileHeaderData {
            Null,
            Bool(bool),
            Integer(i64),
            UInteger(u64),
            Float(f64),
            Text(String),
            Key { name: String, value: Box<FileHeaderData> },
            Array { values: Box<Vec<FileHeaderData>> },
        }

        pub trait FileHeaderParser : Sized {
            fn new(spec: &FileHeaderSpec) -> Self;
            fn read(&self, string: &String) -> Result<FileHeaderData, super::ParserError>;
            fn write(&self, data: &FileHeaderData) -> Result<String, super::ParserError>;
        }

    }

    pub trait FileData : Sized {
        fn get_fulltext(&self) -> String;
        fn get_abbrev(&self) -> String;
    }

    pub trait FileDataParser : Sized {
        fn new() -> FileDataParser;
        fn read(&self, string: String) -> FileData;
        fn write(&self, data: &FileData) -> Result<String, ParserError>;
    }

    pub type HeaderDataTpl = (Option<String>, Option<String>);

    pub fn divide_text(text: String) -> Result<HeaderDataTpl, ParserError> {
        let re = Regex::new(r"(?m)^\-\-\-$\n(.*)^\-\-\-$\n(.*)").unwrap();

        let captures = re.captures(&text[..]).unwrap_or(
            return Err(ParserError::new("Cannot run regex on text",
                                        text.clone(), 0,
                                        "Cannot run regex on text to divide it into header and content."))
        );

        if captures.len() != 2 {
            return Err(ParserError::new("Unexpected Regex output",
                                        text.clone(), 0,
                                        "The regex to divide text into header and content had an unexpected output."))
        }

        let header  = captures.at(0).map(|s| String::from(s));
        let content = captures.at(1).map(|s| String::from(s));
        Ok((header, content))
    }

}
<commit_msg>Move header types/traits outside own module<commit_after>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::path::Path;
use std::result::Result;

use module::todo::TodoModule;

mod todo;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    fn mk(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub type ModuleResult = Result<(), ModuleError>;

pub trait Module {

    fn new(rt : &Runtime) -> Self;
    fn callnames() -> &'static [&'static str];
    fn name(&self) -> &'static str;

    fn execute(&self, rt : &Runtime) -> ModuleResult;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

}

pub mod file {

    use regex::Regex;

    pub struct ParserError {
        summary: String,
        parsertext: String,
        index: i32,
        explanation: Option<String>,
    }

    impl ParserError {
        fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError {
            ParserError {
                summary: String::from(sum),
                parsertext: text,
                index: idx,
                explanation: Some(String::from(expl)),
            }
        }

        fn short(sum: &'static str, text: String, idx: i32) -> ParserError {
            ParserError {
                summary: String::from(sum),
                parsertext: text,
                index: idx,
                explanation: None
            }
        }
    }

    pub enum FileHeaderSpec {
        Null,
        Bool,
        Integer,
        UInteger,
        Float,
        Text,
        Key { name: String, value_type: Box<FileHeaderSpec> },
        Array { allowed_types: Box<Vec<FileHeaderSpec>> },
    }

    pub enum FileHeaderData {
        Null,
        Bool(bool),
        Integer(i64),
        UInteger(u64),
        Float(f64),
        Text(String),
        Key { name: String, value: Box<FileHeaderData> },
        Array { values: Box<Vec<FileHeaderData>> },
    }

    pub trait FileHeaderParser : Sized {
        fn new(spec: &FileHeaderSpec) -> Self;
        fn read(&self, string: &String) -> Result<FileHeaderData, ParserError>;
        fn write(&self, data: &FileHeaderData) -> Result<String, ParserError>;
    }

    pub trait FileData : Sized {
        fn get_fulltext(&self) -> String;
        fn get_abbrev(&self) -> String;
    }

    pub trait FileDataParser : Sized {
        fn new() -> FileDataParser;
        fn read(&self, string: String) -> FileData;
        fn write(&self, data: &FileData) -> Result<String, ParserError>;
    }

    pub type HeaderDataTpl = (Option<String>, Option<String>);

    pub fn divide_text(text: String) -> Result<HeaderDataTpl, ParserError> {
        let re = Regex::new(r"(?m)^\-\-\-$\n(.*)^\-\-\-$\n(.*)").unwrap();

        let captures = re.captures(&text[..]).unwrap_or(
            return Err(ParserError::new("Cannot run regex on text",
                                        text.clone(), 0,
                                        "Cannot run regex on text to divide it into header and content."))
        );

        if captures.len() != 2 {
            return Err(ParserError::new("Unexpected Regex output",
                                        text.clone(), 0,
                                        "The regex to divide text into header and content had an unexpected output."))
        }

        let header  = captures.at(0).map(|s| String::from(s));
        let content = captures.at(1).map(|s| String::from(s));
        Ok((header, content))
    }

}
<|endoftext|>


<commit_before>//! Utility functions for utf8 string slices.
//!
//! This module provides various utility functions that operate on string
//! slices in ways compatible with Ropey.  They may be useful when building
//! additional functionality on top of Ropey.

pub(crate) use str_indices::chars::count as count_chars;
pub use str_indices::chars::from_byte_idx as byte_to_char_idx;
pub use str_indices::chars::to_byte_idx as char_to_byte_idx;
pub(crate) use str_indices::utf16::count_surrogates as count_utf16_surrogates;
pub(crate) use str_indices::utf16::from_byte_idx as utf16_code_unit_to_char_idx;

// Determine which line implementation to use.
#[cfg(feature = "unicode_lines")]
use str_indices::lines;
#[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
use str_indices::lines_crlf as lines;
#[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
use str_indices::lines_lf as lines;

pub(crate) use self::lines::count_breaks as count_line_breaks;
pub use self::lines::from_byte_idx as byte_to_line_idx;
pub use self::lines::to_byte_idx as line_to_byte_idx;

/// Converts from char-index to line-index in a string slice.
///
/// This is equivalent to counting the line endings before the given char.
///
/// Any past-the-end index will return the last line index.
///
/// Runs in O(N) time.
#[inline]
pub fn char_to_line_idx(text: &str, char_idx: usize) -> usize {
    str_indices::lines::from_byte_idx(text, str_indices::chars::to_byte_idx(text, char_idx))
}

/// Converts from line-index to char-index in a string slice.
///
/// More specifically, this returns the index of the first char of the given line.
///
/// Any past-the-end index will return the one-past-the-end char index.
///
/// Runs in O(N) time.
#[inline]
pub fn line_to_char_idx(text: &str, line_idx: usize) -> usize {
    str_indices::chars::from_byte_idx(text, str_indices::lines::to_byte_idx(text, line_idx))
}

//-------------------------------------------------------------

pub(crate) fn byte_to_utf16_surrogate_idx(text: &str, byte_idx: usize) -> usize {
    let mut i = byte_idx;
    while !text.is_char_boundary(i) {
        i -= 1;
    }
    str_indices::utf16::count_surrogates(&text[..i])
}

/// Returns the byte position just after the second-to-last line break
/// in `text`, or zero of there is no second-to-last line break.
///
/// This function is narrow in scope, only being used for iterating
/// backwards over the lines of a `str`.
pub(crate) fn prev_line_end_char_idx(text: &str) -> usize {
    let mut itr = text.bytes().enumerate().rev();

    // This code always needs to execute, but the variable is only needed
    // for certain feature sets, so silence the warning.
    #[allow(unused_variables)]
    let first_byte = if let Some((_, byte)) = itr.next() {
        byte
    } else {
        return 0;
    };

    while let Some((idx, byte)) = itr.next() {
        match byte {
            0x0A => {
                return idx + 1;
            }
            0x0D =>
            {
                #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
                if first_byte != 0x0A {
                    return idx + 1;
                }
            }
            0x0B | 0x0C => {
                #[cfg(feature = "unicode_lines")]
                return idx + 1;
            }
            0x85 =>
            {
                #[cfg(feature = "unicode_lines")]
                if let Some((_, 0xC2)) = itr.next() {
                    return idx + 1;
                }
            }
            0xA8 | 0xA9 =>
            {
                #[cfg(feature = "unicode_lines")]
                if let Some((_, 0x80)) = itr.next() {
                    if let Some((_, 0xE2)) = itr.next() {
                        return idx + 1;
                    }
                }
            }
            _ => {}
        }
    }

    return 0;
}

/// Returns whether the given string ends in a line break or not.
#[inline]
pub(crate) fn ends_with_line_break(text: &str) -> bool {
    if text.is_empty() {
        return false;
    }
    // Find the starting boundary of the last codepoint.
    let mut i = text.len() - 1;
    while !text.is_char_boundary(i) {
        i -= 1;
    }

    // Check if the last codepoint is a line break.

    #[cfg(feature = "unicode_lines")]
    return matches!(
        &text[i..],
        "\u{000A}" | "\u{000B}" | "\u{000C}" | "\u{000D}" | "\u{0085}" | "\u{2028}" | "\u{2029}"
    );

    #[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
    return matches!(&text[i..], "\u{000A}" | "\u{000D}");

    #[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
    return &text[i..] == "\u{000A}";
}

//======================================================================

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

    #[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
    #[test]
    fn prev_line_end_char_idx_lf_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
    #[test]
    fn prev_line_end_char_idx_crlf_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(9, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[cfg(feature = "unicode_lines")]
    #[test]
    fn prev_line_end_char_idx_unicode_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(32, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(22, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(17, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(13, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(9, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[test]
    fn ends_with_line_break_01() {
        assert_eq!(true, ends_with_line_break("\n"));

        #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
        assert_eq!(true, ends_with_line_break("\r"));

        #[cfg(feature = "unicode_lines")]
        {
            assert_eq!(true, ends_with_line_break("\u{000A}"));
            assert_eq!(true, ends_with_line_break("\u{000B}"));
            assert_eq!(true, ends_with_line_break("\u{000C}"));
            assert_eq!(true, ends_with_line_break("\u{000D}"));
            assert_eq!(true, ends_with_line_break("\u{0085}"));
            assert_eq!(true, ends_with_line_break("\u{2028}"));
            assert_eq!(true, ends_with_line_break("\u{2029}"));
        }
    }

    #[test]
    fn ends_with_line_break_02() {
        assert_eq!(true, ends_with_line_break("Hi there!\n"));

        #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
        assert_eq!(true, ends_with_line_break("Hi there!\r"));

        #[cfg(feature = "unicode_lines")]
        {
            assert_eq!(true, ends_with_line_break("Hi there!\u{000A}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000B}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000C}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000D}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{0085}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{2028}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{2029}"));
        }
    }

    #[test]
    fn ends_with_line_break_03() {
        assert_eq!(false, ends_with_line_break(""));
        assert_eq!(false, ends_with_line_break("a"));
        assert_eq!(false, ends_with_line_break("Hi there!"));
    }

    #[test]
    fn ends_with_line_break_04() {
        assert_eq!(false, ends_with_line_break("\na"));
        assert_eq!(false, ends_with_line_break("\ra"));
        assert_eq!(false, ends_with_line_break("\u{000A}a"));
        assert_eq!(false, ends_with_line_break("\u{000B}a"));
        assert_eq!(false, ends_with_line_break("\u{000C}a"));
        assert_eq!(false, ends_with_line_break("\u{000D}a"));
        assert_eq!(false, ends_with_line_break("\u{0085}a"));
        assert_eq!(false, ends_with_line_break("\u{2028}a"));
        assert_eq!(false, ends_with_line_break("\u{2029}a"));
    }
}
<commit_msg>Fix silly bug with utf16 code units conversions.<commit_after>//! Utility functions for utf8 string slices.
//!
//! This module provides various utility functions that operate on string
//! slices in ways compatible with Ropey.  They may be useful when building
//! additional functionality on top of Ropey.

pub(crate) use str_indices::chars::count as count_chars;
pub use str_indices::chars::from_byte_idx as byte_to_char_idx;
pub use str_indices::chars::to_byte_idx as char_to_byte_idx;
pub(crate) use str_indices::utf16::count_surrogates as count_utf16_surrogates;

// Determine which line implementation to use.
#[cfg(feature = "unicode_lines")]
use str_indices::lines;
#[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
use str_indices::lines_crlf as lines;
#[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
use str_indices::lines_lf as lines;

pub(crate) use self::lines::count_breaks as count_line_breaks;
pub use self::lines::from_byte_idx as byte_to_line_idx;
pub use self::lines::to_byte_idx as line_to_byte_idx;

/// Converts from char-index to line-index in a string slice.
///
/// This is equivalent to counting the line endings before the given char.
///
/// Any past-the-end index will return the last line index.
///
/// Runs in O(N) time.
#[inline]
pub fn char_to_line_idx(text: &str, char_idx: usize) -> usize {
    str_indices::lines::from_byte_idx(text, str_indices::chars::to_byte_idx(text, char_idx))
}

/// Converts from line-index to char-index in a string slice.
///
/// More specifically, this returns the index of the first char of the given line.
///
/// Any past-the-end index will return the one-past-the-end char index.
///
/// Runs in O(N) time.
#[inline]
pub fn line_to_char_idx(text: &str, line_idx: usize) -> usize {
    str_indices::chars::from_byte_idx(text, str_indices::lines::to_byte_idx(text, line_idx))
}

//-------------------------------------------------------------

pub(crate) fn byte_to_utf16_surrogate_idx(text: &str, byte_idx: usize) -> usize {
    let mut i = byte_idx;
    while !text.is_char_boundary(i) {
        i -= 1;
    }
    str_indices::utf16::count_surrogates(&text[..i])
}

pub(crate) fn utf16_code_unit_to_char_idx(text: &str, utf16_idx: usize) -> usize {
    str_indices::chars::from_byte_idx(text, str_indices::utf16::to_byte_idx(text, utf16_idx))
}

/// Returns the byte position just after the second-to-last line break
/// in `text`, or zero of there is no second-to-last line break.
///
/// This function is narrow in scope, only being used for iterating
/// backwards over the lines of a `str`.
pub(crate) fn prev_line_end_char_idx(text: &str) -> usize {
    let mut itr = text.bytes().enumerate().rev();

    // This code always needs to execute, but the variable is only needed
    // for certain feature sets, so silence the warning.
    #[allow(unused_variables)]
    let first_byte = if let Some((_, byte)) = itr.next() {
        byte
    } else {
        return 0;
    };

    while let Some((idx, byte)) = itr.next() {
        match byte {
            0x0A => {
                return idx + 1;
            }
            0x0D =>
            {
                #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
                if first_byte != 0x0A {
                    return idx + 1;
                }
            }
            0x0B | 0x0C => {
                #[cfg(feature = "unicode_lines")]
                return idx + 1;
            }
            0x85 =>
            {
                #[cfg(feature = "unicode_lines")]
                if let Some((_, 0xC2)) = itr.next() {
                    return idx + 1;
                }
            }
            0xA8 | 0xA9 =>
            {
                #[cfg(feature = "unicode_lines")]
                if let Some((_, 0x80)) = itr.next() {
                    if let Some((_, 0xE2)) = itr.next() {
                        return idx + 1;
                    }
                }
            }
            _ => {}
        }
    }

    return 0;
}

/// Returns whether the given string ends in a line break or not.
#[inline]
pub(crate) fn ends_with_line_break(text: &str) -> bool {
    if text.is_empty() {
        return false;
    }
    // Find the starting boundary of the last codepoint.
    let mut i = text.len() - 1;
    while !text.is_char_boundary(i) {
        i -= 1;
    }

    // Check if the last codepoint is a line break.

    #[cfg(feature = "unicode_lines")]
    return matches!(
        &text[i..],
        "\u{000A}" | "\u{000B}" | "\u{000C}" | "\u{000D}" | "\u{0085}" | "\u{2028}" | "\u{2029}"
    );

    #[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
    return matches!(&text[i..], "\u{000A}" | "\u{000D}");

    #[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
    return &text[i..] == "\u{000A}";
}

//======================================================================

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

    #[cfg(not(any(feature = "cr_lines", feature = "unicode_lines")))]
    #[test]
    fn prev_line_end_char_idx_lf_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[cfg(all(feature = "cr_lines", not(feature = "unicode_lines")))]
    #[test]
    fn prev_line_end_char_idx_crlf_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(9, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[cfg(feature = "unicode_lines")]
    #[test]
    fn prev_line_end_char_idx_unicode_01() {
        let mut text = "\u{000A}Hello\u{000D}\u{000A}\u{000D}せ\u{000B}か\u{000C}い\u{0085}. \
                        There\u{2028}is something.\u{2029}";

        assert_eq!(48, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(32, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(22, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(17, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(13, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(9, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(8, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(1, text.len());
        text = &text[..prev_line_end_char_idx(text)];
        assert_eq!(0, text.len());
    }

    #[test]
    fn ends_with_line_break_01() {
        assert_eq!(true, ends_with_line_break("\n"));

        #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
        assert_eq!(true, ends_with_line_break("\r"));

        #[cfg(feature = "unicode_lines")]
        {
            assert_eq!(true, ends_with_line_break("\u{000A}"));
            assert_eq!(true, ends_with_line_break("\u{000B}"));
            assert_eq!(true, ends_with_line_break("\u{000C}"));
            assert_eq!(true, ends_with_line_break("\u{000D}"));
            assert_eq!(true, ends_with_line_break("\u{0085}"));
            assert_eq!(true, ends_with_line_break("\u{2028}"));
            assert_eq!(true, ends_with_line_break("\u{2029}"));
        }
    }

    #[test]
    fn ends_with_line_break_02() {
        assert_eq!(true, ends_with_line_break("Hi there!\n"));

        #[cfg(any(feature = "cr_lines", feature = "unicode_lines"))]
        assert_eq!(true, ends_with_line_break("Hi there!\r"));

        #[cfg(feature = "unicode_lines")]
        {
            assert_eq!(true, ends_with_line_break("Hi there!\u{000A}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000B}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000C}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{000D}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{0085}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{2028}"));
            assert_eq!(true, ends_with_line_break("Hi there!\u{2029}"));
        }
    }

    #[test]
    fn ends_with_line_break_03() {
        assert_eq!(false, ends_with_line_break(""));
        assert_eq!(false, ends_with_line_break("a"));
        assert_eq!(false, ends_with_line_break("Hi there!"));
    }

    #[test]
    fn ends_with_line_break_04() {
        assert_eq!(false, ends_with_line_break("\na"));
        assert_eq!(false, ends_with_line_break("\ra"));
        assert_eq!(false, ends_with_line_break("\u{000A}a"));
        assert_eq!(false, ends_with_line_break("\u{000B}a"));
        assert_eq!(false, ends_with_line_break("\u{000C}a"));
        assert_eq!(false, ends_with_line_break("\u{000D}a"));
        assert_eq!(false, ends_with_line_break("\u{0085}a"));
        assert_eq!(false, ends_with_line_break("\u{2028}a"));
        assert_eq!(false, ends_with_line_break("\u{2029}a"));
    }
}
<|endoftext|>


<commit_before>extern crate gluon;
#[macro_use]
extern crate gluon_codegen;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate gluon_vm;

mod init;

use gluon::vm::{self, ExternModule};
use gluon::{import, Compiler, Thread};
use init::new_vm;

#[derive(Debug, PartialEq, Getable, Pushable, VmType, Serialize, Deserialize)]
#[gluon(vm_type = "types.Struct")]
struct Struct {
    string: String,
    number: u32,
    vec: Vec<f64>,
}

fn load_struct_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        new_struct => primitive!(1 new_struct),
    };

    ExternModule::new(vm, module)
}

fn new_struct(_: ()) -> Struct {
    Struct {
        string: "hello".to_owned(),
        number: 1,
        vec: vec![1.0, 2.0, 3.0],
    }
}

#[test]
fn normal_struct() {
    let vm = new_vm();
    let mut compiler = Compiler::new();

    // must be generated by hand because of bug in make_source (see #542)
    let src = r#"
        type Struct = { string: String, number: Int, vec: Array Float }
        { Struct }
    "#;

    compiler.load_script(&vm, "types", &src).unwrap();
    import::add_extern_module(&vm, "functions", load_struct_mod);

    let script = r#"
        let { new_struct } = import! functions

        new_struct ()
    "#;

    let (s, _) = compiler
        .run_expr::<Struct>(&vm, "test", script)
        .unwrap_or_else(|why| panic!("{}", why));

    assert_eq!(
        s,
        Struct {
            string: "hello".into(),
            number: 1,
            vec: vec![1.0, 2.0, 3.0],
        }
    );
}
<commit_msg>test(codegen): Add test for roundtripping a newtype<commit_after>extern crate gluon;
#[macro_use]
extern crate gluon_codegen;
#[macro_use]
extern crate gluon_vm;

mod init;

use gluon::vm::{self, ExternModule};
use gluon::{import, Compiler, Thread};
use init::new_vm;

#[derive(Debug, PartialEq, Getable, Pushable, VmType)]
struct Struct {
    string: String,
    number: u32,
    vec: Vec<f64>,
}

fn load_struct_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        new_struct => primitive!(1 new_struct),
    };

    ExternModule::new(vm, module)
}

fn new_struct(_: ()) -> Struct {
    Struct {
        string: "hello".to_owned(),
        number: 1,
        vec: vec![1.0, 2.0, 3.0],
    }
}

#[test]
fn normal_struct() {
    let vm = new_vm();
    let mut compiler = Compiler::new();
    import::add_extern_module(&vm, "functions", load_struct_mod);

    let script = r#"
        let { new_struct } = import! functions

        new_struct ()
    "#;

    let (s, _) = compiler
        .run_expr::<Struct>(&vm, "test", script)
        .unwrap_or_else(|why| panic!("{}", why));

    assert_eq!(
        s,
        Struct {
            string: "hello".into(),
            number: 1,
            vec: vec![1.0, 2.0, 3.0],
        }
    );
}

#[derive(Debug, PartialEq, VmType, Pushable, Getable)]
struct Newtype(Struct);

fn load_newtype_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        newtype_id => primitive!(1 newtype_id),
    };

    ExternModule::new(vm, module)
}

fn newtype_id(val: Newtype) -> Newtype {
    val
}

#[test]
fn newtype() {
    let vm = new_vm();
    let mut compiler = Compiler::new();
    import::add_extern_module(&vm, "functions", load_newtype_mod);

    // newtypes should map to the inner type
    let script = r#"
        let { newtype_id } = import! functions

        newtype_id { string = "test", number = 42, vec = [1.0, 1.0, 2.0, 3.0, 5.0] }
    "#;

    let (s, _) = compiler
        .run_expr::<Newtype>(&vm, "test", script)
        .unwrap_or_else(|why| panic!("{}", why));

    assert_eq!(
        s,
        Newtype(Struct {
            string: "test".into(),
            number: 42,
            vec: vec![1.0, 1.0, 2.0, 3.0, 5.0],
        })
    );
}
<|endoftext|>


<commit_before>//! Commands for `budget`

#[derive(Debug, PartialEq)]
pub enum Command {
    /// Setup is for generating the configuration
    Setup(i64, u8),
    /// Status, the default command if a working config exists, simply reports the status of the
    /// budget account to the user
    Status,
    /// OneTime creates a one-time transaction
    OneTime(i64),
    /// Recurring adds a recurring transaction
    Recurring(i64, u8),
    /// Remove destroys an exsisting recurring transaction, by ID
    Remove(i64),
    /// List lists all existing recurring transactions, including ID
    List,
}

/// Check if a command is valid
fn is_command_valid(command: &str) -> bool {
    match command {
        "setup" => true,
        "status" => true,
        "spend" => true,
        "tip" => true,
        "expense" => true,
        "income" => true,
        "remove" => true,
        "list" => true,
        _ => false
    }
}

/// Given a tuple of one, two, or three arguments, decide which Command is being asked for and
/// parse its arguments
pub fn args_to_command(args: (Option<&str>, Option<&str>, Option<&str>)) ->
                       Result<Command, String>
    {
        // These three Strings will be the destinations for unwrapped version of the input
        let arg0: String;
        let arg1: String;
        let arg2: String;

        // These variables will be used to hold arguments, if we need them
        let famount: f64;
        let amount: i64;
        let day: u8;

        // Match on the first argument, the command
        match args.0 {
            // If no command was given, we simply need to return the status of the account
            None => return Ok(Command::Status),
            // Otherwise, we have a command and need to try to parse it
            Some(string) => arg0 = String::from(string.as_ref()).to_lowercase(),
        }

        // Make sure the command is valid; if not, return an error.
        match is_command_valid(&arg0) {
            true => (),
            false => return Err(String::from("Invalid command ") + &arg0)
        };

        // Match arg1 against all the commands that take no arguments
        // If it matches none of these, we can proceed to the next argument
        match arg0.as_ref() {
            "status" => return Ok(Command::Status),
            "list" => return Ok(Command::List),
            _ => ()
        }

        // Every command that requires argument needs an i64, an amount of cents, as its first
        // argument.
        match args.1 {
            // If we don't have a second argument, complain
            None => return Err(String::from("Missing required argument: amount.")),
            // If we do, just unwrap it into arg1
            Some(string) => arg1 = String::from(string.as_ref()).to_lowercase(),
        }

        // Check if we're running a Remove. It has different parsing requirements
        if &arg0 == "remove" {
            // For Remove, we parse the second arg directly to an i64 and then return
            match arg1.parse::<i64>() {
                Ok(n) => amount = n,
                Err(r) => return Err(String::from("Argument id was not valid: ")
                                     + r.to_string().as_ref()),
            }
            // We're done, because Remove doesn't require another argument
            return Ok(Command::Remove(amount));
        }

        // Now, we can parse it into the famount f64, because we know we are working with
        // an actual amount
        match arg1.parse::<f64>() {
            Ok(n) => famount = n,
            Err(r) => return Err(String::from("Argument amount was not valid: ")
                                 + r.to_string().as_ref()),
        }

        // Now we need to convert the float number of dollars to an int number of cents
        // f64 as i64 rounds towards 0
        amount = (famount * 100.0) as i64;

        // One last thing to check. If we are adding a recurring transaction, we need to
        //  parse the final argument; otherwise, we're done.
        match arg0.as_ref() {
            "spend" => return Ok(Command::OneTime(-amount)),
            "tip" => return Ok(Command::OneTime(amount)),
            // we know we're not running Remove because we checked it before
            _ => ()
        }

        // At this point we've returned unless we're adding a recurring transaction, so
        //  we need to go ahead and do the parsing for that
        match args.2 {
            // If we don't have a third argument, complain
            None => return Err(String::from("Missing required argument: day.")),
            // If we do, just unwrap it into arg2
            Some(string) => arg2 = String::from(string.as_ref()).to_lowercase(),
        }

        // Parse the third argument into an i8
        match arg2.parse::<u8>() {
            Ok(n) => day = n,
            Err(r) => return Err(String::from("Argument day was not valid: ")
                                 + r.to_string().as_ref()),
        }

        // If we've made it to this point, we're done.
        match arg0.as_ref() {
            "income" => return Ok(Command::Recurring(amount, day)),
            "expense" => return Ok(Command::Recurring(-amount, day)),
            "setup" => return Ok(Command::Setup(amount, day)),
            _ => return Err(String::from("Unknown command: ") + arg0.as_ref()),
        }

    }

<commit_msg>Clarify purpose of commands.rs<commit_after>//! Commands and command parsing for `budget`

#[derive(Debug, PartialEq)]
pub enum Command {
    /// Setup is for generating the configuration
    Setup(i64, u8),
    /// Status, the default command if a working config exists, simply reports the status of the
    /// budget account to the user
    Status,
    /// OneTime creates a one-time transaction
    OneTime(i64),
    /// Recurring adds a recurring transaction
    Recurring(i64, u8),
    /// Remove destroys an exsisting recurring transaction, by ID
    Remove(i64),
    /// List lists all existing recurring transactions, including ID
    List,
}

/// Check if a command is valid
fn is_command_valid(command: &str) -> bool {
    match command {
        "setup" => true,
        "status" => true,
        "spend" => true,
        "tip" => true,
        "expense" => true,
        "income" => true,
        "remove" => true,
        "list" => true,
        _ => false
    }
}

/// Given a tuple of one, two, or three arguments, decide which Command is being asked for and
/// parse its arguments
pub fn args_to_command(args: (Option<&str>, Option<&str>, Option<&str>)) ->
                       Result<Command, String>
    {
        // These three Strings will be the destinations for unwrapped version of the input
        let arg0: String;
        let arg1: String;
        let arg2: String;

        // These variables will be used to hold arguments, if we need them
        let famount: f64;
        let amount: i64;
        let day: u8;

        // Match on the first argument, the command
        match args.0 {
            // If no command was given, we simply need to return the status of the account
            None => return Ok(Command::Status),
            // Otherwise, we have a command and need to try to parse it
            Some(string) => arg0 = String::from(string.as_ref()).to_lowercase(),
        }

        // Make sure the command is valid; if not, return an error.
        match is_command_valid(&arg0) {
            true => (),
            false => return Err(String::from("Invalid command ") + &arg0)
        };

        // Match arg1 against all the commands that take no arguments
        // If it matches none of these, we can proceed to the next argument
        match arg0.as_ref() {
            "status" => return Ok(Command::Status),
            "list" => return Ok(Command::List),
            _ => ()
        }

        // Every command that requires argument needs an i64, an amount of cents, as its first
        // argument.
        match args.1 {
            // If we don't have a second argument, complain
            None => return Err(String::from("Missing required argument: amount.")),
            // If we do, just unwrap it into arg1
            Some(string) => arg1 = String::from(string.as_ref()).to_lowercase(),
        }

        // Check if we're running a Remove. It has different parsing requirements
        if &arg0 == "remove" {
            // For Remove, we parse the second arg directly to an i64 and then return
            match arg1.parse::<i64>() {
                Ok(n) => amount = n,
                Err(r) => return Err(String::from("Argument id was not valid: ")
                                     + r.to_string().as_ref()),
            }
            // We're done, because Remove doesn't require another argument
            return Ok(Command::Remove(amount));
        }

        // Now, we can parse it into the famount f64, because we know we are working with
        // an actual amount
        match arg1.parse::<f64>() {
            Ok(n) => famount = n,
            Err(r) => return Err(String::from("Argument amount was not valid: ")
                                 + r.to_string().as_ref()),
        }

        // Now we need to convert the float number of dollars to an int number of cents
        // f64 as i64 rounds towards 0
        amount = (famount * 100.0) as i64;

        // One last thing to check. If we are adding a recurring transaction, we need to
        //  parse the final argument; otherwise, we're done.
        match arg0.as_ref() {
            "spend" => return Ok(Command::OneTime(-amount)),
            "tip" => return Ok(Command::OneTime(amount)),
            // we know we're not running Remove because we checked it before
            _ => ()
        }

        // At this point we've returned unless we're adding a recurring transaction, so
        //  we need to go ahead and do the parsing for that
        match args.2 {
            // If we don't have a third argument, complain
            None => return Err(String::from("Missing required argument: day.")),
            // If we do, just unwrap it into arg2
            Some(string) => arg2 = String::from(string.as_ref()).to_lowercase(),
        }

        // Parse the third argument into an i8
        match arg2.parse::<u8>() {
            Ok(n) => day = n,
            Err(r) => return Err(String::from("Argument day was not valid: ")
                                 + r.to_string().as_ref()),
        }

        // If we've made it to this point, we're done.
        match arg0.as_ref() {
            "income" => return Ok(Command::Recurring(amount, day)),
            "expense" => return Ok(Command::Recurring(-amount, day)),
            "setup" => return Ok(Command::Setup(amount, day)),
            _ => return Err(String::from("Unknown command: ") + arg0.as_ref()),
        }

    }

<|endoftext|>


<commit_before>/*!
factorizes a matrix of times and observed values
into ...

use it by repeatedly calling `update` with data
and inspecting `hidden` and `weights`.
*/

extern crate num;
use self::num::{Zero};

extern crate nalgebra;
use self::nalgebra::{DMat};

pub struct OnlineNMF<FloatT> {
    /// maps hidden variables (= rows) to observed variables (= cols).
    /// changes on every `update`.
    /// stays constant in size.
    pub hidden: DMat<FloatT>,
    /// maps times (= rows) to hidden variables (= cols).
    /// changes on every `update`.
    /// inspect this.
    /// will grow in size.
    pub weights: DMat<FloatT>,
}

impl<FloatT: Zero + Clone + Copy> OnlineNMF<FloatT> {
    /// returns an online nonnegative matrix factorization
    /// that is supposed to find `nhidden` hidden variables
    /// when repeatedly being `update`d with columns of `nobserved` variables
    pub fn new(nobserved: usize, nhidden: usize) -> OnlineNMF<FloatT> {
        OnlineNMF {
            hidden: DMat::new_zeros(nhidden, nobserved),
            weights: DMat::new_zeros(0, nhidden)
        }
    }

    /// returns the number of observed variables
    #[inline]
    pub fn nobserved(&self) -> usize {
        self.hidden.ncols()
    }

    /// returns the number of hidden variables
    #[inline]
    pub fn nhidden(&self) -> usize {
        self.hidden.nrows()
    }

    pub fn update(&mut self, new_observed_columns: &DMat<FloatT>) {
        assert_eq!(self.nobserved(), new_observed_columns.nrows());

        // do nothing for now
    }
}
<commit_msg>improve docstrings<commit_after>/*!
factorizes a matrix of times and observed values
into ...

use it by repeatedly calling `update` with data
and inspecting `hidden` and `weights`.
*/

extern crate num;
use self::num::{Zero};

extern crate nalgebra;
use self::nalgebra::{DMat};

pub struct OnlineNMF<FloatT> {
    /// maps hidden variables (one per row) to observed variables (one per column).
    /// changes on every `update`.
    /// stays constant in size.
    pub hidden: DMat<FloatT>,
    /// maps times (one per row) to hidden variables (one per column).
    /// changes on every `update`.
    /// inspect this.
    /// will grow in size.
    pub weights: DMat<FloatT>,
}

impl<FloatT: Zero + Clone + Copy> OnlineNMF<FloatT> {
    /// returns an online nonnegative matrix factorization
    /// that is supposed to find `nhidden` hidden variables
    /// when repeatedly being `update`d with columns of `nobserved` variables
    pub fn new(nobserved: usize, nhidden: usize) -> OnlineNMF<FloatT> {
        OnlineNMF {
            hidden: DMat::new_zeros(nhidden, nobserved),
            weights: DMat::new_zeros(0, nhidden)
        }
    }

    /// returns the number of observed variables
    #[inline]
    pub fn nobserved(&self) -> usize {
        self.hidden.ncols()
    }

    /// returns the number of hidden variables
    #[inline]
    pub fn nhidden(&self) -> usize {
        self.hidden.nrows()
    }

    pub fn update(&mut self, new_observed_columns: &DMat<FloatT>) {
        assert_eq!(self.nobserved(), new_observed_columns.nrows());

        // do nothing for now
    }
}
<|endoftext|>