<commit_before><commit_msg>Add eigen.rs by stivstivsti.<commit_after>/*
eigen.rs 0.2

This piece of code is transpiled EigenvalueDecomposition.java from Jama framework.
I had to do this, because I haven't found any buildable rust opensource project
to calculate real eigen values in Rust. There are many packages which are usually bound to
openBLAS, but I can't build them with gnu toolchain, and that's the only toolchain, which
allows gdb (and thus IDE) debug nowadays.

Quality code is far from perfect, hopefully someone will appreciate my one day of
manual code conversion nightmare and mention me in the source code.

Stepan Yakovenko,
https://github.com/stiv-yakovenko

*/
use std::fmt;
use std::ops::Index;
use std::collections::VecDeque;
use std::ops::IndexMut;
use std::cmp;
extern crate num_traits;

use eigen::num_traits::Float;
//use self::num_traits;

pub struct Matrix {
    data:VecDeque<f64>,
    n:usize
}
impl Matrix {
    pub fn new(n:usize)->Matrix{
        let mut data = VecDeque::new();
        data.resize(n * n, 0.);
        Matrix{data:data,n:n}
    }
}
impl fmt::Debug for Matrix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{{").ok();
        for r in 0..self.n {
            for c in 0..self.n {
                write!(f, "{:.3?} ", self[[c,r]]).ok();
            }
            writeln!(f, "").ok();
        }
        write!(f, "}}")
    }
}
impl Index<[usize; 2]> for Matrix{
    type Output = f64;
    fn index(&self, idx: [usize; 2]) -> &f64 {
        &self.data[idx[0]+self.n*idx[1]]
    }
}
impl IndexMut<[usize; 2]> for Matrix{
    fn index_mut(&mut self, idx: [usize; 2]) -> &mut f64 {
        self.data.get_mut(idx[0]+self.n*idx[1]).unwrap()
    }
}
#[allow(dead_code)]
fn cdiv(xr: f64, xi: f64, yr: f64, yi: f64) -> (f64, f64) {
    let r: f64;
    let d: f64;
    if yr.abs() > yi.abs() {
        r = yi / yr;
        d = yr + r * yi;
        ((xr + r * xi) / d, (xi - r * xr) / d)
    } else {
        r = yr / yi;
        d = yi + r * yr;
        ((r * xr + xi) / d, (r * xi - xr) / d)
    }
}

#[allow(dead_code)]
pub fn hqr2(n_in: usize, h: &mut Matrix, v: &mut Matrix, d: &mut Vec<f64>, e: &mut Vec<f64>) {
    //  This is derived from the Algol procedure hqr2,
    //  by Martin and Wilkinson, Handbook for Auto. Comp.,
    //  Vol.ii-Linear Algebra, and the corresponding
    //  Fortran subroutine in EISPACK.
    // Initialize
    let nn = n_in;
    let mut n = nn as i16 - 1;
    let low = 0;
    let high = nn - 1;
    let eps = (2.0).powf(-52.0);
    let mut exshift = 0.0;
    let mut p = 0.;
    let mut q = 0.;
    let mut r = 0.;
    let mut s = 0.;
    let mut z = 0.;
    let mut t;
    let mut w;
    let mut x;
    let mut y;
    // Store roots isolated by balanc and compute matrix norm
    let mut norm = 0.0;
    let mut i = 0 as usize;
    while i < nn {
        if i < low || i > high {
            d[i] = h[[i, i]];
            e[i] = 0.0;
        }
        let mut j = cmp::max(i as i16 - 1, 0) as usize;
        while j < nn {
            norm = norm + (h[[i, j]]).abs();
            j = j + 1;
        }
        i = i + 1;
    }
    // Outer loop over eigenvalue index
    let mut iter = 0;
    while n >= low as i16 {
        // Look for single small sub-diagonal element
        let mut l = n;
        while l > low as i16 {
            s = (h[[l as usize - 1, l as usize - 1]]).abs() + (h[[l as usize, l as usize]]).abs();
            if s == 0.0 {
                s = norm;
            }
            if (h[[l as usize, l as usize - 1]]).abs() < eps * s {
                break;
            }
            l = l - 1;
        }
        // Check for convergence
        // One root found
        if l == n {
            h[[n as usize, n as usize]] = h[[n as usize, n as usize]] + exshift;
            d[n as usize] = h[[n as usize, n as usize]];
            e[n as usize] = 0.0;
            n = n - 1;
            iter = 0;
            // Two roots found
        } else if l == n - 1 {
            w = h[[n as usize, n as usize - 1]] * h[[n as usize - 1, n as usize]];
            p = (h[[n as usize - 1, n as usize - 1]] - h[[n as usize, n as usize]]) / 2.0;
            q = p * p + w;
            z = (q).abs().sqrt();
            h[[n as usize, n as usize]] = h[[n as usize, n as usize]] + exshift;
            h[[n as usize - 1, n as usize - 1]] = h[[n as usize - 1, n as usize - 1]] + exshift;
            x = h[[n as usize, n as usize]];
            // Real pair
            if q >= 0. {
                if p >= 0. {
                    z = p + z;
                } else {
                    z = p - z;
                }
                d[n as usize - 1] = x + z;
                d[n as usize] = d[n as usize - 1];
                if z != 0.0 {
                    d[n as usize] = x - w / z;
                }
                e[n as usize - 1] = 0.0;
                e[n as usize] = 0.0;
                x = h[[n as usize, n as usize - 1]];
                s = (x).abs() + (z).abs();
                p = x / s;
                q = z / s;
                r = (p * p + q * q).sqrt();
                p = p / r;
                q = q / r;
                // Row modification
                let mut j = n - 1;
                while j < nn as i16 {
                    z = h[[n as usize - 1, j as usize]];
                    h[[n as usize - 1, j as usize]] = q * z + p * h[[n as usize, j as usize]];
                    h[[n as usize, j as usize]] = q * h[[n as usize, j as usize]] - p * z;
                    j = j + 1;
                }
                // Column modification
                let mut i = 0;
                while i <= n {
                    z = h[[i as usize, n as usize - 1]];
                    h[[i as usize, n as usize - 1]] = q * z + p * h[[i as usize, n as usize]];
                    h[[i as usize, n as usize]] = q * h[[i as usize, n as usize]] - p * z;
                    i = i + 1;
                }
                // Accumulate transformations
                let mut i = low;
                while i <= high {
                    z = v[[i as usize, n as usize - 1]];
                    v[[i as usize, n as usize - 1]] = q * z + p * v[[i as usize, n as usize]];
                    v[[i as usize, n as usize]] = q * v[[i as usize, n as usize]] - p * z;
                    i = i + 1;
                }
                // Complex pair
            } else {
                d[n as usize - 1] = x + p;
                d[n as usize] = x + p;
                e[n as usize - 1] = z;
                e[n as usize] = -z;
            }
            n = n - 2;
            iter = 0;
            // No convergence yet
        } else {
            // Form shift
            x = h[[n as usize, n as usize]];
            y = 0.0;
            w = 0.0;
            if l < n {
                y = h[[n as usize - 1, n as usize - 1]];
                w = h[[n as usize, n as usize - 1]] * h[[n as usize - 1, n as usize]];
            }
            // Wilkinson's original ad hoc shift
            if iter == 10 {
                exshift += x;
                let mut i = low;
                while i <= n as usize {
                    h[[i, i]] -= x;
                    i = i + 1;
                }
                s = (h[[n as usize, n as usize - 1]]).abs() + (h[[n as usize - 1, n as usize - 2]]).abs();
                y = 0.75 * s;
                x = y;
                w = -0.4375 * s * s;
            }
            // MATLAB's new ad hoc shift
            if iter == 30 {
                s = (y - x) / 2.0;
                s = s * s + w;
                if s > 0. {
                    s = s.sqrt();
                    if y < x {
                        s = -s;
                    }
                    s = x - w / ((y - x) / 2.0 + s);
                    let mut i = low;
                    while i <= n as usize {
                        h[[i, i]] -= s;
                        i = i + 1;
                    }
                    exshift += s;
                    x = 0.964;
                    y = x;
                    w = y;
                }
            }
            iter = iter + 1;   // (Could check iteration count here.)
            // Look for two consecutive small sub-diagonal elements
            let mut m = n - 2;
            while m >= l {
                z = h[[m as usize, m as usize]];
                r = x - z;
                s = y - z;
                p = (r * s - w) / h[[m as usize + 1, m as usize]] + h[[m as usize, m as usize + 1]];
                q = h[[m as usize + 1, m as usize + 1]] - z - r - s;
                r = h[[m as usize + 2, m as usize + 1]];
                s = (p).abs() + (q).abs() + (r).abs();
                p = p / s;
                q = q / s;
                r = r / s;
                if m == l {
                    break;
                }
                if h[[m as usize, m as usize - 1]].abs() * (q).abs() + (r).abs() <
                    eps * ((p).abs() * ((h[[m as usize - 1, m as usize - 1]]).abs() + (z).abs() +
                        (h[[m as usize + 1, m as usize + 1]]).abs()
                    )) {
                    break;
                }
                m = m - 1;
            }
            let mut i = m + 2;
            while i <= n {
                h[[i as usize, i as usize - 2]] = 0.0;
                if i > m + 2 {
                    h[[i as usize, i as usize - 3]] = 0.0;
                }
                i = i + 1;
            }
            // Double QR step involving rows l:n and columns m:n
            let mut k = m;
            while k <= n - 1 {
                let notlast = if k != n - 1 { true } else { false };
                if k != m {
                    p = h[[k as usize, k as usize - 1]];
                    q = h[[k as usize + 1, k as usize - 1]];
                    r = if notlast { h[[k as usize + 2, k as usize - 1]] } else { 0.0 };
                    x = (p).abs() + (q).abs() + (r).abs();
                    if x == 0.0 {
                        k=k+1;
                        continue;
                    }
                    p = p / x;
                    q = q / x;
                    r = r / x;
                }
                s = (p * p + q * q + r * r).sqrt();
                if p < 0. {
                    s = -s;
                }
                if s != 0. {
                    if k != m {
                        h[[k as usize, k as usize - 1]] = -s * x;
                    } else if l != m {
                        h[[k as usize, k as usize - 1]] = -h[[k as usize, k as usize - 1]];
                    }
                    p = p + s;
                    x = p / s;
                    y = q / s;
                    z = r / s;
                    q = q / p;
                    r = r / p;
                    // Row modification
                    let mut j = k;
                    while j < nn as i16 {
                        p = h[[k as usize, j as usize]] + q * h[[k as usize + 1, j as usize]];
                        if notlast {
                            p = p + r * h[[k as usize + 2, j as usize]];
                            h[[k as usize + 2, j as usize]] = h[[k as usize + 2, j as usize]] - p * z;
                        }
                        h[[k as usize, j as usize]] = h[[k as usize, j as usize]] - p * x;
                        h[[k as usize + 1, j as usize]] = h[[k as usize + 1, j as usize]] - p * y;
                        j = j + 1;
                    }
                    // Column modification
                    let mut i = 0;
                    while i <= cmp::min(n as usize, k as usize + 3) {
                        p = x * h[[i, k as usize]] + y * h[[i as usize, k as usize + 1]];
                        if notlast {
                            p = p + z * h[[i, k as usize + 2]];
                            h[[i, k as usize + 2]] = h[[i, k as usize + 2]] - p * r;
                        }
                        h[[i, k as usize]] = h[[i, k as usize]] - p;
                        h[[i, k as usize + 1]] = h[[i, k as usize + 1]] - p * q;
                        i = i + 1;
                    }
                    // Accumulate transformations
                    let mut i = low;
                    while i <= high {
                        p = x * v[[i, k as usize]] + y * v[[i, k as usize + 1]];
                        if notlast {
                            p = p + z * v[[i as usize, k as usize + 2]];
                            v[[i as usize, k as usize + 2]] = v[[i as usize, k as usize + 2]] - p * r;
                        }
                        v[[i, k as usize]] = v[[i, k as usize]] - p;
                        v[[i, k as usize + 1]] = v[[i, k as usize + 1]] - p * q;
                        i = i + 1;
                    }
                }  // (s != 0)
                k = k + 1;
            }  // k loop
        }  // check convergence
    }  // while n >= low
    // Backsubstitute to find vectors of upper triangular form
    if norm == 0.0 {
        return;
    }
    n = nn as i16 - 1;
    while n >= 0 {
        p = d[n as usize];
        q = e[n as usize];
        // Real vector
        if q == 0. {
            let mut l = n;
            h[[n as usize, n as usize]] = 1.0;
            let mut i = n as i16 - 1;
            while i >= 0 {
                w = h[[i as usize, i as usize]] - p;
                r = 0.0;
                let mut j = l;
                while j <= n {
                    r = r + h[[i as usize, j as usize]] * h[[j as usize, n as usize]];
                    j = j + 1;
                }
                if e[i as usize] < 0.0 {
                    z = w;
                    s = r;
                } else {
                    l = i;
                    if e[i as usize] == 0.0 {
                        if w != 0.0 {
                            h[[i as usize, n as usize]] = -r / w;
                        } else {
                            h[[i as usize, n as usize]] = -r / (eps * norm);
                        }
                        // Solve real equations
                    } else {
                        x = h[[i as usize, i as usize + 1]];
                        y = h[[i as usize + 1, i as usize]];
                        q = (d[i as usize] - p) * (d[i as usize] - p) + e[i as usize] * e[i as usize];
                        t = (x * s - z * r) / q;
                        h[[i as usize, n as usize]] = t;
                        if (x).abs() > (z).abs() {
                            h[[i as usize + 1, n as usize]] = (-r - w * t) / x;
                        } else {
                            h[[i as usize + 1, n as usize]] = (-s - y * t) / z;
                        }
                    }
                    // Overflow control
                    t = h[[i as usize, n as usize]];
                    if (eps * t).abs() * t > 1. {
                        let mut j = i;
                        while j <= n as i16 {
                            h[[j as usize, n as usize]] = h[[j as usize, n as usize]] / t;
                            j = j + 1;
                        }
                    }
                }
                i = i - 1;
            }
            // Complex vector
        } else if q < 0. {
            let mut l = n - 1;
            // Last vector component imaginary so matrix is triangular
            if (h[[n as usize, n as usize - 1]]).abs() > (h[[n as usize - 1, n as usize]]).abs() {
                h[[n as usize - 1, n as usize - 1]] = q / h[[n as usize, n as usize - 1]];
                h[[n as usize - 1, n as usize]] = -(h[[n as usize, n as usize]] - p) / h[[n as usize, n as usize - 1]];
            } else {
                let (cdivr, cdivi) = cdiv(0.0, -h[[n as usize - 1, n as usize]], h[[n as usize - 1, n as usize - 1]] - p, q);
                h[[n as usize - 1, n as usize - 1]] = cdivr;
                h[[n as usize - 1, n as usize]] = cdivi;
            }
            h[[n as usize, n as usize - 1]] = 0.0;
            h[[n as usize, n as usize]] = 1.0;
            let mut i = n - 2;
            while i >= 0 {
                let mut ra = 0.;
                let mut sa = 0.;
                let mut vr;
                let vi;
                let mut j = l;
                while j <= n {
                    ra = ra + h[[i as usize, j as usize]] * h[[j as usize, n as usize - 1]];
                    sa = sa + h[[i as usize, j as usize]] * h[[j as usize, n as usize]];
                    j = j + 1;
                }
                w = h[[i as usize, i as usize]] - p;
                if e[i as usize] < 0.0 {
                    z = w;
                    r = ra;
                    s = sa;
                } else {
                    l = i;
                    if e[i as usize] == 0. {
                        let (cdivr, cdivi) = cdiv(-ra, -sa, w, q);
                        h[[i as usize, n as usize - 1]] = cdivr;
                        h[[i as usize, n as usize]] = cdivi;
                    } else {
                        // Solve complex equations
                        x = h[[i as usize, i as usize + 1]];
                        y = h[[i as usize + 1, i as usize]];
                        vr = (d[i as usize] - p) * (d[i as usize] - p) + e[i as usize] * e[i as usize] - q * q;
                        vi = (d[i as usize] - p) * 2.0 * q;
                        if vr == 0.0 && vi == 0.0 {
                            vr = eps * norm * ((w).abs() + (q).abs() +
                                (x).abs() + (y).abs() + (z)).abs();
                        }
                        let (cdivr, cdivi) = cdiv(x * r - z * ra + q * sa, x * s - z * sa - q * ra, vr, vi);
                        h[[i as usize, n as usize - 1]] = cdivr;
                        h[[i as usize, n as usize]] = cdivi;
                        if (x).abs() > ((z).abs() + (q).abs()) {
                            h[[i as usize + 1, n as usize - 1]] = (-ra - w * h[[i as usize, n as usize - 1]] + q * h[[i as usize, n as usize]]) / x;
                            h[[i as usize + 1, n as usize]] = (-sa - w * h[[i as usize, n as usize]] - q * h[[i as usize, n as usize - 1]]) / x;
                        } else {
                            let (cdivr, cdivi) = cdiv(-r - y * h[[i as usize, n as usize - 1]], -s - y * h[[i as usize, n as usize]], z, q);
                            h[[i as usize + 1, n as usize - 1]] = cdivr;
                            h[[i as usize + 1, n as usize]] = cdivi;
                        }
                    }
                    // Overflow control
                    t = (h[[i as usize, n as usize - 1]]).abs().max(h[[i as usize, n as usize]].abs());
                    if (eps * t) * t > 1. {
                        let mut j = i;
                        while j <= n {
                            j = j + 1;
                            h[[j as usize, n as usize - 1]] = h[[j as usize, n as usize - 1]] / t;
                            h[[j as usize, n as usize]] = h[[j as usize, n as usize]] / t;
                        }
                    }
                }
                i = i - 1;
            }
        }
        n = n - 1;
    }
    // Vectors of isolated roots
    let mut i = 0;
    while i < nn {
        if i < low || i > high {
            let mut j = i;
            while j < nn {
                v[[i, j]] = h[[i, j]];
                j = j + 1;
            }
        }
        i = i + 1;
    }
    // Back transformation to get eigenvectors of original matrix
    let mut j = nn as i16 - 1;
    while j >= low as i16 {
        let mut i = low;
        while i <= high {
            z = 0.0;
            let mut k = low;
            while k <= cmp::min(j as usize, high) {
                z = z + v[[i, k]] * h[[k, j as usize]];
                k = k + 1;
            }
            v[[i, j as usize]] = z;
            i = i + 1;
        }
        j = j - 1;
    }
}

//  This is derived from the Algol procedures orthes and ortran,
//  by Martin and Wilkinson, Handbook for Auto. Comp.,
//  Vol.ii-Linear Algebra, and the corresponding
//  Fortran subroutines in EISPACK.
#[allow(dead_code)]
pub fn orthes(m: &mut Matrix, h_mat: &mut Matrix, v_mat: &mut Matrix) {
    let low = 0;
    let n = m.n;
    let high = n - 1;
    let mut m = low + 1;
    let mut ort = vec!(0.; n);
       while m < high - 1 {
        // Scale column.
        let mut scale = 0.0;
        let mut i = m;
        //for (int        i = m;        i < = high;        i + +)
        while i <= high {
            scale = scale + (h_mat[[i, m - 1]]).abs();
            i = i + 1;
        }
        if scale != 0.0 {
            // Compute Householder transformation.
            let mut h = 0.0;
            let mut i = high;
            while i >= m {
                ort[i] = h_mat[[i, m - 1]] / scale;
                h += ort[i] * ort[i];
                i = i - 1;
            }
            let mut g = h.sqrt();
            if ort[m] > 0. {
                g = -g;
            }
            h = h - ort[m] * g;
            ort[m] = ort[m] - g;
            // Apply Householder similarity transformation
            // H = (I-u*u'/h)*H*(I-u*u')/h)
            let mut j = m;
            while j < n {
                let mut f = 0.0;
                let mut i = high;
                while i >= m {
                    f += ort[i] * h_mat[[i, j]];
                    i = i - 1;
                }
                f = f / h;
                let mut i = m;
                while
                    i <= high {
                    h_mat[[i, j]] -= f * ort[i];
                    i = i + 1;
                }
                j = j + 1;
            }
            let mut i = 0;
            while i <= high {
                let mut f = 0.0;
                let mut j = high;
                while j >= m {
                    f += ort[j] * h_mat[[i, j]];
                    j = j - 1;
                }
                f = f / h;
                let mut j = m;
                while j <= high {
                    h_mat[[i, j]] -= f * ort[j];
                    j = j + 1;
                }
                i = i + 1;
            }
            ort[m] = scale * ort[m];
            h_mat[[m, m - 1]] = scale * g;
        }
        m = m + 1;
    }
    // Accumulate transformations (Algol's ortran).
    for i in 0..n {
        for j in 0..n {
            v_mat[[i, j]] = if i == j { 1.0 } else { 0.0 };
        }
    }
    let mut m = high - 1;
    while m >= low + 1 {
        if h_mat[[m, m - 1]] != 0.0 {
            let mut i = m + 1;
            while i <= high {
                ort[i] = h_mat[[i, m - 1]];
                i = i + 1;
            }
            let mut j = m;
            while j <= high {
                let mut g = 0.0;
                let mut i = m;
                while i <= high {
                    g += ort[i] * v_mat[[i, j]];
                    i = i + 1;
                }
                // Double division avoids possible underflow
                g = (g / ort[m]) / h_mat[[m, m - 1]];
                let mut i = m;
                while i <= high {
                    v_mat[[i, j]] += g * ort[i];
                    i = i + 1;
                }
                j = j + 1;
            }
        }
        m = m - 1;
    }
}

#[allow(dead_code)]
fn calc_eigen(m: &mut Matrix) -> Vec<(f64, f64)>{
    let n = m.n;
    let mut h_mat = Matrix::new(n);
    let mut v_mat = Matrix::new(n);
    //let mut ort = vec!(0.;n);
    let mut d = vec!(0.; n);
    let mut e = vec!(0.; n);
    for i in 0..n {
        for j in 0..n {
            h_mat[[i, j]] = m[[i, j]];
        }
    }
    orthes(m, &mut h_mat, &mut v_mat);
    hqr2(n, &mut h_mat, &mut v_mat, &mut d, &mut e);
    let mut r= vec!((0.,0.); n);
    for i in 0..n {
        r[i]=(d[i],e[i])
    }
    r
}

#[allow(dead_code)]
// 6 x x x  + 9 x x + 3  x + 1 == 0 is vec![1.,3.,9.,6.]
pub fn solve_poly(c: Vec<f64>) -> VecDeque<f64> {
    let n = c.len();
    let mut m = Matrix::new(n);
    for i in 0..(n-1) {
        m[[i+1,i]]=1.;
    }
    for i in 0..(n) {
        m[[i,n-1]]=-c[i];
    }
    //println!("{:?}",m);
    let ei = calc_eigen(&mut m);
    let mut r = VecDeque::new();
    for c in ei {
        if c.1*c.1==0. {
            r.push_back(c.0);
        }
    }
    r
}

/*fn main() {
    let c =vec![1.,3.,9.,6.];
    let r =solve_poly(c);
    println!("{:?}",r);
    //    let m = Matrix::new(10);
    //    *m.get(5, 5) = 7.;
}
*/<|endoftext|>


<commit_before><commit_msg>Add problem #99<commit_after>use common::problem::{ Problem };

pub static problem: Problem<'static> = Problem {
    id: 99,
    answer: "709",
    solver: solve
};

fn solve() -> ~str {
    let result = io::file_reader(&Path("files/base_exp.txt"))
        .map(|input| {
            let mut line_idx = 1u;
            let mut max = 0f;
            let mut max_idx = 1;
            for input.each_line |line| {
                for str::find_char(line, ',').each |&idx| {
                    let base = float::from_str(line.slice(0, idx)).get();
                    let exp  = float::from_str(line.slice(idx + 1, line.len())).get();
                    let ln = exp * base.ln();
                    if ln > max {
                        max = ln;
                        max_idx = line_idx;
                    }
                    line_idx += 1;
                }
            }
            max_idx
        });

    match result {
        Err(msg) => fail!(msg),
        Ok(value) => return value.to_str()
    }
}
<|endoftext|>


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

#[macro_use]
extern crate serde_json;

extern crate xi_rpc;
extern crate xi_core_lib;

use std::io;

use xi_rpc::{RpcLoop, ReadError};
use xi_rpc::test_utils::{make_reader, test_channel};
use xi_core_lib::MainState;

#[test]
/// Tests that the handler responds to a standard startup sequence as expected.
fn test_startup() {
    let mut state = MainState::new();
    let (tx, mut rx) = test_channel();
    let mut rpc_looper = RpcLoop::new(tx);
    let json = make_reader(r#"{"method":"client_started","params":{}}
{"method":"set_theme","params":{"theme_name":"InspiredGitHub"}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
    assert_eq!(rx.expect_object().get_method(), Some("available_themes"));
    assert_eq!(rx.expect_object().get_method(), Some("theme_changed"));

    let json = make_reader(r#"{"id":0,"method":"new_view","params":{}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
    assert_eq!(rx.expect_response(), Ok(json!("view-id-1")));
}

#[test]
/// Tests that the handler creates and destroys views and buffers
fn test_state() {
    let mut state = MainState::new();
    let buffers = state._get_buffers();

    let write = io::sink();
    let json = make_reader(r#"{"method":"client_started","params":{}}
{"method":"set_theme","params":{"theme_name":"InspiredGitHub"}}
{"id":0,"method":"new_view","params":{}}"#);
    let mut rpc_looper = RpcLoop::new(write);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());

    {
        let buffers = buffers.lock();
        assert_eq!(buffers.iter_editors().count(), 1);
    }
    assert!(buffers.buffer_for_view(&"view-id-1".into()).is_some());

    let json = make_reader(
        r#"{"method":"close_view","params":{"view_id":"view-id-1"}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
    {
        let buffers = buffers.lock();
        assert_eq!(buffers.iter_editors().count(), 0);
    }

    let json = make_reader(r#"{"id":1,"method":"new_view","params":{}}
{"id":2,"method":"new_view","params":{}}
{"id":3,"method":"new_view","params":{}}"#);

    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
    {
        let buffers = buffers.lock();
        assert_eq!(buffers.iter_editors().count(), 3);
    }
}

#[test]
/// Tests that the runloop exits with the correct error when receiving
/// malformed json.
fn test_malformed_json() {
    let mut state = MainState::new();
    let write = io::sink();
    let mut rpc_looper = RpcLoop::new(write);
    // malformed json, no id: should not receive a response, and connection should close.
    let read = make_reader(r#"{method:"client_started","params":{}}
{"id":0,"method":"new_view","params":{}}"#);
    match rpc_looper.mainloop(|| read, &mut state).err()
        .expect("malformed json exits with error") {
            ReadError::Json(_) => (), // expected
            err => panic!("Unexpected error: {:?}", err),
    }
    // read should have ended after first item
    {
        let buffers = state._get_buffers();
        let buffers = buffers.lock();
        assert_eq!(buffers.iter_editors().count(), 0);
    }
}

#[test]
/// Sends all of the cursor movement-related commands, and verifies that
/// they are handled.
///
///
/// Note: this is a test of message parsing, not of editor behaviour.
fn test_movement_cmds() {
    let mut state = MainState::new();
    let write = io::sink();
    let mut rpc_looper = RpcLoop::new(write);
    // init a new view
    let json = make_reader(r#"{"method":"client_started","params":{}}
{"method":"set_theme","params":{"theme_name":"InspiredGitHub"}}
{"id":0,"method":"new_view","params":{}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());

    let json = make_reader(MOVEMENT_RPCS);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
}

#[test]
/// Sends all the commands which modify the buffer, and verifies that they
/// are handled.
fn test_text_commands() {
    let mut state = MainState::new();
    let write = io::sink();
    let mut rpc_looper = RpcLoop::new(write);
    // init a new view
    let json = make_reader(r#"{"method":"client_started","params":{}}
{"method":"set_theme","params":{"theme_name":"InspiredGitHub"}}
{"id":0,"method":"new_view","params":{}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());

    let json = make_reader(TEXT_EDIT_RPCS);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
}

#[test]
fn test_other_edit_commands() {
    let mut state = MainState::new();
    let write = io::sink();
    let mut rpc_looper = RpcLoop::new(write);
    // init a new view
    let json = make_reader(r#"{"method":"client_started","params":{}}
{"method":"set_theme","params":{"theme_name":"InspiredGitHub"}}
{"id":0,"method":"new_view","params":{}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());

    let json = make_reader(OTHER_EDIT_RPCS);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
}

//TODO: test saving rpc
//TODO: test plugin rpc

const MOVEMENT_RPCS: &str = r#"{"method":"edit","params":{"view_id":"view-id-1","method":"move_up","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_down","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_up_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_down_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_left","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_backward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_right","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_forward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_left_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_right_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_word_left","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_word_right","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_word_left_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_word_right_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_beginning_of_paragraph","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_end_of_paragraph","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_left_end_of_line","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_left_end_of_line_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_right_end_of_line","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_right_end_of_line_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_beginning_of_document","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_beginning_of_document_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_end_of_document","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_end_of_document_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"scroll_page_up","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"scroll_page_down","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"page_up_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"page_down_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"select_all","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"add_selection_above","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"add_selection_below","params":[]}}"#;

const TEXT_EDIT_RPCS: &str = r#"{"method":"edit","params":{"view_id":"view-id-1","method":"insert","params":{"chars":"a"}}}
{"method":"edit","params":{"view_id":"view-id-1","method":"delete_backward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"delete_forward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"delete_word_forward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"delete_word_backward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"delete_to_end_of_paragraph","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"insert_newline","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"insert_tab","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"yank","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"undo","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"redo","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"transpose","params":[]}}
{"id":2,"method":"edit","params":{"view_id":"view-id-1","method":"cut","params":[]}}"#;

const OTHER_EDIT_RPCS: &str = r#"{"method":"edit","params":{"view_id":"view-id-1","method":"scroll","params":[0,1]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"goto_line","params":{"line":1}}}
{"method":"edit","params":{"view_id":"view-id-1","method":"request_lines","params":[0,1]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"click","params":[6,0,0,1]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"drag","params":[17,15,0]}}
{"id":4,"method":"edit","params":{"view_id":"view-id-1","method":"find","params":{"case_sensitive":false,"chars":"m"}}}
{"method":"edit","params":{"view_id":"view-id-1","method":"find_next","params":{"wrap_around":true}}}
{"method":"edit","params":{"view_id":"view-id-1","method":"find_previous","params":{"wrap_around":true}}}
{"method":"edit","params":{"view_id":"view-id-1","method":"debug_rewrap","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"debug_print_spans","params":[]}}
{"id":3,"method":"edit","params":{"view_id":"view-id-1","method":"copy","params":[]}}"#;
<commit_msg>Add test case for gesture edit rpc<commit_after>// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate serde_json;

extern crate xi_rpc;
extern crate xi_core_lib;

use std::io;

use xi_rpc::{RpcLoop, ReadError};
use xi_rpc::test_utils::{make_reader, test_channel};
use xi_core_lib::MainState;

#[test]
/// Tests that the handler responds to a standard startup sequence as expected.
fn test_startup() {
    let mut state = MainState::new();
    let (tx, mut rx) = test_channel();
    let mut rpc_looper = RpcLoop::new(tx);
    let json = make_reader(r#"{"method":"client_started","params":{}}
{"method":"set_theme","params":{"theme_name":"InspiredGitHub"}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
    assert_eq!(rx.expect_object().get_method(), Some("available_themes"));
    assert_eq!(rx.expect_object().get_method(), Some("theme_changed"));

    let json = make_reader(r#"{"id":0,"method":"new_view","params":{}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
    assert_eq!(rx.expect_response(), Ok(json!("view-id-1")));
}

#[test]
/// Tests that the handler creates and destroys views and buffers
fn test_state() {
    let mut state = MainState::new();
    let buffers = state._get_buffers();

    let write = io::sink();
    let json = make_reader(r#"{"method":"client_started","params":{}}
{"method":"set_theme","params":{"theme_name":"InspiredGitHub"}}
{"id":0,"method":"new_view","params":{}}"#);
    let mut rpc_looper = RpcLoop::new(write);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());

    {
        let buffers = buffers.lock();
        assert_eq!(buffers.iter_editors().count(), 1);
    }
    assert!(buffers.buffer_for_view(&"view-id-1".into()).is_some());

    let json = make_reader(
        r#"{"method":"close_view","params":{"view_id":"view-id-1"}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
    {
        let buffers = buffers.lock();
        assert_eq!(buffers.iter_editors().count(), 0);
    }

    let json = make_reader(r#"{"id":1,"method":"new_view","params":{}}
{"id":2,"method":"new_view","params":{}}
{"id":3,"method":"new_view","params":{}}"#);

    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
    {
        let buffers = buffers.lock();
        assert_eq!(buffers.iter_editors().count(), 3);
    }
}

#[test]
/// Tests that the runloop exits with the correct error when receiving
/// malformed json.
fn test_malformed_json() {
    let mut state = MainState::new();
    let write = io::sink();
    let mut rpc_looper = RpcLoop::new(write);
    // malformed json, no id: should not receive a response, and connection should close.
    let read = make_reader(r#"{method:"client_started","params":{}}
{"id":0,"method":"new_view","params":{}}"#);
    match rpc_looper.mainloop(|| read, &mut state).err()
        .expect("malformed json exits with error") {
            ReadError::Json(_) => (), // expected
            err => panic!("Unexpected error: {:?}", err),
    }
    // read should have ended after first item
    {
        let buffers = state._get_buffers();
        let buffers = buffers.lock();
        assert_eq!(buffers.iter_editors().count(), 0);
    }
}

#[test]
/// Sends all of the cursor movement-related commands, and verifies that
/// they are handled.
///
///
/// Note: this is a test of message parsing, not of editor behaviour.
fn test_movement_cmds() {
    let mut state = MainState::new();
    let write = io::sink();
    let mut rpc_looper = RpcLoop::new(write);
    // init a new view
    let json = make_reader(r#"{"method":"client_started","params":{}}
{"method":"set_theme","params":{"theme_name":"InspiredGitHub"}}
{"id":0,"method":"new_view","params":{}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());

    let json = make_reader(MOVEMENT_RPCS);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
}

#[test]
/// Sends all the commands which modify the buffer, and verifies that they
/// are handled.
fn test_text_commands() {
    let mut state = MainState::new();
    let write = io::sink();
    let mut rpc_looper = RpcLoop::new(write);
    // init a new view
    let json = make_reader(r#"{"method":"client_started","params":{}}
{"method":"set_theme","params":{"theme_name":"InspiredGitHub"}}
{"id":0,"method":"new_view","params":{}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());

    let json = make_reader(TEXT_EDIT_RPCS);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
}

#[test]
fn test_other_edit_commands() {
    let mut state = MainState::new();
    let write = io::sink();
    let mut rpc_looper = RpcLoop::new(write);
    // init a new view
    let json = make_reader(r#"{"method":"client_started","params":{}}
{"method":"set_theme","params":{"theme_name":"InspiredGitHub"}}
{"id":0,"method":"new_view","params":{}}"#);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());

    let json = make_reader(OTHER_EDIT_RPCS);
    assert!(rpc_looper.mainloop(|| json, &mut state).is_ok());
}

//TODO: test saving rpc
//TODO: test plugin rpc

const MOVEMENT_RPCS: &str = r#"{"method":"edit","params":{"view_id":"view-id-1","method":"move_up","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_down","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_up_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_down_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_left","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_backward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_right","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_forward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_left_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_right_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_word_left","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_word_right","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_word_left_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_word_right_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_beginning_of_paragraph","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_end_of_paragraph","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_left_end_of_line","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_left_end_of_line_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_right_end_of_line","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_right_end_of_line_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_beginning_of_document","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_beginning_of_document_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_end_of_document","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"move_to_end_of_document_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"scroll_page_up","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"scroll_page_down","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"page_up_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"page_down_and_modify_selection","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"select_all","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"add_selection_above","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"add_selection_below","params":[]}}"#;

const TEXT_EDIT_RPCS: &str = r#"{"method":"edit","params":{"view_id":"view-id-1","method":"insert","params":{"chars":"a"}}}
{"method":"edit","params":{"view_id":"view-id-1","method":"delete_backward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"delete_forward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"delete_word_forward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"delete_word_backward","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"delete_to_end_of_paragraph","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"insert_newline","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"insert_tab","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"yank","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"undo","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"redo","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"transpose","params":[]}}
{"id":2,"method":"edit","params":{"view_id":"view-id-1","method":"cut","params":[]}}"#;

const OTHER_EDIT_RPCS: &str = r#"{"method":"edit","params":{"view_id":"view-id-1","method":"scroll","params":[0,1]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"goto_line","params":{"line":1}}}
{"method":"edit","params":{"view_id":"view-id-1","method":"request_lines","params":[0,1]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"click","params":[6,0,0,1]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"drag","params":[17,15,0]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"gesture","params":{"line": 1, "col": 2, "ty": "toggle_sel"}}}
{"id":4,"method":"edit","params":{"view_id":"view-id-1","method":"find","params":{"case_sensitive":false,"chars":"m"}}}
{"method":"edit","params":{"view_id":"view-id-1","method":"find_next","params":{"wrap_around":true}}}
{"method":"edit","params":{"view_id":"view-id-1","method":"find_previous","params":{"wrap_around":true}}}
{"method":"edit","params":{"view_id":"view-id-1","method":"debug_rewrap","params":[]}}
{"method":"edit","params":{"view_id":"view-id-1","method":"debug_print_spans","params":[]}}
{"id":3,"method":"edit","params":{"view_id":"view-id-1","method":"copy","params":[]}}"#;
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(issue = "0", feature = "windows_stdio")]

use prelude::v1::*;
use io::prelude::*;

use io::{self, Cursor};
use ptr;
use str;
use sync::Mutex;
use sys::c;
use sys::cvt;
use sys::handle::Handle;
use sys_common::io::read_to_end_uninitialized;

pub struct NoClose(Option<Handle>);

pub enum Output {
    Console(NoClose),
    Pipe(NoClose),
}

pub struct Stdin {
    handle: Output,
    utf8: Mutex<io::Cursor<Vec<u8>>>,
}
pub struct Stdout(Output);
pub struct Stderr(Output);

pub fn get(handle: c::DWORD) -> io::Result<Output> {
    let handle = unsafe { c::GetStdHandle(handle) };
    if handle == c::INVALID_HANDLE_VALUE {
        Err(io::Error::last_os_error())
    } else if handle.is_null() {
        Err(io::Error::new(io::ErrorKind::Other,
                           "no stdio handle available for this process"))
    } else {
        let ret = NoClose::new(handle);
        let mut out = 0;
        match unsafe { c::GetConsoleMode(handle, &mut out) } {
            0 => Ok(Output::Pipe(ret)),
            _ => Ok(Output::Console(ret)),
        }
    }
}

fn write(out: &Output, data: &[u8]) -> io::Result<usize> {
    let handle = match *out {
        Output::Console(ref c) => c.get().raw(),
        Output::Pipe(ref p) => return p.get().write(data),
    };
    // As with stdin on windows, stdout often can't handle writes of large
    // sizes. For an example, see #14940. For this reason, don't try to
    // write the entire output buffer on windows.
    //
    // For some other references, it appears that this problem has been
    // encountered by others [1] [2]. We choose the number 8K just because
    // libuv does the same.
    //
    // [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
    // [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
    const OUT_MAX: usize = 8192;
    let (utf16, data_len) = match str::from_utf8(data).ok() {
        Some(mut utf8) => {
            if utf8.len() > OUT_MAX {
                let mut new_len = OUT_MAX;
                while !utf8.is_char_boundary(new_len) {
                    new_len -= 1;
                }
                utf8 = &utf8[..new_len];
            }
            (utf8.encode_utf16().collect::<Vec<u16>>(), utf8.len())
        }
        None => return Err(invalid_encoding()),
    };
    let mut written = 0;
    try!(cvt(unsafe {
        c::WriteConsoleW(handle,
                         utf16.as_ptr() as c::LPCVOID,
                         utf16.len() as u32,
                         &mut written,
                         ptr::null_mut())
    }));

    // FIXME if this only partially writes the utf16 buffer then we need to
    //       figure out how many bytes of `data` were actually written
    assert_eq!(written as usize, utf16.len());
    Ok(data_len)
}

impl Stdin {
    pub fn new() -> io::Result<Stdin> {
        get(c::STD_INPUT_HANDLE).map(|handle| {
            Stdin {
                handle: handle,
                utf8: Mutex::new(Cursor::new(Vec::new())),
            }
        })
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let handle = match self.handle {
            Output::Console(ref c) => c.get().raw(),
            Output::Pipe(ref p) => return p.get().read(buf),
        };
        let mut utf8 = self.utf8.lock().unwrap();
        // Read more if the buffer is empty
        if utf8.position() as usize == utf8.get_ref().len() {
            let mut utf16 = vec![0u16; 0x1000];
            let mut num = 0;
            try!(cvt(unsafe {
                c::ReadConsoleW(handle,
                                utf16.as_mut_ptr() as c::LPVOID,
                                utf16.len() as u32,
                                &mut num,
                                ptr::null_mut())
            }));
            utf16.truncate(num as usize);
            // FIXME: what to do about this data that has already been read?
            let data = match String::from_utf16(&utf16) {
                Ok(utf8) => utf8.into_bytes(),
                Err(..) => return Err(invalid_encoding()),
            };
            *utf8 = Cursor::new(data);
        }

        // MemReader shouldn't error here since we just filled it
        utf8.read(buf)
    }

    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let mut me = self;
        (&mut me).read_to_end(buf)
    }
}

#[unstable(reason = "not public", issue = "0", feature = "fd_read")]
impl<'a> Read for &'a Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (**self).read(buf)
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        unsafe { read_to_end_uninitialized(self, buf) }
    }
}

impl Stdout {
    pub fn new() -> io::Result<Stdout> {
        get(c::STD_OUTPUT_HANDLE).map(Stdout)
    }

    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
        write(&self.0, data)
    }
}

impl Stderr {
    pub fn new() -> io::Result<Stderr> {
        get(c::STD_ERROR_HANDLE).map(Stderr)
    }

    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
        write(&self.0, data)
    }
}

// FIXME: right now this raw stderr handle is used in a few places because
//        std::io::stderr_raw isn't exposed, but once that's exposed this impl
//        should go away
impl io::Write for Stderr {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        Stderr::write(self, data)
    }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

impl NoClose {
    fn new(handle: c::HANDLE) -> NoClose {
        NoClose(Some(Handle::new(handle)))
    }

    fn get(&self) -> &Handle { self.0.as_ref().unwrap() }
}

impl Drop for NoClose {
    fn drop(&mut self) {
        self.0.take().unwrap().into_raw();
    }
}

impl Output {
    pub fn handle(&self) -> &Handle {
        let nc = match *self {
            Output::Console(ref c) => c,
            Output::Pipe(ref c) => c,
        };
        nc.0.as_ref().unwrap()
    }
}

fn invalid_encoding() -> io::Error {
    io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode")
}
<commit_msg>Further simplify Windows stdout/stderr<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(issue = "0", feature = "windows_stdio")]

use prelude::v1::*;
use io::prelude::*;

use cmp;
use io::{self, Cursor};
use ptr;
use str;
use sync::Mutex;
use sys::c;
use sys::cvt;
use sys::handle::Handle;
use sys_common::io::read_to_end_uninitialized;

pub struct NoClose(Option<Handle>);

pub enum Output {
    Console(NoClose),
    Pipe(NoClose),
}

pub struct Stdin {
    handle: Output,
    utf8: Mutex<io::Cursor<Vec<u8>>>,
}
pub struct Stdout(Output);
pub struct Stderr(Output);

pub fn get(handle: c::DWORD) -> io::Result<Output> {
    let handle = unsafe { c::GetStdHandle(handle) };
    if handle == c::INVALID_HANDLE_VALUE {
        Err(io::Error::last_os_error())
    } else if handle.is_null() {
        Err(io::Error::new(io::ErrorKind::Other,
                           "no stdio handle available for this process"))
    } else {
        let ret = NoClose::new(handle);
        let mut out = 0;
        match unsafe { c::GetConsoleMode(handle, &mut out) } {
            0 => Ok(Output::Pipe(ret)),
            _ => Ok(Output::Console(ret)),
        }
    }
}

fn write(out: &Output, data: &[u8]) -> io::Result<usize> {
    let handle = match *out {
        Output::Console(ref c) => c.get().raw(),
        Output::Pipe(ref p) => return p.get().write(data),
    };
    // As with stdin on windows, stdout often can't handle writes of large
    // sizes. For an example, see #14940. For this reason, don't try to
    // write the entire output buffer on windows.
    //
    // For some other references, it appears that this problem has been
    // encountered by others [1] [2]. We choose the number 8K just because
    // libuv does the same.
    //
    // [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
    // [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
    const OUT_MAX: usize = 8192;
    let len = cmp::min(data.len(), OUT_MAX);
    let utf8 = match str::from_utf8(&data[..len]) {
        Ok(s) => s,
        Err(ref e) if e.valid_up_to() == 0 => return Err(invalid_encoding()),
        Err(e) => str::from_utf8(&data[..e.valid_up_to()]).unwrap(),
    };
    let utf16 = utf8.encode_utf16().collect::<Vec<u16>>();
    let mut written = 0;
    try!(cvt(unsafe {
        c::WriteConsoleW(handle,
                         utf16.as_ptr() as c::LPCVOID,
                         utf16.len() as u32,
                         &mut written,
                         ptr::null_mut())
    }));

    // FIXME if this only partially writes the utf16 buffer then we need to
    //       figure out how many bytes of `data` were actually written
    assert_eq!(written as usize, utf16.len());
    Ok(utf8.len())
}

impl Stdin {
    pub fn new() -> io::Result<Stdin> {
        get(c::STD_INPUT_HANDLE).map(|handle| {
            Stdin {
                handle: handle,
                utf8: Mutex::new(Cursor::new(Vec::new())),
            }
        })
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let handle = match self.handle {
            Output::Console(ref c) => c.get().raw(),
            Output::Pipe(ref p) => return p.get().read(buf),
        };
        let mut utf8 = self.utf8.lock().unwrap();
        // Read more if the buffer is empty
        if utf8.position() as usize == utf8.get_ref().len() {
            let mut utf16 = vec![0u16; 0x1000];
            let mut num = 0;
            try!(cvt(unsafe {
                c::ReadConsoleW(handle,
                                utf16.as_mut_ptr() as c::LPVOID,
                                utf16.len() as u32,
                                &mut num,
                                ptr::null_mut())
            }));
            utf16.truncate(num as usize);
            // FIXME: what to do about this data that has already been read?
            let data = match String::from_utf16(&utf16) {
                Ok(utf8) => utf8.into_bytes(),
                Err(..) => return Err(invalid_encoding()),
            };
            *utf8 = Cursor::new(data);
        }

        // MemReader shouldn't error here since we just filled it
        utf8.read(buf)
    }

    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let mut me = self;
        (&mut me).read_to_end(buf)
    }
}

#[unstable(reason = "not public", issue = "0", feature = "fd_read")]
impl<'a> Read for &'a Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (**self).read(buf)
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        unsafe { read_to_end_uninitialized(self, buf) }
    }
}

impl Stdout {
    pub fn new() -> io::Result<Stdout> {
        get(c::STD_OUTPUT_HANDLE).map(Stdout)
    }

    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
        write(&self.0, data)
    }
}

impl Stderr {
    pub fn new() -> io::Result<Stderr> {
        get(c::STD_ERROR_HANDLE).map(Stderr)
    }

    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
        write(&self.0, data)
    }
}

// FIXME: right now this raw stderr handle is used in a few places because
//        std::io::stderr_raw isn't exposed, but once that's exposed this impl
//        should go away
impl io::Write for Stderr {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        Stderr::write(self, data)
    }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

impl NoClose {
    fn new(handle: c::HANDLE) -> NoClose {
        NoClose(Some(Handle::new(handle)))
    }

    fn get(&self) -> &Handle { self.0.as_ref().unwrap() }
}

impl Drop for NoClose {
    fn drop(&mut self) {
        self.0.take().unwrap().into_raw();
    }
}

impl Output {
    pub fn handle(&self) -> &Handle {
        let nc = match *self {
            Output::Console(ref c) => c,
            Output::Pipe(ref c) => c,
        };
        nc.0.as_ref().unwrap()
    }
}

fn invalid_encoding() -> io::Error {
    io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode")
}
<|endoftext|>


<commit_before><commit_msg>assert error removed<commit_after><|endoftext|>


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

//! A syntax highlighting plugin based on syntect.

extern crate syntect;
#[macro_use]
extern crate xi_plugin_lib;

mod stackmap;

use xi_plugin_lib::state_cache::{self, PluginCtx};
use xi_plugin_lib::plugin_base::ScopeSpan;
use syntect::parsing::{ParseState, ScopeStack, SyntaxSet, SCOPE_REPO};
use stackmap::{StackMap, LookupResult};

/// The state for syntax highlighting of one file.
struct PluginState<'a> {
    syntax_set: &'a SyntaxSet,
    stack_idents: StackMap,
    offset: usize,
    initial_state: Option<(ParseState, ScopeStack)>,
    spans_start: usize,
    // unflushed spans
    spans: Vec<ScopeSpan>,
    new_scopes: Vec<Vec<String>>,
    syntax_name: String,
}

const LINES_PER_RPC: usize = 50;

/// The syntax highlighting state corresponding to the beginning of a line
/// (as stored in the state cache).
// Note: this needs to be option because the caching layer relies on Default.
// We can't implement that because the actual initial state depends on the
// syntax. There are other ways to handle this, but this will do for now.
type State = Option<(ParseState, ScopeStack)>;

impl<'a> PluginState<'a> {
    pub fn new(syntax_set: &'a SyntaxSet) -> Self {
        PluginState {
            syntax_set: syntax_set,
            stack_idents: StackMap::default(),
            offset: 0,
            initial_state: None,
            spans_start: 0,
            spans: Vec::new(),
            new_scopes: Vec::new(),
            syntax_name: String::from("None"),
        }
    }

    // compute syntax for one line, also accumulating the style spans
    fn compute_syntax(&mut self, line: &str, state: State) -> State {
        let (mut parse_state, mut scope_state) = state.or_else(|| self.initial_state.clone()).unwrap();
        let ops = parse_state.parse_line(&line);

        let mut prev_cursor = 0;
        let repo = SCOPE_REPO.lock().unwrap();
        for (cursor, batch) in ops {
            if scope_state.len() > 0 {
                let scope_ident = self.stack_idents.get_value(scope_state.as_slice());
                let scope_ident = match scope_ident {
                    LookupResult::Existing(id) => id,
                    LookupResult::New(id) => {
                        let stack_strings = scope_state.as_slice().iter()
                            .map(|slice| repo.to_string(*slice))
                            .collect::<Vec<_>>();
                        self.new_scopes.push(stack_strings);
                        id
                    }
                };

                let start = self.offset - self.spans_start + prev_cursor;
                let end = start + (cursor - prev_cursor);
                if start != end {
                    let span = ScopeSpan::new(start, end, scope_ident);
                    self.spans.push(span);
                }
            }
            prev_cursor = cursor;
            scope_state.apply(&batch);
        }
        Some((parse_state, scope_state))
    }

    #[allow(unused)]
    // Return true if there's any more work to be done.
    fn highlight_one_line(&mut self, ctx: &mut PluginCtx<State>) -> bool {
        if let Some(line_num) = ctx.get_frontier() {
            //print_err!("highlighting {}", line_num);
            let (line_num, offset, state) = ctx.get_prev(line_num);
            if offset != self.offset {
                self.flush_spans(ctx);
                self.offset = offset;
                self.spans_start = offset;
            }
            let new_frontier = match ctx.get_line(line_num) {
                Ok("") => None,
                Ok(s) => {
                    let new_state = self.compute_syntax(s, state);
                    self.offset += s.len();
                    if s.as_bytes().last() == Some(&b'\n') {
                        Some((new_state, line_num + 1))
                    } else {
                        None
                    }
                }
                Err(_) => None,
            };
            let mut converged = false;
            if let Some((ref new_state, new_line_num)) = new_frontier {
                if let Some(old_state) = ctx.get(new_line_num) {
                    converged = old_state.as_ref().unwrap().0 == new_state.as_ref().unwrap().0;
                }
            }
            if !converged {
                if let Some((new_state, new_line_num)) = new_frontier {
                    ctx.set(new_line_num, new_state);
                    ctx.update_frontier(new_line_num);
                    return true;
                }
            }
            ctx.close_frontier();
        }
        false
    }

    fn flush_spans(&mut self, ctx: &mut PluginCtx<State>) {
        if !self.new_scopes.is_empty() {
            ctx.add_scopes(&self.new_scopes);
            self.new_scopes.clear();
        }
        if self.spans_start != self.offset {
            ctx.update_spans(self.spans_start, self.offset - self.spans_start,
                             &self.spans);
            self.spans.clear();
        }
        self.spans_start = self.offset;
    }

    fn do_highlighting(&mut self, mut ctx: PluginCtx<State>) {
        let syntax = match ctx.get_path() {
            Some(ref path) => self.syntax_set.find_syntax_for_file(path).unwrap()
                .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text()),
            None => self.syntax_set.find_syntax_plain_text(),
        };

        if syntax.name != self.syntax_name {
            self.syntax_name = syntax.name.clone();
            print_err!("syntect using {}", syntax.name);
        }

        self.initial_state = Some((ParseState::new(syntax), ScopeStack::new()));
        self.spans = Vec::new();
        self.new_scopes = Vec::new();
        self.offset = 0;
        self.spans_start = 0;
        ctx.reset();
        ctx.schedule_idle(0);
    }
}

impl<'a> state_cache::Plugin for PluginState<'a> {
    type State = State;

    fn initialize(&mut self, ctx: PluginCtx<State>, _buf_size: usize) {
        self.do_highlighting(ctx);
    }

    fn update(&mut self, mut ctx: PluginCtx<State>) {
        ctx.schedule_idle(0);
    }

    fn did_save(&mut self, ctx: PluginCtx<State>) {
        // TODO: use smarter logic to figure out whether we need to re-highlight the whole file
        self.do_highlighting(ctx);
    }

    fn idle(&mut self, mut ctx: PluginCtx<State>, _token: usize) {
        //print_err!("idle task at offset {}", self.offset);
        for _ in 0..LINES_PER_RPC {
            if !self.highlight_one_line(&mut ctx) {
                self.flush_spans(&mut ctx);
                return;
            }
            if ctx.request_is_pending() {
                print_err!("request pending at offset {}", self.offset);
                break;
            }
        }
        self.flush_spans(&mut ctx);
        ctx.schedule_idle(0);
    }
}

fn main() {
    let syntax_set = SyntaxSet::load_defaults_newlines();
    let mut state = PluginState::new(&syntax_set);

    state_cache::mainloop(&mut state);
}
<commit_msg>Fix #352<commit_after>// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A syntax highlighting plugin based on syntect.

extern crate syntect;
#[macro_use]
extern crate xi_plugin_lib;

mod stackmap;

use std::sync::MutexGuard;
use xi_plugin_lib::state_cache::{self, PluginCtx};
use xi_plugin_lib::plugin_base::ScopeSpan;
use syntect::parsing::{ParseState, ScopeStack, SyntaxSet, SCOPE_REPO, ScopeRepository};
use stackmap::{StackMap, LookupResult};

/// The state for syntax highlighting of one file.
struct PluginState<'a> {
    syntax_set: &'a SyntaxSet,
    stack_idents: StackMap,
    offset: usize,
    initial_state: Option<(ParseState, ScopeStack)>,
    spans_start: usize,
    // unflushed spans
    spans: Vec<ScopeSpan>,
    new_scopes: Vec<Vec<String>>,
    syntax_name: String,
}

const LINES_PER_RPC: usize = 50;

type LockedRepo = MutexGuard<'static, ScopeRepository>;

/// The syntax highlighting state corresponding to the beginning of a line
/// (as stored in the state cache).
// Note: this needs to be option because the caching layer relies on Default.
// We can't implement that because the actual initial state depends on the
// syntax. There are other ways to handle this, but this will do for now.
type State = Option<(ParseState, ScopeStack)>;

impl<'a> PluginState<'a> {
    pub fn new(syntax_set: &'a SyntaxSet) -> Self {
        PluginState {
            syntax_set: syntax_set,
            stack_idents: StackMap::default(),
            offset: 0,
            initial_state: None,
            spans_start: 0,
            spans: Vec::new(),
            new_scopes: Vec::new(),
            syntax_name: String::from("None"),
        }
    }

    // compute syntax for one line, also accumulating the style spans
    fn compute_syntax(&mut self, line: &str, state: State) -> State {
        let (mut parse_state, mut scope_state) = state.or_else(|| self.initial_state.clone()).unwrap();
        let ops = parse_state.parse_line(&line);

        let mut prev_cursor = 0;
        let repo = SCOPE_REPO.lock().unwrap();
        for (cursor, batch) in ops {
            if scope_state.len() > 0 {
                let scope_ident = self.identifier_for_stack(&scope_state, &repo);
                let start = self.offset - self.spans_start + prev_cursor;
                let end = start + (cursor - prev_cursor);
                if start != end {
                    let span = ScopeSpan::new(start, end, scope_ident);
                    self.spans.push(span);
                }
            }
            prev_cursor = cursor;
            scope_state.apply(&batch);
        }
        // add span for final state
        let start = self.offset - self.spans_start + prev_cursor;
        let end = start + (line.len() - prev_cursor);
        let scope_ident = self.identifier_for_stack(&scope_state, &repo);
        let span = ScopeSpan::new(start, end, scope_ident);
        self.spans.push(span);
        Some((parse_state, scope_state))
    }

    /// Returns the unique identifier for this `ScopeStack`. We use identifiers
    /// so we aren't constantly sending long stack names to the peer.
    fn identifier_for_stack(&mut self, stack: &ScopeStack, repo: &LockedRepo) -> u32 {
        let identifier = self.stack_idents.get_value(stack.as_slice());
        match identifier {
            LookupResult::Existing(id) => id,
            LookupResult::New(id) => {
                let stack_strings = stack.as_slice().iter()
                    .map(|slice| repo.to_string(*slice))
                    .collect::<Vec<_>>();
                self.new_scopes.push(stack_strings);
                id
            }
        }
    }

    #[allow(unused)]
    // Return true if there's any more work to be done.
    fn highlight_one_line(&mut self, ctx: &mut PluginCtx<State>) -> bool {
        if let Some(line_num) = ctx.get_frontier() {
            let (line_num, offset, state) = ctx.get_prev(line_num);
            if offset != self.offset {
                self.flush_spans(ctx);
                self.offset = offset;
                self.spans_start = offset;
            }
            let new_frontier = match ctx.get_line(line_num) {
                Ok("") => None,
                Ok(s) => {
                    let new_state = self.compute_syntax(s, state);
                    self.offset += s.len();
                    if s.as_bytes().last() == Some(&b'\n') {
                        Some((new_state, line_num + 1))
                    } else {
                        None
                    }
                }
                Err(_) => None,
            };
            let mut converged = false;
            if let Some((ref new_state, new_line_num)) = new_frontier {
                if let Some(old_state) = ctx.get(new_line_num) {
                    converged = old_state.as_ref().unwrap().0 == new_state.as_ref().unwrap().0;
                }
            }
            if !converged {
                if let Some((new_state, new_line_num)) = new_frontier {
                    ctx.set(new_line_num, new_state);
                    ctx.update_frontier(new_line_num);
                    return true;
                }
            }
            ctx.close_frontier();
        }
        false
    }

    fn flush_spans(&mut self, ctx: &mut PluginCtx<State>) {
        if !self.new_scopes.is_empty() {
            ctx.add_scopes(&self.new_scopes);
            self.new_scopes.clear();
        }
        if self.spans_start != self.offset {
            ctx.update_spans(self.spans_start, self.offset - self.spans_start,
                             &self.spans);
            self.spans.clear();
        }
        self.spans_start = self.offset;
    }

    fn do_highlighting(&mut self, mut ctx: PluginCtx<State>) {
        let syntax = match ctx.get_path() {
            Some(ref path) => self.syntax_set.find_syntax_for_file(path).unwrap()
                .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text()),
            None => self.syntax_set.find_syntax_plain_text(),
        };

        if syntax.name != self.syntax_name {
            self.syntax_name = syntax.name.clone();
            print_err!("syntect using {}", syntax.name);
        }

        self.initial_state = Some((ParseState::new(syntax), ScopeStack::new()));
        self.spans = Vec::new();
        self.new_scopes = Vec::new();
        self.offset = 0;
        self.spans_start = 0;
        ctx.reset();
        ctx.schedule_idle(0);
    }
}

impl<'a> state_cache::Plugin for PluginState<'a> {
    type State = State;

    fn initialize(&mut self, ctx: PluginCtx<State>, _buf_size: usize) {
        self.do_highlighting(ctx);
    }

    fn update(&mut self, mut ctx: PluginCtx<State>) {
        ctx.schedule_idle(0);
    }

    fn did_save(&mut self, ctx: PluginCtx<State>) {
        // TODO: use smarter logic to figure out whether we need to re-highlight the whole file
        self.do_highlighting(ctx);
    }

    fn idle(&mut self, mut ctx: PluginCtx<State>, _token: usize) {
        //print_err!("idle task at offset {}", self.offset);
        for _ in 0..LINES_PER_RPC {
            if !self.highlight_one_line(&mut ctx) {
                self.flush_spans(&mut ctx);
                return;
            }
            if ctx.request_is_pending() {
                print_err!("request pending at offset {}", self.offset);
                break;
            }
        }
        self.flush_spans(&mut ctx);
        ctx.schedule_idle(0);
    }
}

fn main() {
    let syntax_set = SyntaxSet::load_defaults_newlines();
    let mut state = PluginState::new(&syntax_set);

    state_cache::mainloop(&mut state);
}
<|endoftext|>


<commit_before><commit_msg>Add solution to Advent day 10<commit_after>// advent10.rs
// look-and-say

use std::io;

fn main() {
    // Part 1 and 2
    let mut input = String::new();

    io::stdin().read_line(&mut input)
        .ok()
        .expect("Failed to read line");
    let mut seq = input.trim().to_string();

    // part 1
    for _ in 0..40 {
        seq = look_and_say(&seq);
    }
    println!("length 40:{}", seq.len());

    // part 2
    for _ in 0..10 {
        seq = look_and_say(&seq);
    }
    println!("length 50:{}", seq.len());
}

// Part 1
fn look_and_say(s: &str) -> String {
    let mut say = String::new();
    if s.len() == 0 {
        return say;
    }

    let mut look = s.chars();

    let mut prev_char = look.next().unwrap();
    let mut run_length = 1;
    for c in look {
        if c != prev_char {
            say.push_str(&run_length.to_string());
            say.push(prev_char);
            run_length = 0;
            prev_char = c;
        }
        run_length += 1;
    }
    say.push_str(&run_length.to_string());
    say.push(prev_char);

    say
}

#[test]
fn test_part1() {
    assert_eq!("11", look_and_say("1"));
    assert_eq!("21", look_and_say("11"));
    assert_eq!("1211", look_and_say("21"));
    assert_eq!("111221", look_and_say("1211"));
    assert_eq!("312211", look_and_say("111221"));
}

<|endoftext|>


<commit_before><commit_msg>added dominates.rs<commit_after>/// Returns true if the candidate dominates or equal the parent
pub fn dominates(offspring_objectives: [f32; 2], parent_objectives: [f32; 2]) -> bool {
    if (offspring_objectives[0] <= parent_objectives[0]) &&
       (offspring_objectives[1] <= parent_objectives[1]) {
        return true;
    }
    return false;
}
<|endoftext|>


<commit_before><commit_msg>Add ansi mod<commit_after>const ESC: u8 = 27;

pub fn escape(sequence: &str) -> Vec<u8> {
  let mut ret = Vec::new();
  ret.push(ESC);
  ret.push_all(String::from_str("[").as_bytes());
  ret.push_all(sequence.as_bytes());
  ret
}

pub fn setpos(line: u16, column: u16) -> Vec<u8> {
  escape(format!("{};{}H", line + 1, column + 1).as_slice())
}

pub fn hide_cursor() -> Vec<u8> {
  escape("?25l")
}

pub fn show_cursor() -> Vec<u8> {
  escape("?25h")
}

pub fn inverse() -> Vec<u8> {
  escape("7m")
}

pub fn reset() -> Vec<u8> {
  escape("0m")
}
<|endoftext|>


<commit_before><commit_msg>Test(delete): refactor tests a little; add new ignored test that shows a failing case<commit_after><|endoftext|>


<commit_before><commit_msg>Chore(sync): log names of syncfiles when they can't be read<commit_after><|endoftext|>


<commit_before><commit_msg>add test<commit_after><|endoftext|>


<commit_before><commit_msg>Fix(delete): fix bug with delete code not detecting a conflict, add test<commit_after><|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 dom::bindings::codegen::EventBinding;
use dom::bindings::codegen::EventBinding::EventConstants;
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::error::Fallible;
use dom::eventtarget::EventTarget;
use dom::window::Window;
use servo_util::str::DOMString;

use geom::point::Point2D;

pub enum Event_ {
    ResizeEvent(uint, uint),
    ReflowEvent,
    ClickEvent(uint, Point2D<f32>),
    MouseDownEvent(uint, Point2D<f32>),
    MouseUpEvent(uint, Point2D<f32>),
    MouseMoveEvent(Point2D<f32>)
}

#[deriving(Encodable)]
pub enum EventPhase {
    PhaseNone      = EventConstants::NONE,
    PhaseCapturing = EventConstants::CAPTURING_PHASE,
    PhaseAtTarget  = EventConstants::AT_TARGET,
    PhaseBubbling  = EventConstants::BUBBLING_PHASE,
}

#[deriving(Eq, Encodable)]
pub enum EventTypeId {
    HTMLEventTypeId,
    UIEventTypeId,
    MouseEventTypeId,
    KeyEventTypeId
}

#[deriving(Encodable)]
pub struct Event {
    type_id: EventTypeId,
    reflector_: Reflector,
    current_target: Option<JS<EventTarget>>,
    target: Option<JS<EventTarget>>,
    type_: DOMString,
    phase: EventPhase,
    canceled: bool,
    stop_propagation: bool,
    stop_immediate: bool,
    cancelable: bool,
    bubbles: bool,
    trusted: bool,
    dispatching: bool,
    initialized: bool,
}

impl Event {
    pub fn new_inherited(type_id: EventTypeId) -> Event {
        Event {
            type_id: type_id,
            reflector_: Reflector::new(),
            current_target: None,
            target: None,
            phase: PhaseNone,
            type_: ~"",
            canceled: false,
            cancelable: true,
            bubbles: true,
            trusted: false,
            dispatching: false,
            stop_propagation: false,
            stop_immediate: false,
            initialized: false,
        }
    }

    pub fn new(window: &JS<Window>) -> JS<Event> {
        reflect_dom_object(~Event::new_inherited(HTMLEventTypeId),
                           window,
                           EventBinding::Wrap)
    }

    pub fn EventPhase(&self) -> u16 {
        self.phase as u16
    }

    pub fn Type(&self) -> DOMString {
        self.type_.clone()
    }

    pub fn GetTarget(&self) -> Option<JS<EventTarget>> {
        self.target.clone()
    }

    pub fn GetCurrentTarget(&self) -> Option<JS<EventTarget>> {
        self.current_target.clone()
    }

    pub fn DefaultPrevented(&self) -> bool {
        self.canceled
    }

    pub fn PreventDefault(&mut self) {
        if self.cancelable {
            self.canceled = true
        }
    }

    pub fn StopPropagation(&mut self) {
        self.stop_propagation = true;
    }

    pub fn StopImmediatePropagation(&mut self) {
        self.stop_immediate = true;
        self.stop_propagation = true;
    }

    pub fn Bubbles(&self) -> bool {
        self.bubbles
    }

    pub fn Cancelable(&self) -> bool {
        self.cancelable
    }

    pub fn TimeStamp(&self) -> u64 {
        0
    }

    pub fn InitEvent(&mut self,
                     type_: DOMString,
                     bubbles: bool,
                     cancelable: bool) {
        self.initialized = true;
        if self.dispatching {
            return;
        }
        self.stop_propagation = false;
        self.stop_immediate = false;
        self.canceled = false;
        self.trusted = false;
        self.target = None;
        self.type_ = type_;
        self.bubbles = bubbles;
        self.cancelable = cancelable;
    }

    pub fn IsTrusted(&self) -> bool {
        self.trusted
    }

    pub fn Constructor(global: &JS<Window>,
                       type_: DOMString,
                       init: &EventBinding::EventInit) -> Fallible<JS<Event>> {
        let mut ev = Event::new(global);
        ev.get_mut().InitEvent(type_, init.bubbles, init.cancelable);
        Ok(ev)
    }
}

impl Reflectable for Event {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }

    fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
        &mut self.reflector_
    }
}
<commit_msg>#2183 Initialize Event::bubbles to false<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 dom::bindings::codegen::EventBinding;
use dom::bindings::codegen::EventBinding::EventConstants;
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::error::Fallible;
use dom::eventtarget::EventTarget;
use dom::window::Window;
use servo_util::str::DOMString;

use geom::point::Point2D;

pub enum Event_ {
    ResizeEvent(uint, uint),
    ReflowEvent,
    ClickEvent(uint, Point2D<f32>),
    MouseDownEvent(uint, Point2D<f32>),
    MouseUpEvent(uint, Point2D<f32>),
    MouseMoveEvent(Point2D<f32>)
}

#[deriving(Encodable)]
pub enum EventPhase {
    PhaseNone      = EventConstants::NONE,
    PhaseCapturing = EventConstants::CAPTURING_PHASE,
    PhaseAtTarget  = EventConstants::AT_TARGET,
    PhaseBubbling  = EventConstants::BUBBLING_PHASE,
}

#[deriving(Eq, Encodable)]
pub enum EventTypeId {
    HTMLEventTypeId,
    UIEventTypeId,
    MouseEventTypeId,
    KeyEventTypeId
}

#[deriving(Encodable)]
pub struct Event {
    type_id: EventTypeId,
    reflector_: Reflector,
    current_target: Option<JS<EventTarget>>,
    target: Option<JS<EventTarget>>,
    type_: DOMString,
    phase: EventPhase,
    canceled: bool,
    stop_propagation: bool,
    stop_immediate: bool,
    cancelable: bool,
    bubbles: bool,
    trusted: bool,
    dispatching: bool,
    initialized: bool,
}

impl Event {
    pub fn new_inherited(type_id: EventTypeId) -> Event {
        Event {
            type_id: type_id,
            reflector_: Reflector::new(),
            current_target: None,
            target: None,
            phase: PhaseNone,
            type_: ~"",
            canceled: false,
            cancelable: true,
            bubbles: false,
            trusted: false,
            dispatching: false,
            stop_propagation: false,
            stop_immediate: false,
            initialized: false,
        }
    }

    pub fn new(window: &JS<Window>) -> JS<Event> {
        reflect_dom_object(~Event::new_inherited(HTMLEventTypeId),
                           window,
                           EventBinding::Wrap)
    }

    pub fn EventPhase(&self) -> u16 {
        self.phase as u16
    }

    pub fn Type(&self) -> DOMString {
        self.type_.clone()
    }

    pub fn GetTarget(&self) -> Option<JS<EventTarget>> {
        self.target.clone()
    }

    pub fn GetCurrentTarget(&self) -> Option<JS<EventTarget>> {
        self.current_target.clone()
    }

    pub fn DefaultPrevented(&self) -> bool {
        self.canceled
    }

    pub fn PreventDefault(&mut self) {
        if self.cancelable {
            self.canceled = true
        }
    }

    pub fn StopPropagation(&mut self) {
        self.stop_propagation = true;
    }

    pub fn StopImmediatePropagation(&mut self) {
        self.stop_immediate = true;
        self.stop_propagation = true;
    }

    pub fn Bubbles(&self) -> bool {
        self.bubbles
    }

    pub fn Cancelable(&self) -> bool {
        self.cancelable
    }

    pub fn TimeStamp(&self) -> u64 {
        0
    }

    pub fn InitEvent(&mut self,
                     type_: DOMString,
                     bubbles: bool,
                     cancelable: bool) {
        self.initialized = true;
        if self.dispatching {
            return;
        }
        self.stop_propagation = false;
        self.stop_immediate = false;
        self.canceled = false;
        self.trusted = false;
        self.target = None;
        self.type_ = type_;
        self.bubbles = bubbles;
        self.cancelable = cancelable;
    }

    pub fn IsTrusted(&self) -> bool {
        self.trusted
    }

    pub fn Constructor(global: &JS<Window>,
                       type_: DOMString,
                       init: &EventBinding::EventInit) -> Fallible<JS<Event>> {
        let mut ev = Event::new(global);
        ev.get_mut().InitEvent(type_, init.bubbles, init.cancelable);
        Ok(ev)
    }
}

impl Reflectable for Event {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }

    fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
        &mut self.reflector_
    }
}
<|endoftext|>


<commit_before><commit_msg>Added function notes<commit_after>// A complilation of notes and lessons from https://doc.rust-lang.org/book/functions.html

fn main() {
    // print_number(5);
    print_number(add_two_numbers(5, 5));
    print_number(semicolon_test());
}

// Similar to specifically typing variables (bindings) - specify the type of parameters like so
// Note that you *must* specify types in the function declaration. You can't just hope the compiler
// figures it out (like 'let')
fn print_number(num : i32) {
    println!("Number is {}", num);
}

// If you don't specify a return type it just defaults to something similar to "void" in C++
// You can specify a return like so
// Side note: I'm not a fan of the style of having the brace on the same line as the declaration,
// especially with a return type there too since it's harder to see the return type at a glance
// when skimming code. However, it appears that's the suggested way of doing it (both in the example
// and the Rust syntax in my editor)
fn add_two_numbers(num1 : i32, num2 : i32) -> i32 {
    // This is an interesting thing: the last line of a method determines what it'll return
    // And yes, not having a semicolon is intentional - if we had one we'd get a compilation error
    // saying that not all control paths return a value
    // This is because "num1 + num2" is an expression while "num1 + num2;" is a statement. An expression
    // returns a value inherantly while a statement does not
    num1 + num2
}

// Statements vs. Expressions is fundamental in Rust. Like it's said above, the difference between expressions
// and statements is that expressions return a value while statements do not
// Using 'let' to assign a value to a variable is *not* an expression and thus doesn't return a value, which
// might be useful in chaining in other languages (eg. x = y = z = 5). This is what's called a 'declaration statement'.
// Note that assigning to an already bound variable is an expression but the return result is an empty tuple.
// So chaining is not useful even then.
// However, like seen above you can not include a semicolon to have a statement become an expression and return a value
fn semicolon_test() -> i32 {
    // The below returns 34 inherantly. But it must be the last thing in the method. I suppose it's a type of shorthand...
    // 34

    // This returns in a more traditional way
    // return 30;

    // This...also returns 24, I guess. Rust is weird.
    return 24

    // A note on the above: using the 'return' keyword is used for early returns. It can be used 'traditionally', like
    // in C++ or Java or similar, as the last return of a method but that's considered bad style. The Rust way is to
    // use the 'return' keyword only for early returns
}

// Diverging functions are functions in Rust that do not return. Here's an example:
// You can set RUST_BACKTRACE environment variable to 1 to see the stack trace at the crash site
fn diverges() -> ! {
    // Forces a crash
    panic!("this method never returns");
}

// We can set a variable binding to a function pointer
fn fn_pointer() {
    // Type inference can be used here - here's an example of not using it though
    let pointer1: fn(i32, i32) -> i32 = add_two_numbers;
    pointer1(32, 54);

    // Type inference for a function pointer
    let pointer2 = add_two_numbers;
    pointer2(21, 21);
}<|endoftext|>


<commit_before><commit_msg>Add tests for parsing HTTP headers<commit_after><|endoftext|>


<commit_before><commit_msg>Rework on the add subcommand<commit_after><|endoftext|>


<commit_before><commit_msg>basic fluid simulation works<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed infinite loop<commit_after><|endoftext|>


<commit_before><commit_msg>Add primitive bot code<commit_after>extern crate irc;

use irc::client::prelude::*;
use std::default::Default;

fn main() {
	let server = IrcServer::from_config(Config{
		owners   : Some(vec!["nabijaczleweli".to_string()]),
		nickname : Some("NabBot".to_string()),
		username : Some("NabBot".to_string()),
		realname : Some("наб's IRC bot".to_string()),
		server   : Some("chat.freenode.net".to_string()),
		use_ssl  : Some(true),
		channels : Some(vec!["#loungecpp".to_string()]),
		user_info: Some("наб's IRC bot".to_string()),
		..Default::default()
	}).unwrap();
	server.identify().unwrap();

	for message in server.iter() {
		if let Ok(message) = message {
			let source_nickname = message.get_source_nickname().map(String::from);

			if let Ok(Command::PRIVMSG(target, msg)) = Command::from_message_io(Ok(message)) {
				if (target == "NabBot" && msg == "Navaer") || msg == "Navaer, NabBot" {
					server.send_privmsg(&*&source_nickname.unwrap_or(target), "Mára mesta").unwrap();
					server.send_quit("Mára mesta").unwrap();
				} else if msg.contains("isn't") || msg.contains("is not") {
					println!("{}: {:?} -> Not your face", source_nickname.as_ref().unwrap_or(&"???".to_string()), msg);
					server.send_privmsg(&target, "Quite unlike your face").unwrap();
				} else if msg.contains("sucks") || msg.contains("is") {
					println!("{}: {:?} -> Your face", source_nickname.as_ref().unwrap_or(&"???".to_string()), msg);
					server.send_privmsg(&target, "Much like your face").unwrap();
				}
			}
		}
	}
}
<|endoftext|>