<commit_before>use std::str;
use std::hashmap::HashMap;

use log::{HTTPLogRecord, LogProcessor};

// TODO: Should be moved outside
static NUMBER_OF_ITEMS: uint = 8u;

struct ObjectStats {
    requests: uint,
    request_time: uint,
    sent_bytes: uint
}

pub struct LogStats {
    priv clients: HashMap<~str, ObjectStats>
}

impl LogStats {
    pub fn new() -> ~LogStats {
        ~LogStats{clients: HashMap::new()}
    }

    pub fn print(&self) {
        let mut stats: ~[(&~str, &ObjectStats)] = self.clients.iter().collect();
        stats.sort_by(|&(_, a), &(_, b)| b.requests.cmp(&a.requests));
        print_sorted(stats, "By requests");
        stats.sort_by(|&(_, a), &(_, b)| b.request_time.cmp(&a.request_time));
        print_sorted(stats, "By request time");
        stats.sort_by(|&(_, a), &(_, b)| b.sent_bytes.cmp(&a.sent_bytes));
        print_sorted(stats, "By sent bytes");
    }
}

impl LogProcessor for LogStats {
    fn process(&mut self, record: HTTPLogRecord) {
        self.clients.insert_or_update_with(
            record.remote_addr.to_owned(),
            ObjectStats{
                requests: 1,
                request_time: record.request_time,
                sent_bytes: record.sent_bytes,
                },
            |_, stats| {
                stats.requests += 1;
                stats.request_time += record.request_time;
                stats.sent_bytes += record.sent_bytes;
            });
    }
}

fn print_sorted(sorted: &[(&~str, &ObjectStats)], message: &str) {
    println!("\n  {}", message);
    println!("=====================================================\
              =============");
    println!("Client                                 \
              Requests   Duration   Bytes");
    println!("-----------------------------------------------------\
              -------------");
    for &(client, stats) in sorted.iter().take(NUMBER_OF_ITEMS) {
        println!("{: <40} {: >6} {: >10} {: >7}",
                 *client, stats.requests,
                 format_duration(stats.request_time),
                 format_bytes(stats.sent_bytes));
    }
}

fn format_duration(duration: uint) -> ~str {
    let (mut n, mut pos, modifier) = if duration < 1000 {
            (duration, 3, ~"s")
        } else if duration < 60 * 1000 {
            (duration / 100, 1, ~"s")
        } else if duration < 60 * 60 * 1000 {
            (duration / 6000, 1, ~"m")
        } else {
            (duration / 360000, 1, ~"h")
        };
    while pos > 0 && n % 10 == 0 {
        n /= 10;
        pos -= 1;
    }
    let int_part = (n / pow(10, pos)).to_str();
    let mut fract_part = str::with_capacity(pos + 1);
    if pos != 0 && n != 0 {
        fract_part.push_char('.');
        while pos > 0 {
            let digit = (n / pow(10, pos - 1)) % 10;
            fract_part.push_char((digit as u8 + '0' as u8) as char);
            pos -= 1;
        }
    }
    int_part + fract_part + modifier
}

fn pow(n: uint, p: uint) -> uint {
    let mut num = 1;
    for _ in range(0, p) {
        num *= n;
    }
    num
}

fn format_bytes(mut bytes: uint) -> ~str {
    static modifiers: [&'static str, ..4] = ["G", "M", "K", ""];
    let mut i = modifiers.len() - 1;
    while bytes >= 1024 && i != 0 {
        bytes /= 1024;
        i -= 1;
    }
    bytes.to_str() + modifiers[i]
}

/*
 * Tests
 */
#[cfg(test)]
mod test {
    use super::{format_duration, format_bytes};

    #[test]
    fn test_format_duration() {
        assert_eq!(~"0s", format_duration(0));
        assert_eq!(~"0.009s", format_duration(9));
        assert_eq!(~"0.09s", format_duration(90));
        assert_eq!(~"0.9s", format_duration(900));
        assert_eq!(~"0.999s", format_duration(999));
        assert_eq!(~"1s", format_duration(1000));
        assert_eq!(~"1s", format_duration(1009));
        assert_eq!(~"1.4s", format_duration(1400));
        assert_eq!(~"1.6s", format_duration(1600));
        assert_eq!(~"59s", format_duration(59000));
        assert_eq!(~"1m", format_duration(60000));
        assert_eq!(~"1.5m", format_duration(90000));
        assert_eq!(~"1h", format_duration(60 * 60 * 1000));
        assert_eq!(~"1.5h", format_duration(90 * 60 * 1000));
        assert_eq!(~"10h", format_duration(10 * 60 * 60 * 1000));
    }

    #[test]
    fn test_format_bytes() {
        assert_eq!(~"0", format_bytes(0));
        assert_eq!(~"9", format_bytes(9));
        assert_eq!(~"90", format_bytes(90));
        assert_eq!(~"900", format_bytes(900));
        assert_eq!(~"1000", format_bytes(1000));
        assert_eq!(~"1K", format_bytes(1024));
        assert_eq!(~"2K", format_bytes(2048));
        assert_eq!(~"4K", format_bytes(4096));
        assert_eq!(~"1M", format_bytes(1024 * 1024));
        assert_eq!(~"1G", format_bytes(1024 * 1024 * 1024));
        assert_eq!(~"1024G", format_bytes(1024 * 1024 * 1024 * 1024));
    }
}
<commit_msg>Simplify types a little bit<commit_after>use std::str;
use std::hashmap::HashMap;

use log::{HTTPLogRecord, LogProcessor};

// TODO: Should be moved outside
static NUMBER_OF_ITEMS: uint = 8u;

struct ObjectStats {
    requests: uint,
    request_time: uint,
    sent_bytes: uint
}

type KeyValue<'r> = (&'r ~str, &'r ObjectStats);

pub struct LogStats {
    priv clients: HashMap<~str, ObjectStats>
}

impl LogStats {
    pub fn new() -> ~LogStats {
        ~LogStats{clients: HashMap::new()}
    }

    pub fn print(&self) {
        let mut stats: ~[KeyValue] = self.clients.iter().collect();
        stats.sort_by(|&(_, a), &(_, b)| b.requests.cmp(&a.requests));
        print_sorted(stats, "By requests");
        stats.sort_by(|&(_, a), &(_, b)| b.request_time.cmp(&a.request_time));
        print_sorted(stats, "By request time");
        stats.sort_by(|&(_, a), &(_, b)| b.sent_bytes.cmp(&a.sent_bytes));
        print_sorted(stats, "By sent bytes");
    }
}

impl LogProcessor for LogStats {
    fn process(&mut self, record: HTTPLogRecord) {
        self.clients.insert_or_update_with(
            record.remote_addr.into_owned(),
            ObjectStats{
                requests: 1,
                request_time: record.request_time,
                sent_bytes: record.sent_bytes,
                },
            |_, stats| {
                stats.requests += 1;
                stats.request_time += record.request_time;
                stats.sent_bytes += record.sent_bytes;
            });
    }
}

fn print_sorted(sorted: &[KeyValue], message: &str) {
    println!("\n  {}", message);
    println!("=====================================================\
              =============");
    println!("Client                                 \
              Requests   Duration   Bytes");
    println!("-----------------------------------------------------\
              -------------");
    for &(client, stats) in sorted.iter().take(NUMBER_OF_ITEMS) {
        println!("{: <40} {: >6} {: >10} {: >7}",
                 *client, stats.requests,
                 format_duration(stats.request_time),
                 format_bytes(stats.sent_bytes));
    }
}

fn format_duration(duration: uint) -> ~str {
    let (mut n, mut pos, modifier) = if duration < 1000 {
            (duration, 3, ~"s")
        } else if duration < 60 * 1000 {
            (duration / 100, 1, ~"s")
        } else if duration < 60 * 60 * 1000 {
            (duration / 6000, 1, ~"m")
        } else {
            (duration / 360000, 1, ~"h")
        };
    while pos > 0 && n % 10 == 0 {
        n /= 10;
        pos -= 1;
    }
    let int_part = (n / pow(10, pos)).to_str();
    let mut fract_part = str::with_capacity(pos + 1);
    if pos != 0 && n != 0 {
        fract_part.push_char('.');
        while pos > 0 {
            let digit = (n / pow(10, pos - 1)) % 10;
            fract_part.push_char((digit as u8 + '0' as u8) as char);
            pos -= 1;
        }
    }
    int_part + fract_part + modifier
}

fn pow(n: uint, p: uint) -> uint {
    let mut num = 1;
    for _ in range(0, p) {
        num *= n;
    }
    num
}

fn format_bytes(mut bytes: uint) -> ~str {
    static modifiers: [&'static str, ..4] = ["G", "M", "K", ""];
    let mut i = modifiers.len() - 1;
    while bytes >= 1024 && i != 0 {
        bytes /= 1024;
        i -= 1;
    }
    bytes.to_str() + modifiers[i]
}

/*
 * Tests
 */
#[cfg(test)]
mod test {
    use super::{format_duration, format_bytes};

    #[test]
    fn test_format_duration() {
        assert_eq!(~"0s", format_duration(0));
        assert_eq!(~"0.009s", format_duration(9));
        assert_eq!(~"0.09s", format_duration(90));
        assert_eq!(~"0.9s", format_duration(900));
        assert_eq!(~"0.999s", format_duration(999));
        assert_eq!(~"1s", format_duration(1000));
        assert_eq!(~"1s", format_duration(1009));
        assert_eq!(~"1.4s", format_duration(1400));
        assert_eq!(~"1.6s", format_duration(1600));
        assert_eq!(~"59s", format_duration(59000));
        assert_eq!(~"1m", format_duration(60000));
        assert_eq!(~"1.5m", format_duration(90000));
        assert_eq!(~"1h", format_duration(60 * 60 * 1000));
        assert_eq!(~"1.5h", format_duration(90 * 60 * 1000));
        assert_eq!(~"10h", format_duration(10 * 60 * 60 * 1000));
    }

    #[test]
    fn test_format_bytes() {
        assert_eq!(~"0", format_bytes(0));
        assert_eq!(~"9", format_bytes(9));
        assert_eq!(~"90", format_bytes(90));
        assert_eq!(~"900", format_bytes(900));
        assert_eq!(~"1000", format_bytes(1000));
        assert_eq!(~"1K", format_bytes(1024));
        assert_eq!(~"2K", format_bytes(2048));
        assert_eq!(~"4K", format_bytes(4096));
        assert_eq!(~"1M", format_bytes(1024 * 1024));
        assert_eq!(~"1G", format_bytes(1024 * 1024 * 1024));
        assert_eq!(~"1024G", format_bytes(1024 * 1024 * 1024 * 1024));
    }
}
<|endoftext|>


<commit_before>//! Singular-value decomposition (SVD) by divide-and-conquer (?gesdd)

use ndarray::*;

use super::convert::*;
use super::error::*;
use super::layout::*;
use super::types::*;

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(u8)]
pub enum UVTFlag {
    Full = b'A',
    Some = b'S',
    None = b'N',
}

/// Singular-value decomposition of matrix (copying) by divide-and-conquer
pub trait SVDDC {
    type U;
    type VT;
    type Sigma;
    fn svddc(&self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

/// Singular-value decomposition of matrix by divide-and-conquer
pub trait SVDDCInto {
    type U;
    type VT;
    type Sigma;
    fn svddc_into(self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

/// Singular-value decomposition of matrix reference by divide-and-conquer
pub trait SVDDCInplace {
    type U;
    type VT;
    type Sigma;
    fn svddc_inplace(&mut self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

impl<A, S> SVDDC for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svddc(&self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        self.to_owned().svddc_into(uvt_flag)
    }
}

impl<A, S> SVDDCInto for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svddc_into(mut self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        self.svddc_inplace(uvt_flag)
    }
}

impl<A, S> SVDDCInplace for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svddc_inplace(&mut self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        let l = self.layout()?;
        let svd_res = unsafe { A::svddc(l, uvt_flag, self.as_allocated_mut()?)? };
        let (m, n) = l.size();
        let k = m.min(n);
        let (ldu, tdu, ldvt, tdvt) = match uvt_flag {
            UVTFlag::Full => (m, m, n, n),
            UVTFlag::Some => (m, k, k, n),
            UVTFlag::None => (1, 1, 1, 1),
        };
        let u = svd_res
            .u
            .map(|u| into_matrix(l.resized(ldu, tdu), u).expect("Size of U mismatches"));
        let vt = svd_res
            .vt
            .map(|vt| into_matrix(l.resized(ldvt, tdvt), vt).expect("Size of VT mismatches"));
        let s = ArrayBase::from(svd_res.s);
        Ok((u, s, vt))
    }
}
<commit_msg>Add documentation for svddc::UVTFlag<commit_after>//! Singular-value decomposition (SVD) by divide-and-conquer (?gesdd)

use ndarray::*;

use super::convert::*;
use super::error::*;
use super::layout::*;
use super::types::*;

/// Specifies how many of the columns of *U* and rows of *V*ᵀ are computed and returned.
///
/// For an input array of shape *m*×*n*, the following are computed:
#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(u8)]
pub enum UVTFlag {
    /// All *m* columns of *U* and all *n* rows of *V*ᵀ.
    Full = b'A',
    /// The first min(*m*,*n*) columns of *U* and the first min(*m*,*n*) rows of *V*ᵀ.
    Some = b'S',
    /// No columns of *U* or rows of *V*ᵀ.
    None = b'N',
}

/// Singular-value decomposition of matrix (copying) by divide-and-conquer
pub trait SVDDC {
    type U;
    type VT;
    type Sigma;
    fn svddc(&self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

/// Singular-value decomposition of matrix by divide-and-conquer
pub trait SVDDCInto {
    type U;
    type VT;
    type Sigma;
    fn svddc_into(self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

/// Singular-value decomposition of matrix reference by divide-and-conquer
pub trait SVDDCInplace {
    type U;
    type VT;
    type Sigma;
    fn svddc_inplace(&mut self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)>;
}

impl<A, S> SVDDC for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svddc(&self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        self.to_owned().svddc_into(uvt_flag)
    }
}

impl<A, S> SVDDCInto for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svddc_into(mut self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        self.svddc_inplace(uvt_flag)
    }
}

impl<A, S> SVDDCInplace for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    type U = Array2<A>;
    type VT = Array2<A>;
    type Sigma = Array1<A::Real>;

    fn svddc_inplace(&mut self, uvt_flag: UVTFlag) -> Result<(Option<Self::U>, Self::Sigma, Option<Self::VT>)> {
        let l = self.layout()?;
        let svd_res = unsafe { A::svddc(l, uvt_flag, self.as_allocated_mut()?)? };
        let (m, n) = l.size();
        let k = m.min(n);
        let (ldu, tdu, ldvt, tdvt) = match uvt_flag {
            UVTFlag::Full => (m, m, n, n),
            UVTFlag::Some => (m, k, k, n),
            UVTFlag::None => (1, 1, 1, 1),
        };
        let u = svd_res
            .u
            .map(|u| into_matrix(l.resized(ldu, tdu), u).expect("Size of U mismatches"));
        let vt = svd_res
            .vt
            .map(|vt| into_matrix(l.resized(ldvt, tdvt), vt).expect("Size of VT mismatches"));
        let s = ArrayBase::from(svd_res.s);
        Ok((u, s, vt))
    }
}
<|endoftext|>


<commit_before>use super::*;

#[test]
fn sliding_windows_1() {
    fn test_window_correctness_with_storage(mut storage: Storage<u32>) {
        let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]];

        {
            let windowed_iter = Adaptor::new(0..5, &mut storage);
            let output: Vec<Vec<u32>> = windowed_iter.map(|x| From::from(&x[..])).collect();
            assert_eq!(output, expected);
        }
    }

    let auto_alloc:   Storage<u32> = Storage::optimized(&(0..5), 3);
    let middle_alloc: Storage<u32> = Storage::new(3);
    let small_alloc:  Storage<u32> = Storage::from_vec(vec![1u32;   1], 3);
    let exact_alloc:  Storage<u32> = Storage::from_vec(vec![1u32;   3], 3);
    let big_alloc:    Storage<u32> = Storage::from_vec(vec![1u32, 100], 3);

    test_window_correctness_with_storage(auto_alloc);
    test_window_correctness_with_storage(middle_alloc);
    test_window_correctness_with_storage(small_alloc);
    test_window_correctness_with_storage(exact_alloc);
    test_window_correctness_with_storage(big_alloc);
}

#[test]
fn sliding_windows_2() {
    let it = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&it, 3);
    let windowed_iter = Adaptor::new(it, &mut storage);

    for mut x in windowed_iter {
        x[1] = 0u32;
        assert_eq!(x[0], 0);
    }
}

#[test]
#[should_panic]
fn sliding_windows_3() {
    let it = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&it, 3);
    let mut windowed_iter = Adaptor::new(it, &mut storage);

    let _a = windowed_iter.next();
    let _b = windowed_iter.next();
}

#[test]
fn sliding_windows_4() {
    let mut storage1: Storage<u32> = Storage::new(3);
    let iter1 = Adaptor::new(0..5, &mut storage1);

    let mut storage2: Storage<u32> = Storage::new(5);
    let iter2 = Adaptor::new(0..5, &mut storage2);

    let mut storage3: Storage<u32> = Storage::new(6);
    let iter3 = Adaptor::new(0..5, &mut storage3);

    let mut storage4: Storage<u32> = Storage::new(6);
    let iter4 = Adaptor::new(42..42, &mut storage4);

    assert_eq!(iter1.size_hint(), (3, Some(3)));
    assert_eq!(iter2.size_hint(), (1, Some(1)));
    assert_eq!(iter3.size_hint(), (1, Some(1)));
    assert_eq!(iter4.size_hint(), (0, Some(0)));
}

#[test]
fn sliding_windows_5() {
    let range = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&range, 0);
    let mut iter = Adaptor::new(range, &mut storage);

    assert!(iter.next().is_none());
    assert!(iter.next().is_none());
}

#[test]
fn sliding_windows_6() {
    let range0 = 0..0;
    let range1 = 0..1;
    let range2 = 0..2;

    let storage0: Storage<u32> = Storage::optimized(&range0, 1);
    let storage0: Vec<u32> = storage0.into();
    assert_eq!(storage0.capacity(), 2);

    let storage1: Storage<u32> = Storage::optimized(&range1, 1);
    let storage1: Vec<u32> = storage1.into();
    assert_eq!(storage1.capacity(), 1);

    let storage2: Storage<u32> = Storage::optimized(&range2, 1);
    let storage2: Vec<u32> = storage2.into();
    assert_eq!(storage2.capacity(), 2);

    let storage3: Storage<u32> = Storage::optimized(&range2, 3);
    let storage3: Vec<u32> = storage3.into();
    assert_eq!(storage3.capacity(), 2);
}
<commit_msg>reeintroduce test for None in size_hint<commit_after>use super::*;

#[test]
fn sliding_windows_1() {
    fn test_window_correctness_with_storage(mut storage: Storage<u32>) {
        let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]];

        {
            let windowed_iter = Adaptor::new(0..5, &mut storage);
            let output: Vec<Vec<u32>> = windowed_iter.map(|x| From::from(&x[..])).collect();
            assert_eq!(output, expected);
        }
    }

    let auto_alloc:   Storage<u32> = Storage::optimized(&(0..5), 3);
    let middle_alloc: Storage<u32> = Storage::new(3);
    let small_alloc:  Storage<u32> = Storage::from_vec(vec![1u32;   1], 3);
    let exact_alloc:  Storage<u32> = Storage::from_vec(vec![1u32;   3], 3);
    let big_alloc:    Storage<u32> = Storage::from_vec(vec![1u32, 100], 3);

    test_window_correctness_with_storage(auto_alloc);
    test_window_correctness_with_storage(middle_alloc);
    test_window_correctness_with_storage(small_alloc);
    test_window_correctness_with_storage(exact_alloc);
    test_window_correctness_with_storage(big_alloc);
}

#[test]
fn sliding_windows_2() {
    let it = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&it, 3);
    let windowed_iter = Adaptor::new(it, &mut storage);

    for mut x in windowed_iter {
        x[1] = 0u32;
        assert_eq!(x[0], 0);
    }
}

#[test]
#[should_panic]
fn sliding_windows_3() {
    let it = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&it, 3);
    let mut windowed_iter = Adaptor::new(it, &mut storage);

    let _a = windowed_iter.next();
    let _b = windowed_iter.next();
}

#[test]
fn sliding_windows_4() {
    let mut storage1: Storage<u32> = Storage::new(3);
    let iter1 = Adaptor::new(0..5, &mut storage1);

    let mut storage2: Storage<u32> = Storage::new(5);
    let iter2 = Adaptor::new(0..5, &mut storage2);

    let mut storage3: Storage<u32> = Storage::new(6);
    let iter3 = Adaptor::new(0..5, &mut storage3);

    let mut storage4: Storage<u32> = Storage::new(6);
    let iter4 = Adaptor::new(42..42, &mut storage4);

    let mut storage5: Storage<u32> = Storage::new(6);
    let iter5 = Adaptor::new(42.., &mut storage5);

    assert_eq!(iter1.size_hint(), (3, Some(3)));
    assert_eq!(iter2.size_hint(), (1, Some(1)));
    assert_eq!(iter3.size_hint(), (1, Some(1)));
    assert_eq!(iter4.size_hint(), (0, Some(0)));
    assert_eq!(iter5.size_hint().1, None);
}

#[test]
fn sliding_windows_5() {
    let range = 0..5;
    let mut storage: Storage<u32> = Storage::optimized(&range, 0);
    let mut iter = Adaptor::new(range, &mut storage);

    assert!(iter.next().is_none());
    assert!(iter.next().is_none());
}

#[test]
fn sliding_windows_6() {
    let range0 = 0..0;
    let range1 = 0..1;
    let range2 = 0..2;

    let storage0: Storage<u32> = Storage::optimized(&range0, 1);
    let storage0: Vec<u32> = storage0.into();
    assert_eq!(storage0.capacity(), 2);

    let storage1: Storage<u32> = Storage::optimized(&range1, 1);
    let storage1: Vec<u32> = storage1.into();
    assert_eq!(storage1.capacity(), 1);

    let storage2: Storage<u32> = Storage::optimized(&range2, 1);
    let storage2: Vec<u32> = storage2.into();
    assert_eq!(storage2.capacity(), 2);

    let storage3: Storage<u32> = Storage::optimized(&range2, 3);
    let storage3: Vec<u32> = storage3.into();
    assert_eq!(storage3.capacity(), 2);
}
<|endoftext|>


<commit_before>use super::SoundexWord;

#[test]
fn soundex_reduce() {
    assert!(&SoundexWord::new("abc").to_string() == "A12");
    assert!(&SoundexWord::new("hello").to_string() == "H4");
    assert!(&SoundexWord::new("STUPID").to_string() == "S313");
    assert!(&SoundexWord::new("What").to_string() == "W3");
}

#[test]
fn sounds_similar() {
    assert!(SoundexWord::new("rupert") == SoundexWord::new("robert"));
    assert!(SoundexWord::new("hey") == SoundexWord::new("hei"));
    assert!(SoundexWord::new("sOundex") == SoundexWord::new("saundecs"));
}

#[test]
fn does_not_sound_similar() {
    assert!(SoundexWord::new("cool") != SoundexWord::new("fool"));
    assert!(SoundexWord::new("nope") != SoundexWord::new("doop"));
    assert!(SoundexWord::new("goat") != SoundexWord::new("goal"));
}

#[test]
fn multiple_words() {
    assert!(SoundexWord::new("hey rupert") == SoundexWord::new("hei robert"));
    assert!(SoundexWord::new("what's up") == SoundexWord::new("wats oop"));
    assert!(SoundexWord::new("my own goat") == SoundexWord::new("mai oun goat"));
}
<commit_msg>Add more tests<commit_after>use super::SoundexWord;

#[test]
fn soundex_reduce() {
    assert!(&SoundexWord::new("abc").to_string() == "A12");
    assert!(&SoundexWord::new("hello").to_string() == "H4");
    assert!(&SoundexWord::new("STUPID").to_string() == "S313");
    assert!(&SoundexWord::new("What").to_string() == "W3");
}

#[test]
fn sounds_similar() {
    assert!(SoundexWord::new("rupert") == SoundexWord::new("robert"));
    assert!(SoundexWord::new("hey") == SoundexWord::new("hei"));
    assert!(SoundexWord::new("sOundex") == SoundexWord::new("saundecs"));
    assert!(SoundexWord::new("america") == SoundexWord::new("amurica"));
    assert!(SoundexWord::new("lambada") == SoundexWord::new("lambda"));
    assert!(SoundexWord::new("lambada") == SoundexWord::new("lambda"));
}

#[test]
fn does_not_sound_similar() {
    assert!(SoundexWord::new("cool") != SoundexWord::new("fool"));
    assert!(SoundexWord::new("nope") != SoundexWord::new("doop"));
    assert!(SoundexWord::new("goat") != SoundexWord::new("goal"));
}

#[test]
fn multiple_words() {
    assert!(SoundexWord::new("hey rupert") == SoundexWord::new("hei robert"));
    assert!(SoundexWord::new("what's up") == SoundexWord::new("wats oop"));
    assert!(SoundexWord::new("my own goat") == SoundexWord::new("mai oun goat"));
    assert!(SoundexWord::new("lol your stupid") == SoundexWord::new("lul ur stupido"));
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Formatter, Error as FormatError};
use std::error::Error;

pub type PortMidiDeviceId = i32;
pub type PortMidiResult<T> = Result<T, PortMidiError>;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PortMidiError {
    HostError,
    InvalidDeviceId,
    InsufficientMemory,
    BufferTooSmall,
    BufferOverflow,
    BadPtr,
    BadData,
    InternalError,
    BufferMaxSize,
}
impl Display for PortMidiError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
        write!(f, "{:?}", self)
    }
}
impl Error for PortMidiError {
    fn description(&self) -> &str {
        match *self {
            PortMidiError::HostError => "Host error",
            PortMidiError::InvalidDeviceId => "Invalid device ID",
            PortMidiError::InsufficientMemory => "Insufficent memory",
            PortMidiError::BufferTooSmall => "Buffer is too small",
            PortMidiError::BufferOverflow => "Buffer has overflow",
            PortMidiError::BadPtr => "Bad pointer was supplied",
            PortMidiError::BadData => "Invalid MIDI message data",
            PortMidiError::InternalError => "Portmidi internal error",
            PortMidiError::BufferMaxSize => "Buffer cannot be made larger",
        }
    }
}

<commit_msg>Refactor trait implementationf or `PortMidiError`<commit_after>use std::fmt::{Display, Formatter, Error as FormatError};
use std::error::Error;

pub type PortMidiDeviceId = i32;
pub type PortMidiResult<T> = Result<T, PortMidiError>;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PortMidiError {
    HostError,
    InvalidDeviceId,
    InsufficientMemory,
    BufferTooSmall,
    BufferOverflow,
    BadPtr,
    BadData,
    InternalError,
    BufferMaxSize,
}
impl PortMidiError {
    fn msg(&self) -> &'static str {
        match *self {
            PortMidiError::HostError => "Host error",
            PortMidiError::InvalidDeviceId => "Invalid device ID",
            PortMidiError::InsufficientMemory => "Insufficent memory",
            PortMidiError::BufferTooSmall => "Buffer is too small",
            PortMidiError::BufferOverflow => "Buffer has overflow",
            PortMidiError::BadPtr => "Bad pointer was supplied",
            PortMidiError::BadData => "Invalid MIDI message data",
            PortMidiError::InternalError => "Portmidi internal error",
            PortMidiError::BufferMaxSize => "Buffer cannot be made larger",
        }

    }
}
impl Display for PortMidiError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
        write!(f, "{}", self.msg())
    }
}
impl Error for PortMidiError {
    fn description(&self) -> &str {
        self.msg()
    }
}
<|endoftext|>


<commit_before>//! Type conversions for binding parameters and getting query results.

use super::{PreparedStatement, ResultRow,
            ColIx, ParamIx};
use super::{
    SqliteResult, SqliteErrorCode, SqliteError,
};
use super::ColumnType::SQLITE_NULL;

use std::error::FromError;

use time;

/// Values that can be bound to parameters in prepared statements.
pub trait ToSql {
    /// Bind the `ix`th parameter to this value (`self`).
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()>;
}

/// A trait for result values from a query.
///
/// cf [sqlite3 result values][column].
///
/// *inspired by sfackler's FromSql (and some haskell bindings?)*
///
/// [column]: http://www.sqlite.org/c3ref/column_blob.html
///
///   - *TODO: consider a `types` submodule*
///   - *TODO: many more implementors, including Option<T>*
pub trait FromSql {
    /// Try to extract a `Self` type value from the `col`th colum of a `ResultRow`.
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Self>;
}

impl ToSql for i32 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int(ix, *self)
    }
}

impl FromSql for i32 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<i32> { Ok(row.column_int(col)) }
}

impl ToSql for i64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int64(ix, *self)
    }
}

impl FromSql for i64 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<i64> { Ok(row.column_int64(col)) }
}

impl ToSql for f64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_double(ix, *self)
    }
}

impl FromSql for f64 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<f64> { Ok(row.column_double(col)) }
}

impl<T: ToSql + Clone> ToSql for Option<T> {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        match (*self).clone() {
            Some(x) => x.to_sql(s, ix),
            None => s.bind_null(ix)
        }
    }
}

impl<T: FromSql + Clone> FromSql for Option<T> {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Option<T>> {
        match row.column_type(col) {
            SQLITE_NULL => Ok(None),
            _ => FromSql::from_sql(row, col).map(|x| Some(x))
        }
    }
}

impl ToSql for String {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_text(ix, (*self).as_ref())
    }
}

impl FromSql for String {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<String> {
        Ok(row.column_text(col).unwrap_or(String::new()))
    }
}

impl FromSql for Vec<u8> {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Vec<u8>> {
        Ok(row.column_blob(col).unwrap_or(Vec::new()))
    }
}

/// Format of sqlite date strings
///
/// From [Date And Time Functions][lang_datefunc]:
/// > The datetime() function returns "YYYY-MM-DD HH:MM:SS"
/// [lang_datefunc]: http://www.sqlite.org/lang_datefunc.html
pub static SQLITE_TIME_FMT: &'static str = "%F %T";

impl FromSql for time::Tm {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<time::Tm> {
        let txt = row.column_text(col).unwrap_or(String::new());
        Ok( try!(time::strptime(txt.as_ref(), SQLITE_TIME_FMT)) )
    }
}

impl FromError<time::ParseError> for SqliteError {
    fn from_error(err: time::ParseError) -> SqliteError {
        SqliteError {
            kind: SqliteErrorCode::SQLITE_MISMATCH,
            desc: "Time did not match expected format",
            detail: Some(format!("Time parsing error: {}", err)),
        }
    }
}

impl ToSql for time::Timespec {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        let timestr = time::at_utc(*self).strftime(SQLITE_TIME_FMT)
            .unwrap() // unit tests ensure SQLITE_TIME_FMT is ok
            .to_string();
        s.bind_text(ix, timestr.as_ref())
    }
}

impl FromSql for time::Timespec {
    /// TODO: propagate error message
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<time::Timespec> {
        let tmo: SqliteResult<time::Tm> = FromSql::from_sql(row, col);
        tmo.map(|tm| tm.to_timespec())
    }
}

#[cfg(test)]
mod tests {
    use time::Tm;
    use super::super::{DatabaseConnection, SqliteResult, ResultSet};
    use super::super::{ResultRowAccess};

    fn with_query<T, F>(sql: &str, mut f: F) -> SqliteResult<T>
        where F: FnMut(&mut ResultSet) -> T
    {
        let db = try!(DatabaseConnection::in_memory());
        let mut s = try!(db.prepare(sql));
        let mut rows = s.execute();
        Ok(f(&mut rows))
    }

    #[test]
    fn get_tm() {
        fn go() -> SqliteResult<()> {
            let conn = try!(DatabaseConnection::in_memory());
            let mut stmt = try!(
                conn.prepare("select datetime('2001-01-01', 'weekday 3', '3 hours')"));
            let mut results = stmt.execute();
            match results.step() {
                Ok(Some(ref mut row)) => {
                    assert_eq!(
                        row.get::<u32, Tm>(0),
                        Tm { tm_sec: 0,
                             tm_min: 0,
                             tm_hour: 3,
                             tm_mday: 3,
                             tm_mon: 0,
                             tm_year: 101,
                             tm_wday: 0,
                             tm_yday: 0,
                             tm_isdst: 0,
                             tm_utcoff: 0,
                             tm_nsec: 0
                        });
                    Ok(())
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            }
        }
        go().unwrap();
    }

    #[test]
    fn get_invalid_tm() {
        with_query("select 'not a time'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Tm> = row.get_opt(0u32);
                    assert!(x.is_err());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }

    #[test]
    fn select_blob() {
        with_query("select x'ff0db0'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Vec<u8>> = row.get_opt(0u32);
                    assert_eq!(x.ok().unwrap(), [0xff, 0x0d, 0xb0].to_vec());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }
}

// Local Variables:
// flycheck-rust-crate-root: "lib.rs"
// End:
<commit_msg>Implement ToSql from [u8]<commit_after>//! Type conversions for binding parameters and getting query results.

use super::{PreparedStatement, ResultRow,
            ColIx, ParamIx};
use super::{
    SqliteResult, SqliteErrorCode, SqliteError,
};
use super::ColumnType::SQLITE_NULL;

use std::error::FromError;

use time;

/// Values that can be bound to parameters in prepared statements.
pub trait ToSql {
    /// Bind the `ix`th parameter to this value (`self`).
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()>;
}

/// A trait for result values from a query.
///
/// cf [sqlite3 result values][column].
///
/// *inspired by sfackler's FromSql (and some haskell bindings?)*
///
/// [column]: http://www.sqlite.org/c3ref/column_blob.html
///
///   - *TODO: consider a `types` submodule*
///   - *TODO: many more implementors, including Option<T>*
pub trait FromSql {
    /// Try to extract a `Self` type value from the `col`th colum of a `ResultRow`.
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Self>;
}

impl ToSql for i32 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int(ix, *self)
    }
}

impl FromSql for i32 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<i32> { Ok(row.column_int(col)) }
}

impl ToSql for i64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_int64(ix, *self)
    }
}

impl FromSql for i64 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<i64> { Ok(row.column_int64(col)) }
}

impl ToSql for f64 {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_double(ix, *self)
    }
}

impl FromSql for f64 {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<f64> { Ok(row.column_double(col)) }
}

impl<T: ToSql + Clone> ToSql for Option<T> {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        match (*self).clone() {
            Some(x) => x.to_sql(s, ix),
            None => s.bind_null(ix)
        }
    }
}

impl<T: FromSql + Clone> FromSql for Option<T> {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Option<T>> {
        match row.column_type(col) {
            SQLITE_NULL => Ok(None),
            _ => FromSql::from_sql(row, col).map(|x| Some(x))
        }
    }
}

impl ToSql for String {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_text(ix, (*self).as_ref())
    }
}

impl FromSql for String {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<String> {
        Ok(row.column_text(col).unwrap_or(String::new()))
    }
}

impl<'a> ToSql for &'a [u8] {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        s.bind_blob(ix, *self)
    }
}

impl FromSql for Vec<u8> {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<Vec<u8>> {
        Ok(row.column_blob(col).unwrap_or(Vec::new()))
    }
}

/// Format of sqlite date strings
///
/// From [Date And Time Functions][lang_datefunc]:
/// > The datetime() function returns "YYYY-MM-DD HH:MM:SS"
/// [lang_datefunc]: http://www.sqlite.org/lang_datefunc.html
pub static SQLITE_TIME_FMT: &'static str = "%F %T";

impl FromSql for time::Tm {
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<time::Tm> {
        let txt = row.column_text(col).unwrap_or(String::new());
        Ok( try!(time::strptime(txt.as_ref(), SQLITE_TIME_FMT)) )
    }
}

impl FromError<time::ParseError> for SqliteError {
    fn from_error(err: time::ParseError) -> SqliteError {
        SqliteError {
            kind: SqliteErrorCode::SQLITE_MISMATCH,
            desc: "Time did not match expected format",
            detail: Some(format!("Time parsing error: {}", err)),
        }
    }
}

impl ToSql for time::Timespec {
    fn to_sql(&self, s: &mut PreparedStatement, ix: ParamIx) -> SqliteResult<()> {
        let timestr = time::at_utc(*self).strftime(SQLITE_TIME_FMT)
            .unwrap() // unit tests ensure SQLITE_TIME_FMT is ok
            .to_string();
        s.bind_text(ix, timestr.as_ref())
    }
}

impl FromSql for time::Timespec {
    /// TODO: propagate error message
    fn from_sql(row: &mut ResultRow, col: ColIx) -> SqliteResult<time::Timespec> {
        let tmo: SqliteResult<time::Tm> = FromSql::from_sql(row, col);
        tmo.map(|tm| tm.to_timespec())
    }
}

#[cfg(test)]
mod tests {
    use time::Tm;
    use super::super::{DatabaseConnection, SqliteResult, ResultSet};
    use super::super::{ResultRowAccess};

    fn with_query<T, F>(sql: &str, mut f: F) -> SqliteResult<T>
        where F: FnMut(&mut ResultSet) -> T
    {
        let db = try!(DatabaseConnection::in_memory());
        let mut s = try!(db.prepare(sql));
        let mut rows = s.execute();
        Ok(f(&mut rows))
    }

    #[test]
    fn get_tm() {
        fn go() -> SqliteResult<()> {
            let conn = try!(DatabaseConnection::in_memory());
            let mut stmt = try!(
                conn.prepare("select datetime('2001-01-01', 'weekday 3', '3 hours')"));
            let mut results = stmt.execute();
            match results.step() {
                Ok(Some(ref mut row)) => {
                    assert_eq!(
                        row.get::<u32, Tm>(0),
                        Tm { tm_sec: 0,
                             tm_min: 0,
                             tm_hour: 3,
                             tm_mday: 3,
                             tm_mon: 0,
                             tm_year: 101,
                             tm_wday: 0,
                             tm_yday: 0,
                             tm_isdst: 0,
                             tm_utcoff: 0,
                             tm_nsec: 0
                        });
                    Ok(())
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            }
        }
        go().unwrap();
    }

    #[test]
    fn get_invalid_tm() {
        with_query("select 'not a time'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Tm> = row.get_opt(0u32);
                    assert!(x.is_err());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }

    #[test]
    fn select_blob() {
        with_query("select x'ff0db0'", |results| {
            match results.step() {
                Ok(Some(ref mut row)) => {
                    let x : SqliteResult<Vec<u8>> = row.get_opt(0u32);
                    assert_eq!(x.ok().unwrap(), [0xff, 0x0d, 0xb0].to_vec());
                },
                Ok(None) => panic!("no row"),
                Err(oops) =>  panic!("error: {:?}", oops)
            };
        }).unwrap();
    }
}

// Local Variables:
// flycheck-rust-crate-root: "lib.rs"
// End:
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::num::Zero;
use std::io;
use std::fmt;
use std::error::Error;

use serde;
use serde_json;

//
// Use distinct 'newtype' types for sectors and sector offsets for type safety.
// When needed, these can still be derefed to u64.
// Derive a bunch of stuff so we can do ops on them.
//
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Sectors(u64);
}

impl Sectors {
    pub const fn new(val: u64) -> Sectors {
        Sectors(val)
    }
}

impl Zero for Sectors {
    fn zero() -> Self {
        Sectors(0)
    }
}

impl serde::Serialize for Sectors {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.visit_u64(**self)
    }
}

impl serde::Deserialize for Sectors {
    fn deserialize<D>(deserializer: &mut D) -> Result<Sectors, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(Sectors(val))
    }
}

custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct SectorOffset(u64);
}

impl SectorOffset {
    pub const fn new(val: u64) -> SectorOffset {
        SectorOffset(val)
    }
}

impl Zero for SectorOffset {
    fn zero() -> Self {
        SectorOffset(0)
    }
}

impl serde::Serialize for SectorOffset {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.visit_u64(**self)
    }
}

impl serde::Deserialize for SectorOffset {
    fn deserialize<D>(deserializer: &mut D) -> Result<SectorOffset, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(SectorOffset(val))
    }
}

// Define a common error enum.
// See http://blog.burntsushi.net/rust-error-handling/
#[derive(Debug)]
pub enum FroyoError {
    Io(io::Error),
    Serde(serde_json::error::Error),
}

impl fmt::Display for FroyoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FroyoError::Io(ref err) => write!(f, "IO error: {}", err),
            FroyoError::Serde(ref err) => write!(f, "Serde error: {}", err),
        }
    }
}

impl Error for FroyoError {
    fn description(&self) -> &str {
        match *self {
            FroyoError::Io(ref err) => err.description(),
            FroyoError::Serde(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            FroyoError::Io(ref err) => Some(err),
            FroyoError::Serde(ref err) => Some(err),
        }
    }
}

impl From<io::Error> for FroyoError {
    fn from(err: io::Error) -> FroyoError {
        FroyoError::Io(err)
    }
}

impl From<serde_json::error::Error> for FroyoError {
    fn from(err: serde_json::error::Error) -> FroyoError {
        FroyoError::Serde(err)
    }
}
<commit_msg>Add support for Nix to FroyoError<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::num::Zero;
use std::io;
use std::fmt;
use std::error::Error;

use serde;
use serde_json;
use nix;

//
// Use distinct 'newtype' types for sectors and sector offsets for type safety.
// When needed, these can still be derefed to u64.
// Derive a bunch of stuff so we can do ops on them.
//
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Sectors(u64);
}

impl Sectors {
    pub const fn new(val: u64) -> Sectors {
        Sectors(val)
    }
}

impl Zero for Sectors {
    fn zero() -> Self {
        Sectors(0)
    }
}

impl serde::Serialize for Sectors {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.visit_u64(**self)
    }
}

impl serde::Deserialize for Sectors {
    fn deserialize<D>(deserializer: &mut D) -> Result<Sectors, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(Sectors(val))
    }
}

custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct SectorOffset(u64);
}

impl SectorOffset {
    pub const fn new(val: u64) -> SectorOffset {
        SectorOffset(val)
    }
}

impl Zero for SectorOffset {
    fn zero() -> Self {
        SectorOffset(0)
    }
}

impl serde::Serialize for SectorOffset {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.visit_u64(**self)
    }
}

impl serde::Deserialize for SectorOffset {
    fn deserialize<D>(deserializer: &mut D) -> Result<SectorOffset, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(SectorOffset(val))
    }
}

// Define a common error enum.
// See http://blog.burntsushi.net/rust-error-handling/
#[derive(Debug)]
pub enum FroyoError {
    Io(io::Error),
    Serde(serde_json::error::Error),
    Nix(nix::Error),
}

impl fmt::Display for FroyoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FroyoError::Io(ref err) => write!(f, "IO error: {}", err),
            FroyoError::Serde(ref err) => write!(f, "Serde error: {}", err),
            FroyoError::Nix(ref err) => write!(f, "Nix error: {}", err.errno().desc()),
        }
    }
}

impl Error for FroyoError {
    fn description(&self) -> &str {
        match *self {
            FroyoError::Io(ref err) => err.description(),
            FroyoError::Serde(ref err) => Error::description(err),
            FroyoError::Nix(ref err) => err.errno().desc(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            FroyoError::Io(ref err) => Some(err),
            FroyoError::Serde(ref err) => Some(err),
            FroyoError::Nix(_) => None,
        }
    }
}

impl From<io::Error> for FroyoError {
    fn from(err: io::Error) -> FroyoError {
        FroyoError::Io(err)
    }
}

impl From<serde_json::error::Error> for FroyoError {
    fn from(err: serde_json::error::Error) -> FroyoError {
        FroyoError::Serde(err)
    }
}

impl From<nix::Error> for FroyoError {
    fn from(err: nix::Error) -> FroyoError {
        FroyoError::Nix(err)
    }
}
<|endoftext|>


<commit_before>//! Representation of a `TextEdit`.
//!
//! `rust-analyzer` never mutates text itself and only sends diffs to clients,
//! so `TextEdit` is the ultimate representation of the work done by
//! rust-analyzer.

pub use text_size::{TextRange, TextSize};

/// `InsertDelete` -- a single "atomic" change to text
///
/// Must not overlap with other `InDel`s
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Indel {
    pub insert: String,
    /// Refers to offsets in the original text
    pub delete: TextRange,
}

#[derive(Default, Debug, Clone)]
pub struct TextEdit {
    /// Invariant: disjoint and sorted by `delete`.
    indels: Vec<Indel>,
}

#[derive(Debug, Default, Clone)]
pub struct TextEditBuilder {
    indels: Vec<Indel>,
}

impl Indel {
    pub fn insert(offset: TextSize, text: String) -> Indel {
        Indel::replace(TextRange::empty(offset), text)
    }
    pub fn delete(range: TextRange) -> Indel {
        Indel::replace(range, String::new())
    }
    pub fn replace(range: TextRange, replace_with: String) -> Indel {
        Indel { delete: range, insert: replace_with }
    }

    pub fn apply(&self, text: &mut String) {
        let start: usize = self.delete.start().into();
        let end: usize = self.delete.end().into();
        text.replace_range(start..end, &self.insert);
    }
}

impl TextEdit {
    pub fn builder() -> TextEditBuilder {
        TextEditBuilder::default()
    }

    pub fn insert(offset: TextSize, text: String) -> TextEdit {
        let mut builder = TextEdit::builder();
        builder.insert(offset, text);
        builder.finish()
    }

    pub fn delete(range: TextRange) -> TextEdit {
        let mut builder = TextEdit::builder();
        builder.delete(range);
        builder.finish()
    }

    pub fn replace(range: TextRange, replace_with: String) -> TextEdit {
        let mut builder = TextEdit::builder();
        builder.replace(range, replace_with);
        builder.finish()
    }

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

    pub fn is_empty(&self) -> bool {
        self.indels.is_empty()
    }

    pub fn iter(&self) -> std::slice::Iter<'_, Indel> {
        self.into_iter()
    }

    pub fn apply(&self, text: &mut String) {
        match self.len() {
            0 => return,
            1 => {
                self.indels[0].apply(text);
                return;
            }
            _ => (),
        }

        let mut total_len = TextSize::of(&*text);
        for indel in &self.indels {
            total_len += TextSize::of(&indel.insert);
            total_len -= indel.delete.end() - indel.delete.start();
        }
        let mut buf = String::with_capacity(total_len.into());
        let mut prev = 0;
        for indel in &self.indels {
            let start: usize = indel.delete.start().into();
            let end: usize = indel.delete.end().into();
            if start > prev {
                buf.push_str(&text[prev..start]);
            }
            buf.push_str(&indel.insert);
            prev = end;
        }
        buf.push_str(&text[prev..text.len()]);
        assert_eq!(TextSize::of(&buf), total_len);

        // FIXME: figure out a way to mutate the text in-place or reuse the
        // memory in some other way
        *text = buf;
    }

    pub fn union(&mut self, other: TextEdit) -> Result<(), TextEdit> {
        // FIXME: can be done without allocating intermediate vector
        let mut all = self.iter().chain(other.iter()).collect::<Vec<_>>();
        if !check_disjoint_and_sort(&mut all) {
            return Err(other);
        }

        self.indels.extend(other.indels);
        check_disjoint_and_sort(&mut self.indels);
        // Only dedup deletions and replacements, keep all insertions
        self.indels.dedup_by(|a, b| a == b && !a.delete.is_empty());
        Ok(())
    }

    pub fn apply_to_offset(&self, offset: TextSize) -> Option<TextSize> {
        let mut res = offset;
        for indel in &self.indels {
            if indel.delete.start() >= offset {
                break;
            }
            if offset < indel.delete.end() {
                return None;
            }
            res += TextSize::of(&indel.insert);
            res -= indel.delete.len();
        }
        Some(res)
    }
}

impl IntoIterator for TextEdit {
    type Item = Indel;
    type IntoIter = std::vec::IntoIter<Indel>;

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

impl<'a> IntoIterator for &'a TextEdit {
    type Item = &'a Indel;
    type IntoIter = std::slice::Iter<'a, Indel>;

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

impl TextEditBuilder {
    pub fn is_empty(&self) -> bool {
        self.indels.is_empty()
    }
    pub fn replace(&mut self, range: TextRange, replace_with: String) {
        self.indel(Indel::replace(range, replace_with));
    }
    pub fn delete(&mut self, range: TextRange) {
        self.indel(Indel::delete(range));
    }
    pub fn insert(&mut self, offset: TextSize, text: String) {
        self.indel(Indel::insert(offset, text));
    }
    pub fn finish(self) -> TextEdit {
        let mut indels = self.indels;
        assert_disjoint_or_equal(&mut indels);
        TextEdit { indels }
    }
    pub fn invalidates_offset(&self, offset: TextSize) -> bool {
        self.indels.iter().any(|indel| indel.delete.contains_inclusive(offset))
    }
    fn indel(&mut self, indel: Indel) {
        self.indels.push(indel);
        if self.indels.len() <= 16 {
            assert_disjoint_or_equal(&mut self.indels);
        }
    }
}

fn assert_disjoint_or_equal(indels: &mut [Indel]) {
    assert!(check_disjoint_and_sort(indels));
}
// FIXME: Remove the impl Bound here, it shouldn't be needed
fn check_disjoint_and_sort(indels: &mut [impl std::borrow::Borrow<Indel>]) -> bool {
    indels.sort_by_key(|indel| (indel.borrow().delete.start(), indel.borrow().delete.end()));
    indels.iter().zip(indels.iter().skip(1)).all(|(l, r)| {
        let l = l.borrow();
        let r = r.borrow();
        l.delete.end() <= r.delete.start() || l == r
    })
}
<commit_msg>test: add unit test for TextEdit::apply()<commit_after>//! Representation of a `TextEdit`.
//!
//! `rust-analyzer` never mutates text itself and only sends diffs to clients,
//! so `TextEdit` is the ultimate representation of the work done by
//! rust-analyzer.

pub use text_size::{TextRange, TextSize};

/// `InsertDelete` -- a single "atomic" change to text
///
/// Must not overlap with other `InDel`s
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Indel {
    pub insert: String,
    /// Refers to offsets in the original text
    pub delete: TextRange,
}

#[derive(Default, Debug, Clone)]
pub struct TextEdit {
    /// Invariant: disjoint and sorted by `delete`.
    indels: Vec<Indel>,
}

#[derive(Debug, Default, Clone)]
pub struct TextEditBuilder {
    indels: Vec<Indel>,
}

impl Indel {
    pub fn insert(offset: TextSize, text: String) -> Indel {
        Indel::replace(TextRange::empty(offset), text)
    }
    pub fn delete(range: TextRange) -> Indel {
        Indel::replace(range, String::new())
    }
    pub fn replace(range: TextRange, replace_with: String) -> Indel {
        Indel { delete: range, insert: replace_with }
    }

    pub fn apply(&self, text: &mut String) {
        let start: usize = self.delete.start().into();
        let end: usize = self.delete.end().into();
        text.replace_range(start..end, &self.insert);
    }
}

impl TextEdit {
    pub fn builder() -> TextEditBuilder {
        TextEditBuilder::default()
    }

    pub fn insert(offset: TextSize, text: String) -> TextEdit {
        let mut builder = TextEdit::builder();
        builder.insert(offset, text);
        builder.finish()
    }

    pub fn delete(range: TextRange) -> TextEdit {
        let mut builder = TextEdit::builder();
        builder.delete(range);
        builder.finish()
    }

    pub fn replace(range: TextRange, replace_with: String) -> TextEdit {
        let mut builder = TextEdit::builder();
        builder.replace(range, replace_with);
        builder.finish()
    }

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

    pub fn is_empty(&self) -> bool {
        self.indels.is_empty()
    }

    pub fn iter(&self) -> std::slice::Iter<'_, Indel> {
        self.into_iter()
    }

    pub fn apply(&self, text: &mut String) {
        match self.len() {
            0 => return,
            1 => {
                self.indels[0].apply(text);
                return;
            }
            _ => (),
        }

        let mut total_len = TextSize::of(&*text);
        for indel in &self.indels {
            total_len += TextSize::of(&indel.insert);
            total_len -= indel.delete.end() - indel.delete.start();
        }
        let mut buf = String::with_capacity(total_len.into());
        let mut prev = 0;
        for indel in &self.indels {
            let start: usize = indel.delete.start().into();
            let end: usize = indel.delete.end().into();
            if start > prev {
                buf.push_str(&text[prev..start]);
            }
            buf.push_str(&indel.insert);
            prev = end;
        }
        buf.push_str(&text[prev..text.len()]);
        assert_eq!(TextSize::of(&buf), total_len);

        // FIXME: figure out a way to mutate the text in-place or reuse the
        // memory in some other way
        *text = buf;
    }

    pub fn union(&mut self, other: TextEdit) -> Result<(), TextEdit> {
        // FIXME: can be done without allocating intermediate vector
        let mut all = self.iter().chain(other.iter()).collect::<Vec<_>>();
        if !check_disjoint_and_sort(&mut all) {
            return Err(other);
        }

        self.indels.extend(other.indels);
        check_disjoint_and_sort(&mut self.indels);
        // Only dedup deletions and replacements, keep all insertions
        self.indels.dedup_by(|a, b| a == b && !a.delete.is_empty());
        Ok(())
    }

    pub fn apply_to_offset(&self, offset: TextSize) -> Option<TextSize> {
        let mut res = offset;
        for indel in &self.indels {
            if indel.delete.start() >= offset {
                break;
            }
            if offset < indel.delete.end() {
                return None;
            }
            res += TextSize::of(&indel.insert);
            res -= indel.delete.len();
        }
        Some(res)
    }
}

impl IntoIterator for TextEdit {
    type Item = Indel;
    type IntoIter = std::vec::IntoIter<Indel>;

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

impl<'a> IntoIterator for &'a TextEdit {
    type Item = &'a Indel;
    type IntoIter = std::slice::Iter<'a, Indel>;

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

impl TextEditBuilder {
    pub fn is_empty(&self) -> bool {
        self.indels.is_empty()
    }
    pub fn replace(&mut self, range: TextRange, replace_with: String) {
        self.indel(Indel::replace(range, replace_with));
    }
    pub fn delete(&mut self, range: TextRange) {
        self.indel(Indel::delete(range));
    }
    pub fn insert(&mut self, offset: TextSize, text: String) {
        self.indel(Indel::insert(offset, text));
    }
    pub fn finish(self) -> TextEdit {
        let mut indels = self.indels;
        assert_disjoint_or_equal(&mut indels);
        TextEdit { indels }
    }
    pub fn invalidates_offset(&self, offset: TextSize) -> bool {
        self.indels.iter().any(|indel| indel.delete.contains_inclusive(offset))
    }
    fn indel(&mut self, indel: Indel) {
        self.indels.push(indel);
        if self.indels.len() <= 16 {
            assert_disjoint_or_equal(&mut self.indels);
        }
    }
}

fn assert_disjoint_or_equal(indels: &mut [Indel]) {
    assert!(check_disjoint_and_sort(indels));
}
// FIXME: Remove the impl Bound here, it shouldn't be needed
fn check_disjoint_and_sort(indels: &mut [impl std::borrow::Borrow<Indel>]) -> bool {
    indels.sort_by_key(|indel| (indel.borrow().delete.start(), indel.borrow().delete.end()));
    indels.iter().zip(indels.iter().skip(1)).all(|(l, r)| {
        let l = l.borrow();
        let r = r.borrow();
        l.delete.end() <= r.delete.start() || l == r
    })
}

#[test]
fn test_apply() {
    let mut text = "_11h1_2222_xx3333_4444_6666".to_string();
    let mut builder = TextEditBuilder::default();
    builder.replace(TextRange::new(3.into(), 4.into()), "1".to_string());
    builder.delete(TextRange::new(11.into(), 13.into()));
    builder.insert(22.into(), "_5555".to_string());

    let text_edit = builder.finish();
    text_edit.apply(&mut text);

    assert_eq!(text, "_1111_2222_3333_4444_5555_6666")
}<|endoftext|>


<commit_before>//! Things we have not found a home for.

use std::sync::Arc;
use std::time::{SystemTime, Duration};
use basetypes::*;
use moves::*;
use tt::*;
use position::*;
use search::*;

/// A sequence of moves from some starting position, together with the
/// value assigned to the final position.
pub struct Variation {
    /// A sequence of moves from some starting position.
    pub moves: Vec<Move>,

    /// The value assigned to the final position.
    pub value: Value,

    /// The accuracy of the assigned value.
    pub bound: BoundType,
}

/// Contains information about the current progress of a search.
pub struct SearchStatus {
    /// The starting time for the search.
    pub started_at: SystemTime,

    /// The starting (root) position for the search.
    pub position: Position,

    /// `true` if the search has stopped, `false` otherwise.
    pub done: bool,

    /// The reached search depth.
    pub depth: u8,

    /// The number of legal moves in the starting (root) position.
    pub legal_moves_count: usize,

    /// The best variations found so far. The first move in each
    /// variation will be different.
    pub variations: Vec<Variation>,

    /// The duration of the search in milliseconds.
    pub duration_millis: u64,

    /// The number of analyzed nodes.
    pub searched_nodes: NodeCount,

    /// Average number of analyzed nodes per second.
    pub nps: NodeCount,
}

/// A thread that executes consecutive searches in different starting
/// positions.
pub struct SearchThread {
    tt: Arc<Tt>,
    status: SearchStatus,
    searcher: DeepeningSearcher<AspirationSearcher<AlphabetaSearcher>>,
}

impl SearchThread {
    /// Creates a new instance.
    pub fn new(tt: Arc<Tt>) -> SearchThread {
        SearchThread {
            tt: tt.clone(),
            status: SearchStatus {
                started_at: SystemTime::now(),
                position: Position::from_fen(START_POSITION_FEN).ok().unwrap(),
                done: true,
                depth: 0,
                variations: vec![Variation {
                                     value: VALUE_MIN,
                                     bound: BOUND_LOWER,
                                     moves: vec![],
                                 }],
                legal_moves_count: 20,
                searched_nodes: 0,
                duration_millis: 0,
                nps: 0,
            },
            searcher: DeepeningSearcher::new(tt),
        }
    }

    /// Stops the current search, starts a new search, updates the
    /// status.
    ///
    /// `position` is the starting position for the new
    /// search. `variation_count` specifies how many best lines of
    /// play to calculate (the first move in each line will be
    /// different). `searchmoves` restricts the analysis to the
    /// supplied list of moves only (no restrictions if the suppied
    /// list is empty). The move format is long algebraic
    /// notation. Examples: e2e4, e7e5, e1g1 (white short castling),
    /// e7e8q (for promotion).
    #[allow(unused_variables)]
    pub fn search(&mut self,
                  position: &Position,
                  variation_count: usize,
                  mut searchmoves: Vec<String>) {
        let mut legal_moves = position.legal_moves();
        let legal_moves_count = legal_moves.len();

        // Remove all legal moves not allowed by `searchmoves`.
        if !searchmoves.is_empty() {
            searchmoves.sort();
            let mut moves = vec![];
            for m in legal_moves.iter() {
                if searchmoves.binary_search(&m.notation()).is_ok() {
                    moves.push(*m);
                }
            }
            if !moves.is_empty() {
                legal_moves = moves;
            }
        };

        self.stop();
        self.searcher.start_search(SearchParams {
            search_id: 0,
            position: position.clone(),
            depth: MAX_DEPTH,
            lower_bound: VALUE_MIN,
            upper_bound: VALUE_MAX,
            searchmoves: legal_moves,
            variation_count: variation_count,
        });

        self.status = SearchStatus {
            started_at: SystemTime::now(),
            position: position.clone(),
            done: false,
            depth: 0,
            legal_moves_count: legal_moves_count,
            variations: vec![Variation {
                                 value: VALUE_MIN,
                                 bound: BOUND_LOWER,
                                 moves: vec![],
                             }], // TODO: Set good initial value (vec![best_move]).
            searched_nodes: 0,
            duration_millis: 0,
            ..self.status
        };
    }

    /// Stops the current search, updates the status.
    ///
    /// Does nothing if the current search is already stopped.
    pub fn stop(&mut self) {
        self.searcher.terminate_search();
        while !self.status().done {
            self.wait_status_update(Duration::from_millis(1000));
        }
    }

    /// Returns the status of the current search.
    ///
    /// **Important note:** Consecutive calls to this method will
    /// return the same unchanged result. Only after calling `search`,
    /// `stop`, or `wait_status_update`, the result returned by
    /// `status` may change.
    #[inline(always)]
    pub fn status(&self) -> &SearchStatus {
        &self.status
    }

    /// Waits for a search status update, timing out after a specified
    /// duration or earlier.
    pub fn wait_status_update(&mut self, duration: Duration) {
        self.searcher.wait_report(duration);
        while let Ok(r) = self.searcher.try_recv_report() {
            self.process_report(r)
        }
    }

    /// A helper method. It updates the current status according to
    /// the received report message.
    fn process_report(&mut self, report: Report) {
        let duration = self.status.started_at.elapsed().unwrap();
        self.status.duration_millis = 1000 * duration.as_secs() +
                                      (duration.subsec_nanos() / 1000000) as u64;
        self.status.searched_nodes = report.searched_nodes;
        self.status.nps = 1000 * (self.status.nps + self.status.searched_nodes) /
                          (1000 + self.status.duration_millis);
        if self.status.depth < report.depth {
            self.status.depth = report.depth;
            self.status.variations = vec![extract_pv(&self.tt,
                                                     &self.status.position,
                                                     report.depth)];
        }
        self.status.done = report.done;
    }
}

/// A helper function. It extracts the primary variation (PV) from the
/// transposition table (TT) and returns it.
///
/// **Note:** Because the PV is a moving target (the search continues
/// to run in parallel), imperfections in the reported PVs are
/// unavoidable. To deal with this, we turn a blind eye if the value
/// at the root of the PV differs from the value at the leaf by no
/// more than `EPSILON`.
fn extract_pv(tt: &Tt, position: &Position, depth: u8) -> Variation {
    const EPSILON: Value = 8; // A sufficiently small value (in centipawns).

    // Extract the PV, the leaf value, the root value, and the bound
    // type from the TT.
    let mut p = position.clone();
    let mut our_turn = true;
    let mut prev_move = None;
    let mut moves = Vec::new();
    let mut leaf_value = -9999;
    let mut root_value = leaf_value;
    let mut bound = BOUND_LOWER;
    while let Some(entry) = tt.peek(p.hash()) {
        if entry.bound() != BOUND_NONE {
            // Get the value and the bound type. In half of the
            // cases the value stored in `entry` is from other
            // side's perspective.
            if our_turn {
                leaf_value = entry.value();
                bound = entry.bound();
            } else {
                leaf_value = -entry.value();
                bound = match entry.bound() {
                    BOUND_UPPER => BOUND_LOWER,
                    BOUND_LOWER => BOUND_UPPER,
                    x => x,
                };
            }

            // The values under -9999 and over 9999 may look ugly in
            // some GUIs, so we trim them.
            if leaf_value > 9999 {
                leaf_value = 9999;
                if bound == BOUND_LOWER {
                    bound = BOUND_EXACT
                }
            }
            if leaf_value < -9999 {
                leaf_value = 9999;
                if bound == BOUND_UPPER {
                    bound = BOUND_EXACT
                }
            }

            if let Some(m) = prev_move {
                // Extend the PV with the previous move.
                moves.push(m);
            } else {
                // We are at the root -- set the root value.
                root_value = leaf_value;
            }

            if moves.len() < depth as usize && (leaf_value - root_value).abs() <= EPSILON {
                if let Some(m) = p.try_move_digest(entry.move16()) {
                    if p.do_move(m) {
                        if bound == BOUND_EXACT {
                            // Extend the PV with one more move.
                            prev_move = Some(m);
                            our_turn = !our_turn;
                            continue;
                        } else {
                            // This is the last move in the PV.
                            moves.push(m);
                        }
                    }
                }
            }
        }
        break;
    }

    // Change the bound type if the leaf value in the PV differs too
    // much from the root value.
    bound = match leaf_value - root_value {
        x if x > EPSILON && bound != BOUND_UPPER => BOUND_LOWER,
        x if x < -EPSILON && bound != BOUND_LOWER => BOUND_UPPER,
        _ => bound,
    };

    Variation {
        value: root_value,
        bound: bound,
        moves: moves,
    }
}
<commit_msg>use MultipvSearcher<commit_after>//! Things we have not found a home for.

use std::sync::Arc;
use std::time::{SystemTime, Duration};
use basetypes::*;
use moves::*;
use tt::*;
use position::*;
use search::*;

/// A sequence of moves from some starting position, together with the
/// value assigned to the final position.
pub struct Variation {
    /// A sequence of moves from some starting position.
    pub moves: Vec<Move>,

    /// The value assigned to the final position.
    pub value: Value,

    /// The accuracy of the assigned value.
    pub bound: BoundType,
}

/// Contains information about the current progress of a search.
pub struct SearchStatus {
    /// The starting time for the search.
    pub started_at: SystemTime,

    /// The starting (root) position for the search.
    pub position: Position,

    /// `true` if the search has stopped, `false` otherwise.
    pub done: bool,

    /// The reached search depth.
    pub depth: u8,

    /// The number of legal moves in the starting (root) position.
    pub legal_moves_count: usize,

    /// The best variations found so far. The first move in each
    /// variation will be different.
    pub variations: Vec<Variation>,

    /// The duration of the search in milliseconds.
    pub duration_millis: u64,

    /// The number of analyzed nodes.
    pub searched_nodes: NodeCount,

    /// Average number of analyzed nodes per second.
    pub nps: NodeCount,
}

/// A thread that executes consecutive searches in different starting
/// positions.
pub struct SearchThread {
    tt: Arc<Tt>,
    status: SearchStatus,
    searcher: DeepeningSearcher<MultipvSearcher<AlphabetaSearcher>>,
}

impl SearchThread {
    /// Creates a new instance.
    pub fn new(tt: Arc<Tt>) -> SearchThread {
        SearchThread {
            tt: tt.clone(),
            status: SearchStatus {
                started_at: SystemTime::now(),
                position: Position::from_fen(START_POSITION_FEN).ok().unwrap(),
                done: true,
                depth: 0,
                variations: vec![Variation {
                                     value: VALUE_MIN,
                                     bound: BOUND_LOWER,
                                     moves: vec![],
                                 }],
                legal_moves_count: 20,
                searched_nodes: 0,
                duration_millis: 0,
                nps: 0,
            },
            searcher: DeepeningSearcher::new(tt),
        }
    }

    /// Stops the current search, starts a new search, updates the
    /// status.
    ///
    /// `position` is the starting position for the new
    /// search. `variation_count` specifies how many best lines of
    /// play to calculate (the first move in each line will be
    /// different). `searchmoves` restricts the analysis to the
    /// supplied list of moves only (no restrictions if the suppied
    /// list is empty). The move format is long algebraic
    /// notation. Examples: e2e4, e7e5, e1g1 (white short castling),
    /// e7e8q (for promotion).
    #[allow(unused_variables)]
    pub fn search(&mut self,
                  position: &Position,
                  variation_count: usize,
                  mut searchmoves: Vec<String>) {
        let mut legal_moves = position.legal_moves();
        let legal_moves_count = legal_moves.len();

        // Remove all legal moves not allowed by `searchmoves`.
        if !searchmoves.is_empty() {
            searchmoves.sort();
            let mut moves = vec![];
            for m in legal_moves.iter() {
                if searchmoves.binary_search(&m.notation()).is_ok() {
                    moves.push(*m);
                }
            }
            if !moves.is_empty() {
                legal_moves = moves;
            }
        };

        self.stop();
        self.searcher.start_search(SearchParams {
            search_id: 0,
            position: position.clone(),
            depth: MAX_DEPTH,
            lower_bound: VALUE_MIN,
            upper_bound: VALUE_MAX,
            searchmoves: legal_moves,
            variation_count: variation_count,
        });

        self.status = SearchStatus {
            started_at: SystemTime::now(),
            position: position.clone(),
            done: false,
            depth: 0,
            legal_moves_count: legal_moves_count,
            variations: vec![Variation {
                                 value: VALUE_MIN,
                                 bound: BOUND_LOWER,
                                 moves: vec![],
                             }], // TODO: Set good initial value (vec![best_move]).
            searched_nodes: 0,
            duration_millis: 0,
            ..self.status
        };
    }

    /// Stops the current search, updates the status.
    ///
    /// Does nothing if the current search is already stopped.
    pub fn stop(&mut self) {
        self.searcher.terminate_search();
        while !self.status().done {
            self.wait_status_update(Duration::from_millis(1000));
        }
    }

    /// Returns the status of the current search.
    ///
    /// **Important note:** Consecutive calls to this method will
    /// return the same unchanged result. Only after calling `search`,
    /// `stop`, or `wait_status_update`, the result returned by
    /// `status` may change.
    #[inline(always)]
    pub fn status(&self) -> &SearchStatus {
        &self.status
    }

    /// Waits for a search status update, timing out after a specified
    /// duration or earlier.
    pub fn wait_status_update(&mut self, duration: Duration) {
        self.searcher.wait_report(duration);
        while let Ok(r) = self.searcher.try_recv_report() {
            self.process_report(r)
        }
    }

    /// A helper method. It updates the current status according to
    /// the received report message.
    fn process_report(&mut self, report: Report) {
        let duration = self.status.started_at.elapsed().unwrap();
        self.status.duration_millis = 1000 * duration.as_secs() +
                                      (duration.subsec_nanos() / 1000000) as u64;
        self.status.searched_nodes = report.searched_nodes;
        self.status.nps = 1000 * (self.status.nps + self.status.searched_nodes) /
                          (1000 + self.status.duration_millis);
        if self.status.depth < report.depth {
            self.status.depth = report.depth;
            self.status.variations = vec![extract_pv(&self.tt,
                                                     &self.status.position,
                                                     report.depth)];
        }
        self.status.done = report.done;
    }
}

/// A helper function. It extracts the primary variation (PV) from the
/// transposition table (TT) and returns it.
///
/// **Note:** Because the PV is a moving target (the search continues
/// to run in parallel), imperfections in the reported PVs are
/// unavoidable. To deal with this, we turn a blind eye if the value
/// at the root of the PV differs from the value at the leaf by no
/// more than `EPSILON`.
fn extract_pv(tt: &Tt, position: &Position, depth: u8) -> Variation {
    const EPSILON: Value = 8; // A sufficiently small value (in centipawns).

    // Extract the PV, the leaf value, the root value, and the bound
    // type from the TT.
    let mut p = position.clone();
    let mut our_turn = true;
    let mut prev_move = None;
    let mut moves = Vec::new();
    let mut leaf_value = -9999;
    let mut root_value = leaf_value;
    let mut bound = BOUND_LOWER;
    while let Some(entry) = tt.peek(p.hash()) {
        if entry.bound() != BOUND_NONE {
            // Get the value and the bound type. In half of the
            // cases the value stored in `entry` is from other
            // side's perspective.
            if our_turn {
                leaf_value = entry.value();
                bound = entry.bound();
            } else {
                leaf_value = -entry.value();
                bound = match entry.bound() {
                    BOUND_UPPER => BOUND_LOWER,
                    BOUND_LOWER => BOUND_UPPER,
                    x => x,
                };
            }

            // The values under -9999 and over 9999 may look ugly in
            // some GUIs, so we trim them.
            if leaf_value > 9999 {
                leaf_value = 9999;
                if bound == BOUND_LOWER {
                    bound = BOUND_EXACT
                }
            }
            if leaf_value < -9999 {
                leaf_value = 9999;
                if bound == BOUND_UPPER {
                    bound = BOUND_EXACT
                }
            }

            if let Some(m) = prev_move {
                // Extend the PV with the previous move.
                moves.push(m);
            } else {
                // We are at the root -- set the root value.
                root_value = leaf_value;
            }

            if moves.len() < depth as usize && (leaf_value - root_value).abs() <= EPSILON {
                if let Some(m) = p.try_move_digest(entry.move16()) {
                    if p.do_move(m) {
                        if bound == BOUND_EXACT {
                            // Extend the PV with one more move.
                            prev_move = Some(m);
                            our_turn = !our_turn;
                            continue;
                        } else {
                            // This is the last move in the PV.
                            moves.push(m);
                        }
                    }
                }
            }
        }
        break;
    }

    // Change the bound type if the leaf value in the PV differs too
    // much from the root value.
    bound = match leaf_value - root_value {
        x if x > EPSILON && bound != BOUND_UPPER => BOUND_LOWER,
        x if x < -EPSILON && bound != BOUND_LOWER => BOUND_UPPER,
        _ => bound,
    };

    Variation {
        value: root_value,
        bound: bound,
        moves: moves,
    }
}
<|endoftext|>