<commit_before>// Implements http://rosettacode.org/wiki/Write_ppm_file
#![allow(unused_features)]
#![allow(unused_attributes)]
#![feature(old_io)]
#![feature(env)]
#![feature(old_path)]
#![feature(core)]

extern crate rand;

use std::old_io::{File, BufferedWriter, IoResult};
use bitmap::Image;
mod bitmap;

trait PPMWritable {
    fn write_ppm(&self, filename: &str) -> IoResult<()>;
}

impl PPMWritable for Image {
    fn write_ppm(&self, filename: &str) -> IoResult<()> {
        let file = File::create(&Path::new(filename));
        let mut writer = BufferedWriter::new(file);
        try!(writer.write_line("P6"));
        try!(write!(&mut writer, "{} {} {}\n", self.width, self.height, 255));
        for color in &(self.data) {
            for channel in &[color.red, color.green, color.blue] {
                try!(writer.write_u8(*channel));
            }
        }
        Ok(())
    }
}

#[cfg(not(test))]
pub fn main() {
    use bitmap::Color;

    // write a PPM image, the left side of which is red, and the right side
    // of which is blue
    let mut image = Image::new(64, 64);
    image.fill(Color { red: 255, green: 0, blue: 0 });
    for y in 0..64 {
        for x in 32..64 {
            image[(x, y)] = Color { red: 0, green: 0, blue: 255 };
        }
    }
    image.write_ppm("./test_image.ppm").unwrap();
}

#[cfg(test)]
mod test {
    use bitmap::{Color, Image};
    use std::old_io::{File, BufferedReader};
    use rand;
    use rand::Rng;
    use std::env;

    #[test]
    fn write_ppm() {
        let mut image = Image::new(2,1);
        image[(0, 0)] = Color { red: 1, green: 2, blue: 3 };
        image[(1, 0)] = Color { red: 4, green: 5, blue: 6 };
        let fname = format!("{}/test-{}.ppm", env::temp_dir().as_str().unwrap(), rand::thread_rng().gen::<i32>());
        // Can't use try! macro because we want to panic, not return.
        match image.write_ppm(&fname[..]) {
            Ok(_) => {},
            Err(e) => panic!(e)
        }

        let file = File::open(&Path::new(&fname[..]));
        let mut reader = BufferedReader::new(file);
        assert_eq!(reader.read_line().unwrap(), "P6\n");
        assert_eq!(reader.read_line().unwrap(), "2 1 255\n");
        assert_eq!(reader.read_byte().unwrap(), 1);
        assert_eq!(reader.read_byte().unwrap(), 2);
        assert_eq!(reader.read_byte().unwrap(), 3);
        assert_eq!(reader.read_byte().unwrap(), 4);
        assert_eq!(reader.read_byte().unwrap(), 5);
        assert_eq!(reader.read_byte().unwrap(), 6);
        assert!(reader.read_byte().is_err());

    }
}
<commit_msg>Fix build<commit_after>// Implements http://rosettacode.org/wiki/Write_ppm_file
#![allow(unused_features)]
#![allow(unused_attributes)]
#![feature(old_io)]
#![feature(env)]
#![feature(old_path)]
#![feature(core)]

extern crate rand;

use std::old_io::{File, BufferedWriter, IoResult};
use bitmap::Image;
mod bitmap;

trait PPMWritable {
    fn write_ppm(&self, filename: &str) -> IoResult<()>;
}

impl PPMWritable for Image {
    fn write_ppm(&self, filename: &str) -> IoResult<()> {
        let file = File::create(&Path::new(filename));
        let mut writer = BufferedWriter::new(file);
        try!(writer.write_line("P6"));
        try!(write!(&mut writer, "{} {} {}\n", self.width, self.height, 255));
        for color in &(self.data) {
            for channel in &[color.red, color.green, color.blue] {
                try!(writer.write_u8(*channel));
            }
        }
        Ok(())
    }
}

#[cfg(not(test))]
pub fn main() {
    use bitmap::Color;

    // write a PPM image, the left side of which is red, and the right side
    // of which is blue
    let mut image = Image::new(64, 64);
    image.fill(Color { red: 255, green: 0, blue: 0 });
    for y in 0..64 {
        for x in 32..64 {
            image[(x, y)] = Color { red: 0, green: 0, blue: 255 };
        }
    }
    image.write_ppm("./test_image.ppm").unwrap();
}

#[cfg(test)]
mod test {
    use bitmap::{Color, Image};
    use std::old_io::{File, BufferedReader};
    use rand;
    use rand::Rng;
    use std::env;

    #[test]
    fn write_ppm() {
        let mut image = Image::new(2,1);
        image[(0, 0)] = Color { red: 1, green: 2, blue: 3 };
        image[(1, 0)] = Color { red: 4, green: 5, blue: 6 };
        let fname = format!("{}/test-{}.ppm", env::temp_dir().to_str().unwrap(), rand::thread_rng().gen::<i32>());
        // Can't use try! macro because we want to panic, not return.
        match image.write_ppm(&fname[..]) {
            Ok(_) => {},
            Err(e) => panic!(e)
        }

        let file = File::open(&Path::new(&fname[..]));
        let mut reader = BufferedReader::new(file);
        assert_eq!(reader.read_line().unwrap(), "P6\n");
        assert_eq!(reader.read_line().unwrap(), "2 1 255\n");
        assert_eq!(reader.read_byte().unwrap(), 1);
        assert_eq!(reader.read_byte().unwrap(), 2);
        assert_eq!(reader.read_byte().unwrap(), 3);
        assert_eq!(reader.read_byte().unwrap(), 4);
        assert_eq!(reader.read_byte().unwrap(), 5);
        assert_eq!(reader.read_byte().unwrap(), 6);
        assert!(reader.read_byte().is_err());

    }
}
<|endoftext|>


<commit_before>//! Linear algebra utils module.
//!
//! Contains support methods for linear algebra structs.

use std::cmp;
use libnum::Zero;
use std::ops::{Add, Mul, Sub, Div};
use std::mem;

/// Compute dot product of two slices.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
/// let b = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::dot(&a,&b);
/// ```
pub fn dot<T: Copy + Zero + Add<T, Output = T> + Mul<T, Output = T>>(u: &[T], v: &[T]) -> T {
    let len = cmp::min(u.len(), v.len());
    let mut xs = &u[..len];
    let mut ys = &v[..len];

    let mut s = T::zero();
    let (mut p0,
         mut p1,
         mut p2,
         mut p3,
         mut p4,
         mut p5,
         mut p6,
         mut p7) = (T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero());

    while xs.len() >= 8 {
        p0 = p0 + xs[0] * ys[0];
        p1 = p1 + xs[1] * ys[1];
        p2 = p2 + xs[2] * ys[2];
        p3 = p3 + xs[3] * ys[3];
        p4 = p4 + xs[4] * ys[4];
        p5 = p5 + xs[5] * ys[5];
        p6 = p6 + xs[6] * ys[6];
        p7 = p7 + xs[7] * ys[7];

        xs = &xs[8..];
        ys = &ys[8..];
    }
    s = s + p0 + p4;
    s = s + p1 + p5;
    s = s + p2 + p6;
    s = s + p3 + p7;

    for i in 0..xs.len() {
        s = s + xs[i] * ys[i];
    }
    s
}

/// Unrolled sum
///
/// Computes the sum over the slice consuming it in the process.
///
/// Given graciously by bluss from ndarray!
pub fn unrolled_sum<T>(mut xs: &[T]) -> T
    where T: Clone + Add<Output = T> + Zero
{
    // eightfold unrolled so that floating point can be vectorized
    // (even with strict floating point accuracy semantics)
    let mut sum = T::zero();
    let (mut p0,
         mut p1,
         mut p2,
         mut p3,
         mut p4,
         mut p5,
         mut p6,
         mut p7) = (T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero());
    while xs.len() >= 8 {
        p0 = p0 + xs[0].clone();
        p1 = p1 + xs[1].clone();
        p2 = p2 + xs[2].clone();
        p3 = p3 + xs[3].clone();
        p4 = p4 + xs[4].clone();
        p5 = p5 + xs[5].clone();
        p6 = p6 + xs[6].clone();
        p7 = p7 + xs[7].clone();

        xs = &xs[8..];
    }
    sum = sum.clone() + (p0 + p4);
    sum = sum.clone() + (p1 + p5);
    sum = sum.clone() + (p2 + p6);
    sum = sum.clone() + (p3 + p7);
    for elt in xs {
        sum = sum.clone() + elt.clone();
    }
    sum
}

pub fn in_place_vec_bin_op<F, T: Copy>(mut u: &mut [T], v: &[T], mut f: F)
    where F: FnMut(&mut T, &T) {
        let len = cmp::min(u.len(), v.len());

        let ys = &v[..len];

        let mut new_slice = mem::replace(&mut u, &mut []);
        let (l,_) = new_slice.split_at_mut(len);
        u = l;

        for i in 0..len {
            f(&mut u[i], &ys[i])
        }
}

fn vec_bin_op<F, T: Copy>(u: &[T], v: &[T], f: F) -> Vec<T>
    where F: Fn(T, T) -> T {
        let len = cmp::min(u.len(), v.len());

        let xs = &u[..len];
        let ys = &v[..len];

        let mut out_vec = Vec::with_capacity(len);
        unsafe {
            out_vec.set_len(len);
        }

        {
            let out_slice = &mut out_vec[..len];

            for i in 0..len {
                out_slice[i] = f(xs[i], ys[i]);
            }
        }

        out_vec
}

/// Compute vector sum of two slices.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
/// let b = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::vec_sum(&a,&b);
///
/// assert_eq!(c, vec![2.0,4.0, 6.0, 8.0]);
/// ```
pub fn vec_sum<T: Copy + Add<T, Output = T>>(u: &[T], v: &[T]) -> Vec<T> {
    vec_bin_op(u, v, |x, y| { x + y })
}

/// Compute vector difference two slices.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
/// let b = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::vec_sub(&a,&b);
///
/// assert_eq!(c, vec![0.0; 4]);
/// ```
pub fn vec_sub<T: Copy + Sub<T, Output = T>>(u: &[T], v: &[T]) -> Vec<T> {
    vec_bin_op(u, v, |x, y| { x - y })
}

/// Computes elementwise multiplication.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
/// let b = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::ele_mul(&a,&b);
///
/// assert_eq!(c, vec![1.0,4.0,9.0,16.0]);
/// ```
pub fn ele_mul<T: Copy + Mul<T, Output = T>>(u: &[T], v: &[T]) -> Vec<T> {
    vec_bin_op(u, v, |x, y| { x * y })
}

/// Computes elementwise division.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
/// let b = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::ele_div(&a,&b);
///
/// assert_eq!(c, vec![1.0; 4]);
/// ```
pub fn ele_div<T: Copy + Div<T, Output = T>>(u: &[T], v: &[T]) -> Vec<T> {
    vec_bin_op(u, v, |x, y| { x / y })
}

/// Find argmax of slice.
///
/// Returns index of first occuring maximum.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::argmax(&a);
/// assert_eq!(c.0, 3);
/// assert_eq!(c.1, 4.0);
/// ```
pub fn argmax<T: Copy + PartialOrd>(u: &[T]) -> (usize, T) {
    assert!(u.len() != 0);

    let mut max_index = 0;
    let mut max = u[max_index];

    for (i, v) in (u.iter()).enumerate() {
        if max < *v {
            max_index = i;
            max = *v;
        }
    }

    (max_index, max)
}

/// Find argmin of slice.
///
/// Returns index of first occuring minimum.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![5.0,2.0,3.0,4.0];
///
/// let c = utils::argmin(&a);
/// assert_eq!(c.0, 1);
/// assert_eq!(c.1, 2.0);
/// ```
pub fn argmin<T: Copy + PartialOrd>(u: &[T]) -> (usize, T) {
    assert!(u.len() != 0);

    let mut min_index = 0;
    let mut min = u[min_index];

    for (i, v) in (u.iter()).enumerate() {
        if min > *v {
            min_index = i;
            min = *v;
        }
    }

    (min_index, min)
}

/// Find index of value in slice.
///
/// Returns index of first occuring value.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::find(&a, 3.0);
/// assert_eq!(c, 2);
/// ```
pub fn find<T: PartialEq>(p: &[T], u: T) -> usize {
    for (i, v) in p.iter().enumerate() {
        if *v == u {
            return i;
        }
    }

    panic!("Value not found.")
}
<commit_msg>Adding docs and debug assertions<commit_after>//! Linear algebra utils module.
//!
//! Contains support methods for linear algebra structs.

use std::cmp;
use libnum::Zero;
use std::ops::{Add, Mul, Sub, Div};
use std::mem;

/// Compute dot product of two slices.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
/// let b = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::dot(&a,&b);
/// ```
pub fn dot<T: Copy + Zero + Add<T, Output = T> + Mul<T, Output = T>>(u: &[T], v: &[T]) -> T {
    let len = cmp::min(u.len(), v.len());
    let mut xs = &u[..len];
    let mut ys = &v[..len];

    let mut s = T::zero();
    let (mut p0,
         mut p1,
         mut p2,
         mut p3,
         mut p4,
         mut p5,
         mut p6,
         mut p7) = (T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero());

    while xs.len() >= 8 {
        p0 = p0 + xs[0] * ys[0];
        p1 = p1 + xs[1] * ys[1];
        p2 = p2 + xs[2] * ys[2];
        p3 = p3 + xs[3] * ys[3];
        p4 = p4 + xs[4] * ys[4];
        p5 = p5 + xs[5] * ys[5];
        p6 = p6 + xs[6] * ys[6];
        p7 = p7 + xs[7] * ys[7];

        xs = &xs[8..];
        ys = &ys[8..];
    }
    s = s + p0 + p4;
    s = s + p1 + p5;
    s = s + p2 + p6;
    s = s + p3 + p7;

    for i in 0..xs.len() {
        s = s + xs[i] * ys[i];
    }
    s
}

/// Unrolled sum
///
/// Computes the sum over the slice consuming it in the process.
///
/// Given graciously by bluss from ndarray!
pub fn unrolled_sum<T>(mut xs: &[T]) -> T
    where T: Clone + Add<Output = T> + Zero
{
    // eightfold unrolled so that floating point can be vectorized
    // (even with strict floating point accuracy semantics)
    let mut sum = T::zero();
    let (mut p0,
         mut p1,
         mut p2,
         mut p3,
         mut p4,
         mut p5,
         mut p6,
         mut p7) = (T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero(),
                    T::zero());
    while xs.len() >= 8 {
        p0 = p0 + xs[0].clone();
        p1 = p1 + xs[1].clone();
        p2 = p2 + xs[2].clone();
        p3 = p3 + xs[3].clone();
        p4 = p4 + xs[4].clone();
        p5 = p5 + xs[5].clone();
        p6 = p6 + xs[6].clone();
        p7 = p7 + xs[7].clone();

        xs = &xs[8..];
    }
    sum = sum.clone() + (p0 + p4);
    sum = sum.clone() + (p1 + p5);
    sum = sum.clone() + (p2 + p6);
    sum = sum.clone() + (p3 + p7);
    for elt in xs {
        sum = sum.clone() + elt.clone();
    }
    sum
}

/// Vectorized binary operation applied to two slices.
/// The first argument should be a mutable slice which will
/// be modified in place to prevent new memory allocation.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
///
/// let mut a = vec![2.0; 10];
/// let b = vec![3.0; 10];
///
/// utils::in_place_vec_bin_op(&mut a, &b, |x, &y| { *x = 1f64 + *x * y });
///
/// // Will print a vector of `7`s.
/// println!("{:?}", a);
/// ```
pub fn in_place_vec_bin_op<F, T: Copy>(mut u: &mut [T], v: &[T], mut f: F)
    where F: FnMut(&mut T, &T) {
        debug_assert_eq!(u.len(), v.len());
        let len = cmp::min(u.len(), v.len());

        let ys = &v[..len];

        let mut new_slice = mem::replace(&mut u, &mut []);
        let (l,_) = new_slice.split_at_mut(len);
        u = l;

        for i in 0..len {
            f(&mut u[i], &ys[i])
        }
}

fn vec_bin_op<F, T: Copy>(u: &[T], v: &[T], f: F) -> Vec<T>
    where F: Fn(T, T) -> T {
        debug_assert_eq!(u.len(), v.len());
        let len = cmp::min(u.len(), v.len());

        let xs = &u[..len];
        let ys = &v[..len];

        let mut out_vec = Vec::with_capacity(len);
        unsafe {
            out_vec.set_len(len);
        }

        {
            let out_slice = &mut out_vec[..len];

            for i in 0..len {
                out_slice[i] = f(xs[i], ys[i]);
            }
        }

        out_vec
}

/// Compute vector sum of two slices.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
/// let b = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::vec_sum(&a,&b);
///
/// assert_eq!(c, vec![2.0,4.0, 6.0, 8.0]);
/// ```
pub fn vec_sum<T: Copy + Add<T, Output = T>>(u: &[T], v: &[T]) -> Vec<T> {
    vec_bin_op(u, v, |x, y| { x + y })
}

/// Compute vector difference two slices.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
/// let b = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::vec_sub(&a,&b);
///
/// assert_eq!(c, vec![0.0; 4]);
/// ```
pub fn vec_sub<T: Copy + Sub<T, Output = T>>(u: &[T], v: &[T]) -> Vec<T> {
    vec_bin_op(u, v, |x, y| { x - y })
}

/// Computes elementwise multiplication.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
/// let b = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::ele_mul(&a,&b);
///
/// assert_eq!(c, vec![1.0,4.0,9.0,16.0]);
/// ```
pub fn ele_mul<T: Copy + Mul<T, Output = T>>(u: &[T], v: &[T]) -> Vec<T> {
    vec_bin_op(u, v, |x, y| { x * y })
}

/// Computes elementwise division.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
/// let b = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::ele_div(&a,&b);
///
/// assert_eq!(c, vec![1.0; 4]);
/// ```
pub fn ele_div<T: Copy + Div<T, Output = T>>(u: &[T], v: &[T]) -> Vec<T> {
    vec_bin_op(u, v, |x, y| { x / y })
}

/// Find argmax of slice.
///
/// Returns index of first occuring maximum.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::argmax(&a);
/// assert_eq!(c.0, 3);
/// assert_eq!(c.1, 4.0);
/// ```
pub fn argmax<T: Copy + PartialOrd>(u: &[T]) -> (usize, T) {
    assert!(u.len() != 0);

    let mut max_index = 0;
    let mut max = u[max_index];

    for (i, v) in (u.iter()).enumerate() {
        if max < *v {
            max_index = i;
            max = *v;
        }
    }

    (max_index, max)
}

/// Find argmin of slice.
///
/// Returns index of first occuring minimum.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![5.0,2.0,3.0,4.0];
///
/// let c = utils::argmin(&a);
/// assert_eq!(c.0, 1);
/// assert_eq!(c.1, 2.0);
/// ```
pub fn argmin<T: Copy + PartialOrd>(u: &[T]) -> (usize, T) {
    assert!(u.len() != 0);

    let mut min_index = 0;
    let mut min = u[min_index];

    for (i, v) in (u.iter()).enumerate() {
        if min > *v {
            min_index = i;
            min = *v;
        }
    }

    (min_index, min)
}

/// Find index of value in slice.
///
/// Returns index of first occuring value.
///
/// # Examples
///
/// ```
/// use rusty_machine::linalg::utils;
/// let a = vec![1.0,2.0,3.0,4.0];
///
/// let c = utils::find(&a, 3.0);
/// assert_eq!(c, 2);
/// ```
pub fn find<T: PartialEq>(p: &[T], u: T) -> usize {
    for (i, v) in p.iter().enumerate() {
        if *v == u {
            return i;
        }
    }

    panic!("Value not found.")
}
<|endoftext|>


<commit_before>//! Functionality for downloading crates and maintaining download counts
//!
//! Crate level functionality is located in `krate::downloads`.

use crate::controllers::prelude::*;

use chrono::{Duration, NaiveDate, Utc};

use crate::models::{Crate, VersionDownload};
use crate::schema::*;
use crate::views::EncodableVersionDownload;

use super::{extract_crate_name_and_semver, version_and_crate};

/// Handles the `GET /crates/:crate_id/:version/download` route.
/// This returns a URL to the location where the crate is stored.
pub fn download(req: &mut dyn RequestExt) -> EndpointResult {
    let recorder = req.timing_recorder();

    let crate_name = &req.params()["crate_id"];
    let version = &req.params()["version"];

    let (version_id, crate_name): (_, String) = {
        use self::versions::dsl::*;

        let conn = recorder.record("get_conn", || req.db_conn())?;

        // Returns the crate name as stored in the database, or an error if we could
        // not load the version ID from the database.
        recorder.record("get_version", || {
            versions
                .inner_join(crates::table)
                .select((id, crates::name))
                .filter(Crate::with_name(crate_name))
                .filter(num.eq(version))
                .first(&*conn)
        })?
    };

    // The increment does not happen instantly, but it's deferred to be executed in a batch
    // along with other downloads. See crate::downloads_counter for the implementation.
    req.app().downloads_counter.increment(version_id);

    let redirect_url = req
        .app()
        .config
        .uploader
        .crate_location(&crate_name, version);

    if req.wants_json() {
        #[derive(Serialize)]
        struct R {
            url: String,
        }
        Ok(req.json(&R { url: redirect_url }))
    } else {
        Ok(req.redirect(redirect_url))
    }
}

/// Handles the `GET /crates/:crate_id/:version/downloads` route.
pub fn downloads(req: &mut dyn RequestExt) -> EndpointResult {
    let (crate_name, semver) = extract_crate_name_and_semver(req)?;

    let conn = req.db_read_only()?;
    let (version, _) = version_and_crate(&conn, crate_name, semver)?;

    let cutoff_end_date = req
        .query()
        .get("before_date")
        .and_then(|d| NaiveDate::parse_from_str(d, "%F").ok())
        .unwrap_or_else(|| Utc::today().naive_utc());
    let cutoff_start_date = cutoff_end_date - Duration::days(89);

    let downloads = VersionDownload::belonging_to(&version)
        .filter(version_downloads::date.between(cutoff_start_date, cutoff_end_date))
        .order(version_downloads::date)
        .load(&*conn)?
        .into_iter()
        .map(VersionDownload::into)
        .collect();

    #[derive(Serialize)]
    struct R {
        version_downloads: Vec<EncodableVersionDownload>,
    }
    Ok(req.json(&R {
        version_downloads: downloads,
    }))
}
<commit_msg>Auto merge of #3514 - jtgeibel:non-canonical-dl, r=pietroalbini<commit_after>//! Functionality for downloading crates and maintaining download counts
//!
//! Crate level functionality is located in `krate::downloads`.

use crate::controllers::prelude::*;

use chrono::{Duration, NaiveDate, Utc};

use crate::models::{Crate, VersionDownload};
use crate::schema::*;
use crate::views::EncodableVersionDownload;

use super::{extract_crate_name_and_semver, version_and_crate};

/// Handles the `GET /crates/:crate_id/:version/download` route.
/// This returns a URL to the location where the crate is stored.
pub fn download(req: &mut dyn RequestExt) -> EndpointResult {
    let recorder = req.timing_recorder();

    let crate_name = &req.params()["crate_id"];
    let version = &req.params()["version"];

    let (version_id, canonical_crate_name): (_, String) = {
        use self::versions::dsl::*;

        let conn = recorder.record("get_conn", || req.db_conn())?;

        // Returns the crate name as stored in the database, or an error if we could
        // not load the version ID from the database.
        recorder.record("get_version", || {
            versions
                .inner_join(crates::table)
                .select((id, crates::name))
                .filter(Crate::with_name(crate_name))
                .filter(num.eq(version))
                .first(&*conn)
        })?
    };

    // The increment does not happen instantly, but it's deferred to be executed in a batch
    // along with other downloads. See crate::downloads_counter for the implementation.
    req.app().downloads_counter.increment(version_id);

    let redirect_url = req
        .app()
        .config
        .uploader
        .crate_location(&canonical_crate_name, version);

    if &canonical_crate_name != crate_name {
        req.log_metadata("bot", "dl");
    }

    if req.wants_json() {
        #[derive(Serialize)]
        struct R {
            url: String,
        }
        Ok(req.json(&R { url: redirect_url }))
    } else {
        Ok(req.redirect(redirect_url))
    }
}

/// Handles the `GET /crates/:crate_id/:version/downloads` route.
pub fn downloads(req: &mut dyn RequestExt) -> EndpointResult {
    let (crate_name, semver) = extract_crate_name_and_semver(req)?;

    let conn = req.db_read_only()?;
    let (version, _) = version_and_crate(&conn, crate_name, semver)?;

    let cutoff_end_date = req
        .query()
        .get("before_date")
        .and_then(|d| NaiveDate::parse_from_str(d, "%F").ok())
        .unwrap_or_else(|| Utc::today().naive_utc());
    let cutoff_start_date = cutoff_end_date - Duration::days(89);

    let downloads = VersionDownload::belonging_to(&version)
        .filter(version_downloads::date.between(cutoff_start_date, cutoff_end_date))
        .order(version_downloads::date)
        .load(&*conn)?
        .into_iter()
        .map(VersionDownload::into)
        .collect();

    #[derive(Serialize)]
    struct R {
        version_downloads: Vec<EncodableVersionDownload>,
    }
    Ok(req.json(&R {
        version_downloads: downloads,
    }))
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

#![cfg_attr(rustc, feature(rustc_private))]
#![cfg_attr(rustdoc, feature(rustdoc))]

#[cfg(rustdoc)]
extern crate rustdoc as this;

#[cfg(rustc)]
extern crate rustc_driver as this;

fn main() {
    this::main()
}
<commit_msg>Remove src/driver<commit_after><|endoftext|>


<commit_before>//! A screen as reported by the compositor.
//!
//! Note that there isn't a one-to-one mapping between number of outputs,
//! screens, and the outputs as reported by Way Cooler.

use std::default::Default;

use rlua::{self, AnyUserData, Lua, MetaMethod, Table, ToLua, UserData,
           UserDataMethods, Value};
use wlroots::{Area, Origin, Size};

use common::{class::{self, Class, ClassBuilder},
             signal::emit_object_signal,
             object::{self, Object},
             property::Property};
use wayland_obj::Output;

pub const SCREENS_HANDLE: &'static str = "__screens";

pub type Screen<'lua> = Object<'lua, ScreenState>;

#[derive(Clone)]
pub struct ScreenState {
    // Is this screen still valid and may be used
    pub valid: bool,
    // Screen geometry
    pub geometry: Area,
    // Screen workarea
    pub workarea: Area,
    // The screen outputs information
    pub outputs: Vec<Output>,
    // Some XID identifying this screen
    pub xid: u32
}

unsafe impl Send for ScreenState {}

impl PartialEq for ScreenState {
    fn eq(&self, other: &ScreenState) -> bool {
        self.valid == other.valid &&
            self.geometry == other.geometry &&
            self.workarea == other.workarea &&
            self.xid == other.xid &&
            self.outputs == other.outputs
    }
}

impl Eq for ScreenState {}

impl Default for ScreenState {
    fn default() -> Self {
        ScreenState { valid: true,
                      geometry: Area::default(),
                      workarea: Area::default(),
                      outputs: vec![],
                      xid: 0 }
    }
}

impl UserData for ScreenState {
    fn add_methods(methods: &mut UserDataMethods<Self>) {
        object::default_add_methods(methods);
        methods.add_meta_function(MetaMethod::Index, index);
    }
}

impl<'lua> Screen<'lua> {
    pub fn new(lua: &Lua) -> rlua::Result<Screen> {
        let class = class::class_setup(lua, "screen")?;
        Ok(Screen::allocate(lua, class)?.build())
    }

    pub fn init_screens(&mut self,
                    output: Output,
                    outputs: Vec<Output>)
                    -> rlua::Result<()> {
        let mut state = self.state_mut()?;
        let (width, height) = output.resolution();
        let resolution = Size { width, height };
        state.outputs = outputs;
        state.geometry = state.geometry.with_size(resolution);
        state.workarea = state.workarea.with_size(resolution);
        Ok(())
    }

    pub fn set_geometry(&mut self, lua: &Lua, geometry: Area)
                        -> rlua::Result<()> {
        if self.state()?.geometry != geometry {
            let geometry = self.state()?.geometry;
            let old_area = lua.create_table()?;
            old_area.set("x", geometry.origin.x)?;
            old_area.set("y", geometry.origin.y)?;
            old_area.set("width", geometry.size.width)?;
            old_area.set("height", geometry.size.height)?;
            self.state_mut()?.geometry = geometry;
            emit_object_signal(lua, self.clone().into(), "property::geometry".into(), old_area)?;
        }
        Ok(())
    }

    pub fn set_workarea(&mut self, lua: &Lua, geometry: Area)
                    -> rlua::Result<()> {
        if self.state()?.workarea != geometry {
            let geometry = self.state()?.geometry;
            let old_area = lua.create_table()?;
            old_area.set("x", geometry.origin.x)?;
            old_area.set("y", geometry.origin.y)?;
            old_area.set("width", geometry.size.width)?;
            old_area.set("height", geometry.size.height)?;
            self.state_mut()?.workarea = geometry;
            emit_object_signal(lua, self.clone().into(), "property::workarea".into(), old_area)?;
        }
        Ok(())
    }

    pub fn get_geometry(&self, lua: &'lua Lua) -> rlua::Result<Table<'lua>> {
        let state = self.state()?;
        let Origin { x, y } = state.geometry.origin;
        let Size { width, height } = state.geometry.size;
        let table = lua.create_table()?;
        table.set("x", x)?;
        table.set("y", y)?;
        table.set("width", width)?;
        table.set("height", height)?;
        Ok(table)
    }

    pub fn get_workarea(&self, lua: &'lua Lua) -> rlua::Result<Table<'lua>> {
        let state = self.state()?;
        let Origin { x, y } = state.workarea.origin;
        let Size { width, height } = state.workarea.size;
        let table = lua.create_table()?;
        table.set("x", x)?;
        table.set("y", y)?;
        table.set("width", width)?;
        table.set("height", height)?;
        Ok(table)
    }
}

/// Adds a screen to the list of screens.
pub fn add_screen(lua: &Lua, screen: Screen) -> rlua::Result<()> {
    let mut screens = lua.named_registry_value::<Vec<AnyUserData>>(SCREENS_HANDLE)?;
    screens.push(screen.into());
    lua.set_named_registry_value(SCREENS_HANDLE, screens.to_lua(lua)?)?;
    Ok(())
}

/// Find a screen based on the output.
pub fn get_screen(lua: &Lua, output: Output) -> rlua::Result<Screen> {
    lua.named_registry_value::<Vec<AnyUserData>>(SCREENS_HANDLE)?
        .into_iter()
        .map(|obj| Screen::cast(obj.into()).unwrap())
        // TODO Can there be multiple screens the output is associated with?
        // Will need to handle that case
        .find(|screen| {
            let state = screen.state().expect("Could not get screen state");
            state.outputs.iter().any(|cur_output| *cur_output == output)
        })
        .ok_or(rlua::Error::RuntimeError(format!("No screen with output {:?}", output)))
}

pub fn init<'lua>(lua: &'lua Lua) -> rlua::Result<Class<ScreenState>> {
    let builder = Class::builder(lua, "screen", None)?;
    let res = property_setup(lua, method_setup(lua, builder)?)?.save_class("screen")?
                                                               .build()?;
    let screens: &mut Vec<Screen> = &mut vec![];
    // TODO Get the list of outputs from Way Cooler
    //for output in server.outputs.iter() {
    //    let mut screen = Screen::new(lua)?;
    //    screen.init_screens(output.clone(), vec![output.clone()])?;
    //    // TODO Move to Screen impl like the others
    //    screens.push(screen);
    //}

    // If no screens exist, fake one.
    if screens.is_empty() {
        let mut screen = Screen::new(lua)?;
        {
            let mut obj = screen.state_mut()?;
            obj.geometry = Size::new(1024, 768).into();
            obj.workarea = obj.geometry;
        }
        screens.push(screen);
    }

    lua.set_named_registry_value(SCREENS_HANDLE, screens.clone().to_lua(lua)?)?;
    Ok(res)
}

fn method_setup<'lua>(lua: &'lua Lua,
                      builder: ClassBuilder<'lua, ScreenState>)
                      -> rlua::Result<ClassBuilder<'lua, ScreenState>> {
    // TODO Do properly
    use super::dummy;
    builder.method("connect_signal".into(), lua.create_function(dummy)?)?
           .method("count".into(), lua.create_function(count)?)?
           .method("__call".into(), lua.create_function(iterate_over_screens)?)?
           .method("__index".into(), lua.create_function(index)?)
}

fn property_setup<'lua>(lua: &'lua Lua,
                        builder: ClassBuilder<'lua, ScreenState>)
                        -> rlua::Result<ClassBuilder<'lua, ScreenState>> {
    builder.property(Property::new("geometry".into(),
                                   None,
                                   Some(lua.create_function(get_geometry)?),
                                   None))?
           .property(Property::new("workarea".into(),
                                   None,
                                   Some(lua.create_function(get_workarea)?),
                                   None))
}

fn get_geometry<'lua>(lua: &'lua Lua, screen: Screen<'lua>) -> rlua::Result<Table<'lua>> {
    screen.get_geometry(lua)
}

fn get_workarea<'lua>(lua: &'lua Lua, screen: Screen<'lua>) -> rlua::Result<Table<'lua>> {
    screen.get_workarea(lua)
}

fn count<'lua>(lua: &'lua Lua, _: ()) -> rlua::Result<Value<'lua>> {
    let screens = lua.named_registry_value::<Vec<Screen>>(SCREENS_HANDLE)?;
    Ok(Value::Integer(screens.len() as _))
}

/// Ok this requires some explanation...
/// Lua gives us the previous value in the loop, with the first one being nil
/// since there was nothing there before.
///
/// To ensure we loop over everything, we take the index of that value in our
/// list, increment it by 1 (starting at 0 if it's the start) and then once it
/// falls outside the bounds it will stop by returning nil.
fn iterate_over_screens<'lua>(lua: &'lua Lua,
                              (_, prev): (Value<'lua>, Value<'lua>))
                              -> rlua::Result<Value<'lua>> {
    let mut screens = lua.named_registry_value::<Vec<Screen>>(SCREENS_HANDLE)?;

    let index = match prev {
        Value::Nil => 0,
        Value::UserData(ref object) => {
            if let Ok(screen) = Screen::cast(object.clone().into()) {
                screens.iter()
                       .position(|t| *t.state().unwrap() == *screen.state().unwrap())
                       .unwrap_or(screens.len()) + 1
            } else {
                panic!("Unexpected non-screen table in loop");
            }
        }
        _ => panic!("Unexpected non-screen or nil value in screens loop")
    };
    if index < screens.len() {
        screens.remove(index).to_lua(lua)
    } else {
        Ok(Value::Nil)
    }
}

fn index<'lua>(lua: &'lua Lua,
               (obj, index): (Screen<'lua>, Value<'lua>))
               -> rlua::Result<Value<'lua>> {
    let screens: Vec<Screen> = lua.named_registry_value(SCREENS_HANDLE)?;
    match index {
        Value::String(ref string) => {
            let string = string.to_str()?;
            if string == "primary" {
                // TODO Emit primary changed signal
                if screens.len() > 0 {
                    return screens[0].clone().to_lua(lua)
                }
            }
            for screen in screens.iter() {
                let mut screen_state = screen.state()?;
                for output in &screen_state.outputs {
                    if output.name() == string {
                        return screen.clone().to_lua(lua)
                    }
                }
            }
        }
        // TODO Might need to do Number instead
        Value::Integer(screen_index) => {
            if screen_index < 1 || screen_index as usize > screens.len() {
                return Err(rlua::Error::RuntimeError(format!("invalid screen \
                                                              number: {} (of {} \
                                                              existing)",
                                                             screen_index,
                                                             screens.len())))
            }
            return screens[(screen_index - 1) as usize].clone().to_lua(lua)
        }
        Value::UserData(ref obj) => {
            // If this is a screen, just return it
            if let Ok(screen) = Screen::cast(obj.clone().into()) {
                return screen.to_lua(lua)
            }
        }
        // TODO This checke user data like in luaA_toudata in awesome
        _ => {}
    }
    // TODO checkudata
    let meta = obj.get_metatable()?.expect("screen had no metatable");
    match meta.get(index.clone()) {
        Err(_) | Ok(Value::Nil) => object::default_index(lua, (obj, index)),
        Ok(value) => Ok(value)
    }
}
<commit_msg>Fixed index for screen<commit_after>//! A screen as reported by the compositor.
//!
//! Note that there isn't a one-to-one mapping between number of outputs,
//! screens, and the outputs as reported by Way Cooler.

use std::default::Default;

use rlua::{self, AnyUserData, Lua, MetaMethod, Table, ToLua, UserData,
           UserDataMethods, Value};
use wlroots::{Area, Origin, Size};

use common::{class::{self, Class, ClassBuilder},
             signal::emit_object_signal,
             object::{self, Object},
             property::Property};
use wayland_obj::Output;

pub const SCREENS_HANDLE: &'static str = "__screens";

pub type Screen<'lua> = Object<'lua, ScreenState>;

#[derive(Clone)]
pub struct ScreenState {
    // Is this screen still valid and may be used
    pub valid: bool,
    // Screen geometry
    pub geometry: Area,
    // Screen workarea
    pub workarea: Area,
    // The screen outputs information
    pub outputs: Vec<Output>,
    // Some XID identifying this screen
    pub xid: u32
}

unsafe impl Send for ScreenState {}

impl PartialEq for ScreenState {
    fn eq(&self, other: &ScreenState) -> bool {
        self.valid == other.valid &&
            self.geometry == other.geometry &&
            self.workarea == other.workarea &&
            self.xid == other.xid &&
            self.outputs == other.outputs
    }
}

impl Eq for ScreenState {}

impl Default for ScreenState {
    fn default() -> Self {
        ScreenState { valid: true,
                      geometry: Area::default(),
                      workarea: Area::default(),
                      outputs: vec![],
                      xid: 0 }
    }
}

impl UserData for ScreenState {
    fn add_methods(methods: &mut UserDataMethods<Self>) {
        object::default_add_methods(methods);
        methods.add_meta_function(MetaMethod::Index, index);
    }
}

impl<'lua> Screen<'lua> {
    pub fn new(lua: &Lua) -> rlua::Result<Screen> {
        let class = class::class_setup(lua, "screen")?;
        Ok(Screen::allocate(lua, class)?.build())
    }

    pub fn init_screens(&mut self,
                    output: Output,
                    outputs: Vec<Output>)
                    -> rlua::Result<()> {
        let mut state = self.state_mut()?;
        let (width, height) = output.resolution();
        let resolution = Size { width, height };
        state.outputs = outputs;
        state.geometry = state.geometry.with_size(resolution);
        state.workarea = state.workarea.with_size(resolution);
        Ok(())
    }

    pub fn set_geometry(&mut self, lua: &Lua, geometry: Area)
                        -> rlua::Result<()> {
        if self.state()?.geometry != geometry {
            let geometry = self.state()?.geometry;
            let old_area = lua.create_table()?;
            old_area.set("x", geometry.origin.x)?;
            old_area.set("y", geometry.origin.y)?;
            old_area.set("width", geometry.size.width)?;
            old_area.set("height", geometry.size.height)?;
            self.state_mut()?.geometry = geometry;
            emit_object_signal(lua, self.clone().into(), "property::geometry".into(), old_area)?;
        }
        Ok(())
    }

    pub fn set_workarea(&mut self, lua: &Lua, geometry: Area)
                    -> rlua::Result<()> {
        if self.state()?.workarea != geometry {
            let geometry = self.state()?.geometry;
            let old_area = lua.create_table()?;
            old_area.set("x", geometry.origin.x)?;
            old_area.set("y", geometry.origin.y)?;
            old_area.set("width", geometry.size.width)?;
            old_area.set("height", geometry.size.height)?;
            self.state_mut()?.workarea = geometry;
            emit_object_signal(lua, self.clone().into(), "property::workarea".into(), old_area)?;
        }
        Ok(())
    }

    pub fn get_geometry(&self, lua: &'lua Lua) -> rlua::Result<Table<'lua>> {
        let state = self.state()?;
        let Origin { x, y } = state.geometry.origin;
        let Size { width, height } = state.geometry.size;
        let table = lua.create_table()?;
        table.set("x", x)?;
        table.set("y", y)?;
        table.set("width", width)?;
        table.set("height", height)?;
        Ok(table)
    }

    pub fn get_workarea(&self, lua: &'lua Lua) -> rlua::Result<Table<'lua>> {
        let state = self.state()?;
        let Origin { x, y } = state.workarea.origin;
        let Size { width, height } = state.workarea.size;
        let table = lua.create_table()?;
        table.set("x", x)?;
        table.set("y", y)?;
        table.set("width", width)?;
        table.set("height", height)?;
        Ok(table)
    }
}

/// Adds a screen to the list of screens.
pub fn add_screen(lua: &Lua, screen: Screen) -> rlua::Result<()> {
    let mut screens = lua.named_registry_value::<Vec<AnyUserData>>(SCREENS_HANDLE)?;
    screens.push(screen.into());
    lua.set_named_registry_value(SCREENS_HANDLE, screens.to_lua(lua)?)?;
    Ok(())
}

/// Find a screen based on the output.
pub fn get_screen(lua: &Lua, output: Output) -> rlua::Result<Screen> {
    lua.named_registry_value::<Vec<AnyUserData>>(SCREENS_HANDLE)?
        .into_iter()
        .map(|obj| Screen::cast(obj.into()).unwrap())
        // TODO Can there be multiple screens the output is associated with?
        // Will need to handle that case
        .find(|screen| {
            let state = screen.state().expect("Could not get screen state");
            state.outputs.iter().any(|cur_output| *cur_output == output)
        })
        .ok_or(rlua::Error::RuntimeError(format!("No screen with output {:?}", output)))
}

pub fn init<'lua>(lua: &'lua Lua) -> rlua::Result<Class<ScreenState>> {
    let builder = Class::builder(lua, "screen", None)?;
    let res = property_setup(lua, method_setup(lua, builder)?)?.save_class("screen")?
                                                               .build()?;
    let screens: &mut Vec<Screen> = &mut vec![];
    // TODO Get the list of outputs from Way Cooler
    //for output in server.outputs.iter() {
    //    let mut screen = Screen::new(lua)?;
    //    screen.init_screens(output.clone(), vec![output.clone()])?;
    //    // TODO Move to Screen impl like the others
    //    screens.push(screen);
    //}

    // If no screens exist, fake one.
    if screens.is_empty() {
        let mut screen = Screen::new(lua)?;
        {
            let mut obj = screen.state_mut()?;
            obj.geometry = Size::new(1024, 768).into();
            obj.workarea = obj.geometry;
        }
        screens.push(screen);
    }

    lua.set_named_registry_value(SCREENS_HANDLE, screens.clone().to_lua(lua)?)?;
    Ok(res)
}

fn method_setup<'lua>(lua: &'lua Lua,
                      builder: ClassBuilder<'lua, ScreenState>)
                      -> rlua::Result<ClassBuilder<'lua, ScreenState>> {
    // TODO Do properly
    use super::dummy;
    builder.method("connect_signal".into(), lua.create_function(dummy)?)?
           .method("count".into(), lua.create_function(count)?)?
           .method("__call".into(), lua.create_function(iterate_over_screens)?)?
           .method("__index".into(), lua.create_function(index)?)
}

fn property_setup<'lua>(lua: &'lua Lua,
                        builder: ClassBuilder<'lua, ScreenState>)
                        -> rlua::Result<ClassBuilder<'lua, ScreenState>> {
    builder.property(Property::new("geometry".into(),
                                   None,
                                   Some(lua.create_function(get_geometry)?),
                                   None))?
           .property(Property::new("workarea".into(),
                                   None,
                                   Some(lua.create_function(get_workarea)?),
                                   None))
}

fn get_geometry<'lua>(lua: &'lua Lua, screen: Screen<'lua>) -> rlua::Result<Table<'lua>> {
    screen.get_geometry(lua)
}

fn get_workarea<'lua>(lua: &'lua Lua, screen: Screen<'lua>) -> rlua::Result<Table<'lua>> {
    screen.get_workarea(lua)
}

fn count<'lua>(lua: &'lua Lua, _: ()) -> rlua::Result<Value<'lua>> {
    let screens = lua.named_registry_value::<Vec<Screen>>(SCREENS_HANDLE)?;
    Ok(Value::Integer(screens.len() as _))
}

/// Ok this requires some explanation...
/// Lua gives us the previous value in the loop, with the first one being nil
/// since there was nothing there before.
///
/// To ensure we loop over everything, we take the index of that value in our
/// list, increment it by 1 (starting at 0 if it's the start) and then once it
/// falls outside the bounds it will stop by returning nil.
fn iterate_over_screens<'lua>(lua: &'lua Lua,
                              (_, prev): (Value<'lua>, Value<'lua>))
                              -> rlua::Result<Value<'lua>> {
    let mut screens = lua.named_registry_value::<Vec<Screen>>(SCREENS_HANDLE)?;

    let index = match prev {
        Value::Nil => 0,
        Value::UserData(ref object) => {
            if let Ok(screen) = Screen::cast(object.clone().into()) {
                screens.iter()
                       .position(|t| *t.state().unwrap() == *screen.state().unwrap())
                       .unwrap_or(screens.len()) + 1
            } else {
                panic!("Unexpected non-screen table in loop");
            }
        }
        _ => panic!("Unexpected non-screen or nil value in screens loop")
    };
    if index < screens.len() {
        screens.remove(index).to_lua(lua)
    } else {
        Ok(Value::Nil)
    }
}

fn index<'lua>(lua: &'lua Lua,
               (obj, index): (AnyUserData<'lua>, Value<'lua>))
               -> rlua::Result<Value<'lua>> {
    let screens: Vec<Screen> = lua.named_registry_value(SCREENS_HANDLE)?;
    match index {
        Value::String(ref string) => {
            let string = string.to_str()?;
            if string == "primary" {
                // TODO Emit primary changed signal
                if screens.len() > 0 {
                    return screens[0].clone().to_lua(lua)
                }
            }
            for screen in screens.iter() {
                let mut screen_state = screen.state()?;
                for output in &screen_state.outputs {
                    if output.name() == string {
                        return screen.clone().to_lua(lua)
                    }
                }
            }
        }
        // TODO Might need to do Number instead
        Value::Integer(screen_index) => {
            if screen_index < 1 || screen_index as usize > screens.len() {
                return Err(rlua::Error::RuntimeError(format!("invalid screen \
                                                              number: {} (of {} \
                                                              existing)",
                                                             screen_index,
                                                             screens.len())))
            }
            return screens[(screen_index - 1) as usize].clone().to_lua(lua)
        }
        Value::UserData(ref obj) => {
            // If this is a screen, just return it
            if let Ok(screen) = Screen::cast(obj.clone().into()) {
                return screen.to_lua(lua)
            }
        }
        // TODO This checke user data like in luaA_toudata in awesome
        _ => {}
    }
    // TODO checkudata
    let table: Table = obj.get_user_value()?;
    let meta = table.get_metatable().expect("screen had no metatable");
    match meta.get(index.clone()) {
        Err(_) | Ok(Value::Nil) => object::default_index(lua, (Screen::cast(obj)?, index)),
        Ok(value) => Ok(value)
    }
}
<|endoftext|>


<commit_before>#[link(name = "rusp",
       vers = "0.1",
       author = "Brendan Zabarauskas",
       url = "https://github.com/bjz/rusp")];

#[comment = "A minimal Lisp dialect for Rust."];
#[crate_type = "lib"];

use std::hashmap::*;

///
/// Symbol identifier
///
#[deriving(Eq, Clone, IterBytes)]
pub struct Ident(~str);

///
/// Holds a typed value from the environment
///
#[deriving(Eq, Clone)]
pub enum Value {
    String(~str),
    Bool(bool),
    Int(int),
    Float(float),
}

///
/// Primitive language expressions
///
#[deriving(Eq, Clone)]
pub enum Expr {
    ///
    /// Symbol reference
    ///
    /// ~~~
    /// <ident>
    /// ~~~
    ///
    Symbol(Ident),
    ///
    /// Constant literal
    ///
    /// ~~~
    /// <val>
    /// ~~~
    ///
    Literal(Value),
    ///
    /// Quotation
    ///
    /// ~~~
    /// (quote <expr>)
    /// ~~~
    ///
    Quote(@Expr),
    ///
    /// Conditional expression
    ///
    /// ~~~
    /// (if <test> <conseq> <alt>)
    /// ~~~
    ///
    If(@Expr, @Expr, @Expr),
    ///
    /// Anonymous function
    ///
    /// ~~~
    /// (|<ident>*| <expr>)
    /// ~~~
    ///
    Lambda(~[Ident], @Expr),
    ///
    /// Symbol definition
    ///
    /// ~~~
    /// (def <ident> <expr>)
    /// ~~~
    ///
    Define(Ident, @Expr),
    ///
    /// Procedure call
    ///
    /// ~~~
    /// (<ident> <expr>+)
    /// ~~~
    ///
    Call(Ident, ~[Expr]),

#[deriving(Eq)]
pub struct Env {
    values: HashMap<Ident, Value>,
    outer: Option<@mut Env>,
}

impl Env {
    /// Initializes an empty environment
    pub fn empty() -> Env {
        Env { values: HashMap::new(), outer: None }
    }

    /// Initializes a new environment
    pub fn new(values: &[(Ident, Value)], outer: Option<@mut Env>) -> @mut Env {
        let env = @mut Env {
            values: HashMap::new(),
            outer: outer,
        };
        for values.each |&(id, val)| {
            env.insert(id, val);
        }
        env
    }

    /// Inserts a new identifier/value pair into the environment
    pub fn insert(&mut self, ident: Ident, val: Value) -> bool {
        self.values.insert(ident, val)
    }

    /// Attempts to find a value corresponding to the supplied identifier
    pub fn find(&self, ident: &Ident) -> Option<Value> {
        match self.values.find(ident) {
            Some(val) => Some(val.clone()),
            None => self.outer.chain(|env| env.find(ident)),
        }
    }
}

///
/// A position in a source string
///
pub struct Position {
    line: uint,
    col: uint,
}

pub enum ParseResult {
    Success(Expr),
    Failure {
        description: ~str,
        position: Position,
    },
}

///
/// Performs a recursive decent parse of the source string.
///
pub fn parse(src: &str) -> ParseResult {
    for str::each_char(src) |_| {}
    fail!()
}

impl Expr {
    ///
    /// Evaluates an expression tree
    ///
    pub fn eval(&self, env: &Env) -> Value {
        match *self {
            Symbol(ref id) => env.find(id).expect(
                fmt!("The value of %? was not defined in this environment", id)
            ),
            Literal(ref val) => val.clone(),
            Quote(_) => fail!(),
            If(test, conseq, alt) => {
                match test.eval(env) {
                    Bool(val) => {
                        if val { conseq.eval(env) }
                        else   { alt.eval(env)    }
                    }
                    expr => {
                        fail!("expected Boolean expression, found: %?", expr);
                    }
                }
            }
            Lambda(_,_) => fail!(),
            Define(_,_) => fail!(),
            Call(_,_) => fail!(),
        }
    }
}

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

    #[test]
    fn test_env() {
        let outer = Env::new([
            (Ident(~"a"), Int(0)),
            (Ident(~"b"), Float(1.0)),
            (Ident(~"c"), String(~"hi")),
        ], None);

        let inner = Env::new([
            (Ident(~"a"), Int(3)),
            (Ident(~"b"), Int(4)),
        ], Some(outer));

        assert_eq!(outer.find(&Ident(~"a")), Some(Int(0)));
        assert_eq!(outer.find(&Ident(~"b")), Some(Float(1.0)));
        assert_eq!(outer.find(&Ident(~"c")), Some(String(~"hi")));
        assert_eq!(inner.find(&Ident(~"a")), Some(Int(3)));
        assert_eq!(inner.find(&Ident(~"b")), Some(Int(4)));
        assert_eq!(inner.find(&Ident(~"c")), Some(String(~"hi")));
    }

    #[test]
    fn test_eval_if() {
        fn not(test: bool) -> bool {
            match If(
                @Literal(Bool(test)),
                @Literal(Bool(false)),
                @Literal(Bool(true))
            ).eval(&Env::empty()) {
                Bool(b) => b,
                _ => fail!("Should not fail."),
            }
        }

        assert_eq!(not(true), false);
        assert_eq!(not(false), true);
    }
}<commit_msg>Filling in the eval function...<commit_after>#[link(name = "rusp",
       vers = "0.1",
       author = "Brendan Zabarauskas",
       url = "https://github.com/bjz/rusp")];

#[comment = "A minimal Lisp dialect for Rust."];
#[crate_type = "lib"];

// Inspired by Peter Norvig's [Lis.py](http://norvig.com/lispy.html)

use std::hashmap::*;

///
/// Symbol identifier
///
#[deriving(Eq, Clone, IterBytes)]
pub struct Ident(~str);

impl ToStr for Ident {
    fn to_str(&self) -> ~str {
        (**self).clone()
    }
}

///
/// Holds a typed value from the environment
///
#[deriving(Eq, Clone)]
pub enum Value {
    Empty,
    Boolean(bool),
    Integer(int),
    Float(float),
    String(~str),
    Quote(@Expr),
    Lambda(~[Ident], @Expr, @mut Env),
}

///
/// Primitive language expressions
///
#[deriving(Eq, Clone)]
pub enum Expr {
    ///
    /// Symbol reference
    ///
    /// ~~~
    /// <ident>
    /// ~~~
    ///
    Symbol(Ident),
    ///
    /// Constant literal
    ///
    /// ~~~
    /// <val>
    /// ~~~
    ///
    Literal(Value),
    ///
    /// Quoted expression
    ///
    /// ~~~
    /// (quote <expr>)
    /// ~~~
    ///
    QuoteExpr(@Expr),
    ///
    /// Conditional expression
    ///
    /// ~~~
    /// (if <test> <conseq> <alt>)
    /// ~~~
    ///
    IfExpr(@Expr, @Expr, @Expr),
    ///
    /// Anonymous function
    ///
    /// ~~~
    /// (|<ident>*| <expr>)
    /// ~~~
    ///
    LambdaExpr(~[Ident], @Expr),
    ///
    /// Symbol definition
    ///
    /// ~~~
    /// (let <ident> <expr>)
    /// ~~~
    ///
    LetExpr(Ident, @Expr),
    ///
    /// Procedure call
    ///
    /// ~~~
    /// (<expr> <expr>+)
    /// ~~~
    ///
    CallExpr(@Expr, ~[Expr]),
}

#[deriving(Eq)]
pub struct Env {
    values: HashMap<Ident, Value>,
    outer: Option<@mut Env>,
}

impl Env {
    /// Initializes an empty environment
    pub fn empty() -> @mut Env {
        @mut Env { values: HashMap::new(), outer: None }
    }

    /// Initializes a new environment with the specified values
    pub fn new(values: &[(Ident, Value)], outer: Option<@mut Env>) -> @mut Env {
        let env = @mut Env {
            values: HashMap::new(),
            outer: outer,
        };
        for values.each |&(id, val)| {
            env.define(id, val);
        }
        env
    }

    /// Defines a new identifier/value pair
    pub fn define(&mut self, ident: Ident, val: Value) -> bool {
        self.values.insert(ident, val)
    }

    /// Attempts to find a value corresponding to the supplied identifier
    pub fn find(&self, ident: &Ident) -> Option<Value> {
        match self.values.find(ident) {
            Some(val) => Some(val.clone()),
            None => self.outer.chain(|env| env.find(ident)),
        }
    }
}

///
/// A position in the source string
///
pub struct Position {
    line: uint,
    col: uint,
}

pub enum ParseResult {
    Success(Expr),
    Failure {
        description: ~str,
        position: Position,
    },
}

///
/// Performs a recursive decent parse of the source string.
///
pub fn parse(src: &str) -> ParseResult {
    for str::each_char(src) |_| {}
    fail!()
}

pub type EvalResult = Result<Value, ~str>;

impl Expr {
    ///
    /// Evaluates an expression tree in the supplied environment
    ///
    pub fn eval(&self, env: @mut Env) -> EvalResult {
        match *self {
            Symbol(ref id) =>{
                match env.find(id) {
                    Some(val) => Ok(val),
                    None => Err(fmt!("The value of `%s` was not defined in this environment", id.to_str())),
                }
            }
            Literal(ref val) => {
                Ok(val.clone())
            }
            QuoteExpr(expr) => {
                Ok(Quote(expr))
            }
            IfExpr(test, conseq, alt) => {
                do test.eval(env).chain |val| {
                    match val {
                        Boolean(true) => conseq.eval(env),
                        Boolean(false) => alt.eval(env),
                        _ => Err(fmt!("expected Boolean value, found: %?", val)),
                    }
                }
            }
            LambdaExpr(ref ids, expr) => {
                Ok(Lambda(ids.clone(), expr, Env::new([], Some(env))))
            }
            LetExpr(ref id, expr) => {
                do expr.eval(env).chain |val| {
                    if env.define(id.clone(), val) {
                        Ok(Empty)
                    } else {
                        Err(fmt!("`%s` was already defined in this environment.", id.to_str()))
                    }
                }
            }
            CallExpr(_,_) => fail!(),
        }
    }
}

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

    #[test]
    fn test_env() {
        let outer = Env::new([
            (Ident(~"a"), Integer(0)),
            (Ident(~"b"), Float(1.0)),
            (Ident(~"c"), String(~"hi")),
        ], None);

        let inner = Env::new([
            (Ident(~"a"), Integer(3)),
            (Ident(~"b"), Integer(4)),
        ], Some(outer));

        assert_eq!(outer.find(&Ident(~"a")), Some(Integer(0)));
        assert_eq!(outer.find(&Ident(~"b")), Some(Float(1.0)));
        assert_eq!(outer.find(&Ident(~"c")), Some(String(~"hi")));
        assert_eq!(inner.find(&Ident(~"a")), Some(Integer(3)));
        assert_eq!(inner.find(&Ident(~"b")), Some(Integer(4)));
        assert_eq!(inner.find(&Ident(~"c")), Some(String(~"hi")));
    }

    #[test]
    fn test_eval_symbol() {
        let env = Env::new([
            (Ident(~"a"), Integer(0)),
            (Ident(~"b"), Float(1.0)),
            (Ident(~"c"), String(~"hi")),
        ], None);

        assert_eq!(Symbol(Ident(~"a")).eval(env).get(), Integer(0));
        assert_eq!(Symbol(Ident(~"b")).eval(env).get(), Float(1.0));
        assert_eq!(Symbol(Ident(~"c")).eval(env).get(), String(~"hi"));
        assert!(Symbol(Ident(~"d")).eval(env).is_err());
    }

    #[test]
    fn test_eval_literal() {
        assert_eq!(Literal(Empty).eval(Env::empty()).get(), Empty);
        assert_eq!(Literal(Integer(1)).eval(Env::empty()).get(), Integer(1));
        assert_eq!(Literal(Float(1.0)).eval(Env::empty()).get(), Float(1.0));
        assert_eq!(Literal(String(~"hi")).eval(Env::empty()).get(), String(~"hi"));
        assert_eq!(Literal(Quote(@Literal(Empty))).eval(Env::empty()).get(),
                   Quote(@Literal(Empty)));
    }

    #[test]
    fn test_eval_quote_expr() {
        assert_eq!(QuoteExpr(@Literal(String(~"hi"))).eval(Env::empty()).get(),
                   Quote(@Literal(String(~"hi"))));
    }

    #[test]
    fn test_eval_if_expr() {
        fn not(test: Value) -> EvalResult {
            IfExpr(
                @Literal(test),
                @Literal(Boolean(false)),
                @Literal(Boolean(true))
            ).eval(Env::empty())
        }

        assert_eq!(not(Boolean(true)).get(), Boolean(false));
        assert_eq!(not(Boolean(false)).get(), Boolean(true));
        assert!(not(String(~"hi")).is_err());
    }

    #[test]
    fn test_eval_lambda_expr() {

    }

    #[test]
    fn test_eval_let_expr() {
        let env = Env::empty();
        assert!(LetExpr(Ident(~"a"), @Literal(Integer(0))).eval(env).is_ok());
        assert!(LetExpr(Ident(~"b"), @Literal(Float(1.0))).eval(env).is_ok());
        assert!(LetExpr(Ident(~"c"), @Literal(String(~"hi"))).eval(env).is_ok());

        assert_eq!(env.find(&Ident(~"a")), Some(Integer(0)));
        assert_eq!(env.find(&Ident(~"b")), Some(Float(1.0)));
        assert_eq!(env.find(&Ident(~"c")), Some(String(~"hi")));

        assert!(LetExpr(Ident(~"c"), @Literal(Empty)).eval(env).is_err());
    }

    #[test]
    fn test_eval_call_expr() {

    }
}<|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/. */

#![doc = "Rust wrappers around the raw JS apis"]

use libc::types::os::arch::c95::{size_t, c_uint};
use libc::c_char;
use std::cmp;
use std::rc;
use std::rt::Runtime;
use jsapi::*;
use jsval::{JSVal, NullValue};
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use ERR;
use std::str::raw::from_c_str;
use green::task::GreenTask;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = rc::Rc<rt_rsrc>;

pub struct rt_rsrc {
    pub ptr : *mut JSRuntime,
}

impl Drop for rt_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *mut JSRuntime) -> rt {
    return rc::Rc::new(rt_rsrc {
        ptr: p
    })
}

pub trait RtUtils {
    fn cx(&self) -> rc::Rc<Cx>;
}

impl RtUtils for rc::Rc<rt_rsrc> {
    fn cx(&self) -> rc::Rc<Cx> {
        unsafe {
            new_context(JS_NewContext(self.deref().ptr,
                                      default_stacksize as size_t), self.clone())
        }
    }
}

extern fn gc_callback(rt: *mut JSRuntime, _status: JSGCStatus) {
    use std::rt::local::Local;
    use std::rt::task::Task;
    unsafe {
        let mut task = Local::borrow(None::<Task>);
        let green_task: Box<GreenTask> = task.maybe_take_runtime().unwrap();
        let (start, end) = green_task.stack_bounds();
        JS_SetNativeStackBounds(rt, cmp::min(start, end), cmp::max(start, end));
        task.put_runtime(green_task);
    }
}

pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        JS_SetGCCallback(runtime, Some(gc_callback));
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    pub ptr: *mut JSContext,
    pub rt: rt,
}

#[unsafe_destructor]
impl Drop for Cx {
    fn drop(&mut self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *mut JSContext, rt: rt) -> rc::Rc<Cx> {
    return rc::Rc::new(Cx {
        ptr: ptr,
        rt: rt,
    })
}

impl Cx {
    pub fn set_default_options_and_version(&self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE);
        self.set_version(JSVERSION_LATEST);
    }

    pub fn set_options(&self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    pub fn set_version(&self, v: JSVersion) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    pub fn set_logging_error_reporter(&self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportError));
        }
    }

    pub fn set_error_reporter(&self, reportfn: unsafe extern "C" fn(*mut JSContext, *c_char, *mut JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportfn));
        }
    }

    pub fn evaluate_script(&self, glob: *mut JSObject, script: String, filename: String, line_num: uint)
                    -> Result<(),()> {
        let script_utf16 = script.to_utf16();
        filename.to_c_str().with_ref(|filename_cstr| {
            let mut rval: JSVal = NullValue();
            debug!("Evaluating script from {:s} with content {}", filename, script);
            // SpiderMonkey does not approve of null pointers.
            let (ptr, len) = if script_utf16.len() == 0 {
                static empty: &'static [u16] = &[];
                (empty.as_ptr(), 0)
            } else {
                (script_utf16.as_ptr(), script_utf16.len() as c_uint)
            };
            assert!(ptr.is_not_null());
            unsafe {
                if ERR == JS_EvaluateUCScript(self.ptr, glob, ptr, len,
                                              filename_cstr, line_num as c_uint,
                                              &mut rval) {
                    debug!("...err!");
                    Err(())
                } else {
                    // we could return the script result but then we'd have
                    // to root it and so forth and, really, who cares?
                    debug!("...ok!");
                    Ok(())
                }
            }
        })
    }
}

pub extern fn reportError(_cx: *mut JSContext, msg: *c_char, report: *mut JSErrorReport) {
    unsafe {
        let fnptr = (*report).filename;
        let fname = if fnptr.is_not_null() {from_c_str(fnptr)} else {"none".to_string()};
        let lineno = (*report).lineno;
        let msg = from_c_str(msg);
        error!("Error at {:s}:{}: {:s}\n", fname, lineno, msg);
    }
}

pub fn with_compartment<R>(cx: *mut JSContext, object: *mut JSObject, cb: || -> R) -> R {
    unsafe {
        let call = JS_EnterCrossCompartmentCall(cx, object);
        let result = cb();
        JS_LeaveCrossCompartmentCall(call);
        result
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::RtUtils;

    #[test]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.deref().set_default_options_and_version();
        cx.deref().set_logging_error_reporter();
    }

}
<commit_msg>Convert a doc-comment to "sugared" form<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/. */

//! Rust wrappers around the raw JS apis

use libc::types::os::arch::c95::{size_t, c_uint};
use libc::c_char;
use std::cmp;
use std::rc;
use std::rt::Runtime;
use jsapi::*;
use jsval::{JSVal, NullValue};
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use ERR;
use std::str::raw::from_c_str;
use green::task::GreenTask;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = rc::Rc<rt_rsrc>;

pub struct rt_rsrc {
    pub ptr : *mut JSRuntime,
}

impl Drop for rt_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *mut JSRuntime) -> rt {
    return rc::Rc::new(rt_rsrc {
        ptr: p
    })
}

pub trait RtUtils {
    fn cx(&self) -> rc::Rc<Cx>;
}

impl RtUtils for rc::Rc<rt_rsrc> {
    fn cx(&self) -> rc::Rc<Cx> {
        unsafe {
            new_context(JS_NewContext(self.deref().ptr,
                                      default_stacksize as size_t), self.clone())
        }
    }
}

extern fn gc_callback(rt: *mut JSRuntime, _status: JSGCStatus) {
    use std::rt::local::Local;
    use std::rt::task::Task;
    unsafe {
        let mut task = Local::borrow(None::<Task>);
        let green_task: Box<GreenTask> = task.maybe_take_runtime().unwrap();
        let (start, end) = green_task.stack_bounds();
        JS_SetNativeStackBounds(rt, cmp::min(start, end), cmp::max(start, end));
        task.put_runtime(green_task);
    }
}

pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        JS_SetGCCallback(runtime, Some(gc_callback));
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    pub ptr: *mut JSContext,
    pub rt: rt,
}

#[unsafe_destructor]
impl Drop for Cx {
    fn drop(&mut self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *mut JSContext, rt: rt) -> rc::Rc<Cx> {
    return rc::Rc::new(Cx {
        ptr: ptr,
        rt: rt,
    })
}

impl Cx {
    pub fn set_default_options_and_version(&self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE);
        self.set_version(JSVERSION_LATEST);
    }

    pub fn set_options(&self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    pub fn set_version(&self, v: JSVersion) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    pub fn set_logging_error_reporter(&self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportError));
        }
    }

    pub fn set_error_reporter(&self, reportfn: unsafe extern "C" fn(*mut JSContext, *c_char, *mut JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportfn));
        }
    }

    pub fn evaluate_script(&self, glob: *mut JSObject, script: String, filename: String, line_num: uint)
                    -> Result<(),()> {
        let script_utf16 = script.to_utf16();
        filename.to_c_str().with_ref(|filename_cstr| {
            let mut rval: JSVal = NullValue();
            debug!("Evaluating script from {:s} with content {}", filename, script);
            // SpiderMonkey does not approve of null pointers.
            let (ptr, len) = if script_utf16.len() == 0 {
                static empty: &'static [u16] = &[];
                (empty.as_ptr(), 0)
            } else {
                (script_utf16.as_ptr(), script_utf16.len() as c_uint)
            };
            assert!(ptr.is_not_null());
            unsafe {
                if ERR == JS_EvaluateUCScript(self.ptr, glob, ptr, len,
                                              filename_cstr, line_num as c_uint,
                                              &mut rval) {
                    debug!("...err!");
                    Err(())
                } else {
                    // we could return the script result but then we'd have
                    // to root it and so forth and, really, who cares?
                    debug!("...ok!");
                    Ok(())
                }
            }
        })
    }
}

pub extern fn reportError(_cx: *mut JSContext, msg: *c_char, report: *mut JSErrorReport) {
    unsafe {
        let fnptr = (*report).filename;
        let fname = if fnptr.is_not_null() {from_c_str(fnptr)} else {"none".to_string()};
        let lineno = (*report).lineno;
        let msg = from_c_str(msg);
        error!("Error at {:s}:{}: {:s}\n", fname, lineno, msg);
    }
}

pub fn with_compartment<R>(cx: *mut JSContext, object: *mut JSObject, cb: || -> R) -> R {
    unsafe {
        let call = JS_EnterCrossCompartmentCall(cx, object);
        let result = cb();
        JS_LeaveCrossCompartmentCall(call);
        result
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::RtUtils;

    #[test]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.deref().set_default_options_and_version();
        cx.deref().set_logging_error_reporter();
    }

}
<|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/. */

//! Rust wrappers around the raw JS apis

use libc::types::os::arch::c95::{size_t, c_uint};
use libc::c_char;
use std::cmp;
use std::rc;
use std::rt::Runtime;
use jsapi::*;
use jsval::{JSVal, NullValue};
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use ERR;
use std::str::raw::from_c_str;
use green::task::GreenTask;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = rc::Rc<rt_rsrc>;

pub struct rt_rsrc {
    pub ptr : *mut JSRuntime,
}

impl Drop for rt_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *mut JSRuntime) -> rt {
    return rc::Rc::new(rt_rsrc {
        ptr: p
    })
}

pub trait RtUtils {
    fn cx(&self) -> rc::Rc<Cx>;
}

impl RtUtils for rc::Rc<rt_rsrc> {
    fn cx(&self) -> rc::Rc<Cx> {
        unsafe {
            new_context(JS_NewContext(self.deref().ptr,
                                      default_stacksize as size_t), self.clone())
        }
    }
}

extern fn gc_callback(rt: *mut JSRuntime, _status: JSGCStatus) {
    use std::rt::local::Local;
    use std::rt::task::Task;
    unsafe {
        let mut task = Local::borrow(None::<Task>);
        let green_task: Box<GreenTask> = task.maybe_take_runtime().unwrap();
        let (start, end) = green_task.stack_bounds();
        JS_SetNativeStackBounds(rt, cmp::min(start, end), cmp::max(start, end));
        task.put_runtime(green_task);
    }
}

pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        JS_SetGCCallback(runtime, Some(gc_callback));
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    pub ptr: *mut JSContext,
    pub rt: rt,
}

#[unsafe_destructor]
impl Drop for Cx {
    fn drop(&mut self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *mut JSContext, rt: rt) -> rc::Rc<Cx> {
    return rc::Rc::new(Cx {
        ptr: ptr,
        rt: rt,
    })
}

impl Cx {
    pub fn set_default_options_and_version(&self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE);
        self.set_version(JSVERSION_LATEST);
    }

    pub fn set_options(&self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    pub fn set_version(&self, v: JSVersion) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    pub fn set_logging_error_reporter(&self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportError));
        }
    }

    pub fn set_error_reporter(&self, reportfn: unsafe extern "C" fn(*mut JSContext, *const c_char, *mut JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportfn));
        }
    }

    pub fn evaluate_script(&self, glob: *mut JSObject, script: String, filename: String, line_num: uint)
                    -> Result<(),()> {
        let script_utf16: Vec<u16> = script.as_slice().utf16_units().collect();
        let filename_cstr = filename.to_c_str();
        let mut rval: JSVal = NullValue();
        debug!("Evaluating script from {:s} with content {}", filename, script);
        // SpiderMonkey does not approve of null pointers.
        let (ptr, len) = if script_utf16.len() == 0 {
            static empty: &'static [u16] = &[];
            (empty.as_ptr(), 0)
        } else {
            (script_utf16.as_ptr(), script_utf16.len() as c_uint)
        };
        assert!(ptr.is_not_null());
        unsafe {
            if ERR == JS_EvaluateUCScript(self.ptr, glob, ptr, len,
                                          filename_cstr.as_ptr(), line_num as c_uint,
                                          &mut rval) {
                debug!("...err!");
                Err(())
            } else {
                // we could return the script result but then we'd have
                // to root it and so forth and, really, who cares?
                debug!("...ok!");
                Ok(())
            }
        }
    }
}

pub extern fn reportError(_cx: *mut JSContext, msg: *const c_char, report: *mut JSErrorReport) {
    unsafe {
        let fnptr = (*report).filename;
        let fname = if fnptr.is_not_null() {from_c_str(fnptr)} else {"none".to_string()};
        let lineno = (*report).lineno;
        let msg = from_c_str(msg);
        error!("Error at {:s}:{}: {:s}\n", fname, lineno, msg);
    }
}

pub fn with_compartment<R>(cx: *mut JSContext, object: *mut JSObject, cb: || -> R) -> R {
    unsafe {
        let call = JS_EnterCrossCompartmentCall(cx, object);
        let result = cb();
        JS_LeaveCrossCompartmentCall(call);
        result
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::RtUtils;

    #[test]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.deref().set_default_options_and_version();
        cx.deref().set_logging_error_reporter();
    }

}
<commit_msg>Upgrade Rust.<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/. */

//! Rust wrappers around the raw JS apis

use libc::types::os::arch::c95::{size_t, c_uint};
use libc::c_char;
use std::cmp;
use std::rc;
use std::rt::Runtime;
use std::string;
use jsapi::*;
use jsval::{JSVal, NullValue};
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use ERR;
use green::task::GreenTask;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = rc::Rc<rt_rsrc>;

pub struct rt_rsrc {
    pub ptr : *mut JSRuntime,
}

impl Drop for rt_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *mut JSRuntime) -> rt {
    return rc::Rc::new(rt_rsrc {
        ptr: p
    })
}

pub trait RtUtils {
    fn cx(&self) -> rc::Rc<Cx>;
}

impl RtUtils for rc::Rc<rt_rsrc> {
    fn cx(&self) -> rc::Rc<Cx> {
        unsafe {
            new_context(JS_NewContext(self.deref().ptr,
                                      default_stacksize as size_t), self.clone())
        }
    }
}

extern fn gc_callback(rt: *mut JSRuntime, _status: JSGCStatus) {
    use std::rt::local::Local;
    use std::rt::task::Task;
    unsafe {
        let mut task = Local::borrow(None::<Task>);
        let green_task: Box<GreenTask> = task.maybe_take_runtime().unwrap();
        let (start, end) = green_task.stack_bounds();
        JS_SetNativeStackBounds(rt, cmp::min(start, end), cmp::max(start, end));
        task.put_runtime(green_task);
    }
}

pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        JS_SetGCCallback(runtime, Some(gc_callback));
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    pub ptr: *mut JSContext,
    pub rt: rt,
}

#[unsafe_destructor]
impl Drop for Cx {
    fn drop(&mut self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *mut JSContext, rt: rt) -> rc::Rc<Cx> {
    return rc::Rc::new(Cx {
        ptr: ptr,
        rt: rt,
    })
}

impl Cx {
    pub fn set_default_options_and_version(&self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE);
        self.set_version(JSVERSION_LATEST);
    }

    pub fn set_options(&self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    pub fn set_version(&self, v: JSVersion) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    pub fn set_logging_error_reporter(&self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportError));
        }
    }

    pub fn set_error_reporter(&self, reportfn: unsafe extern "C" fn(*mut JSContext, *const c_char, *mut JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, Some(reportfn));
        }
    }

    pub fn evaluate_script(&self, glob: *mut JSObject, script: String, filename: String, line_num: uint)
                    -> Result<(),()> {
        let script_utf16: Vec<u16> = script.as_slice().utf16_units().collect();
        let filename_cstr = filename.to_c_str();
        let mut rval: JSVal = NullValue();
        debug!("Evaluating script from {:s} with content {}", filename, script);
        // SpiderMonkey does not approve of null pointers.
        let (ptr, len) = if script_utf16.len() == 0 {
            static empty: &'static [u16] = &[];
            (empty.as_ptr(), 0)
        } else {
            (script_utf16.as_ptr(), script_utf16.len() as c_uint)
        };
        assert!(ptr.is_not_null());
        unsafe {
            if ERR == JS_EvaluateUCScript(self.ptr, glob, ptr, len,
                                          filename_cstr.as_ptr(), line_num as c_uint,
                                          &mut rval) {
                debug!("...err!");
                Err(())
            } else {
                // we could return the script result but then we'd have
                // to root it and so forth and, really, who cares?
                debug!("...ok!");
                Ok(())
            }
        }
    }
}

pub extern fn reportError(_cx: *mut JSContext, msg: *const c_char, report: *mut JSErrorReport) {
    unsafe {
        let fnptr = (*report).filename;
        let fname = if fnptr.is_not_null() {string::raw::from_buf(fnptr as *const i8 as *const u8)} else {"none".to_string()};
        let lineno = (*report).lineno;
        let msg = string::raw::from_buf(msg as *const i8 as *const u8);
        error!("Error at {:s}:{}: {:s}\n", fname, lineno, msg);
    }
}

pub fn with_compartment<R>(cx: *mut JSContext, object: *mut JSObject, cb: || -> R) -> R {
    unsafe {
        let call = JS_EnterCrossCompartmentCall(cx, object);
        let result = cb();
        JS_LeaveCrossCompartmentCall(call);
        result
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::RtUtils;

    #[test]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.deref().set_default_options_and_version();
        cx.deref().set_logging_error_reporter();
    }

}
<|endoftext|>


<commit_before>
mod hangeul;

pub fn test_const() {
    assert!(hangeul::hangeul::syllable_start as u32 == 0xac00);
    assert!(hangeul::hangeul::syllable_end as u32 == 0xd7a3);

    assert!(hangeul::hangeul::jamo_initial_start as u32 == 0x1100);
    assert!(hangeul::hangeul::jamo_initial_modern_end as u32 == 0x1112);
}

fn test_jamo() {
    use hangeul::hangeul::Hangeul;
    let input_str = "아희방맣희";
    for c in input_str.chars() {
        let hangeul: hangeul::hangeul::HangeulSyllable = hangeul::hangeul::Hangeul::from_char(c);
        println(format!("{:?}", hangeul));
        println(format!("{}{}{}", hangeul.initial_jamo().unwrap(), hangeul.vowel_jamo().unwrap(), hangeul.final_jamo().unwrap_or(' ')));
    }
}

fn main() {
    use hangeul::hangeul::Hangeul;
    test_const();
    test_jamo();
}
<commit_msg>`println` is removed<commit_after>
mod hangeul;

pub fn test_const() {
    assert!(hangeul::hangeul::syllable_start as u32 == 0xac00);
    assert!(hangeul::hangeul::syllable_end as u32 == 0xd7a3);

    assert!(hangeul::hangeul::jamo_initial_start as u32 == 0x1100);
    assert!(hangeul::hangeul::jamo_initial_modern_end as u32 == 0x1112);
}

fn test_jamo() {
    use hangeul::hangeul::Hangeul;
    let input_str = "아희방맣희";
    for c in input_str.chars() {
        let hangeul: hangeul::hangeul::HangeulSyllable = hangeul::hangeul::Hangeul::from_char(c);
        println!("{:?}", hangeul);
        println!("{}{}{}", hangeul.initial_jamo().unwrap(), hangeul.vowel_jamo().unwrap(), hangeul.final_jamo().unwrap_or(' '));
    }
}

fn main() {
    use hangeul::hangeul::Hangeul;
    test_const();
    test_jamo();
}
<|endoftext|>


<commit_before>use std::cell::UnsafeCell;
use std::sync::mpsc::{Sender, Receiver, RecvError, TryRecvError};
use basetypes::*;
use chess_move::MoveStack;
use tt::*;
use position::Position;

pub struct Parameters {
    id: usize,
    position: Position,
    depth: u8,
    alpha: Value,
    beta: Value,
}

pub enum Command {
    Search(Parameters),
    Stop,
    Exit,
}

pub struct Progress {
    search_id: usize,
    node_count: NodeCount,
}

pub struct Done {
    search_id: usize,
    value: Option<Value>,
}

pub fn run(tt: &TranspositionTable,
           commands: Receiver<Command>,
           reports: Sender<Progress>,
           results: Sender<Done>) {
    thread_local!(
        static MOVE_STACK: UnsafeCell<MoveStack> = UnsafeCell::new(MoveStack::new())
    );
    MOVE_STACK.with(|move_stack| {
        let mut pending_command = None;
        loop {
            let command = pending_command.take()
                                         .unwrap_or(commands.recv()
                                                            .or::<RecvError>(Ok(Command::Exit))
                                                            .unwrap());
            match command {
                Command::Search(mut params) => {
                    let search_id = params.id;
                    let mut node_count = 0;
                    results.send(Done {
                        search_id: search_id,
                        value: search(tt,
                                      &mut params.position,
                                      unsafe { &mut *move_stack.get() },
                                      &mut 0,
                                      &mut |nc| {
                                          node_count += nc;
                                          reports.send(Progress {
                                              search_id: search_id,
                                              node_count: node_count,
                                          });
                                          match commands.try_recv() {
                                              Ok(x) => {
                                                  pending_command = Some(x);
                                                  // *pending_command.borrow_mut() = Some(x);
                                                  Err(TerminatedSearch)
                                              }
                                              Err(_) => Ok(()),
                                          }
                                      },
                                      params.alpha,
                                      params.beta,
                                      params.depth)
                                   .ok(),
                    });
                }
                Command::Stop => continue,
                Command::Exit => break,
            }
        }
    })
}

/// Represents a terminated search condition.
pub struct TerminatedSearch;

pub fn search(tt: &TranspositionTable,
              p: &mut Position,
              moves: &mut MoveStack,
              nc: &mut NodeCount,
              report: &mut FnMut(NodeCount) -> Result<(), TerminatedSearch>,
              mut alpha: Value, // lower bound
              beta: Value, // upper bound
              depth: u8)
              -> Result<Value, TerminatedSearch> {
    assert!(alpha < beta);
    if depth == 0 {
        // On leaf nodes, do quiescence search.
        let (value, nodes) = p.evaluate_quiescence(alpha, beta);
        *nc += nodes;
        Ok(value)
    } else {
        moves.save();
        p.generate_moves(moves);
        // TODO: Consult `tt` here.

        let mut bound_type = BOUND_UPPER;
        let mut move16 = 0;
        let mut no_moves_yet = true;
        while let Some(m) = moves.remove_best_move() {
            if p.do_move(m) {
                // From time to time, we report how many nodes had
                // been searched since the last report. This also
                // gives an opportunity for the search to be
                // terminated.
                *nc += 1;
                if *nc > NODE_COUNT_REPORT_INTERVAL {
                    try!(report(*nc));
                    *nc = 0;
                }

                let value = if no_moves_yet {
                    // The first move we analyze with a fully open
                    // window (alpha, beta).
                    -try!(search(tt, p, moves, nc, report, -beta, -alpha, depth - 1))
                } else {
                    // For the next moves we first try to prove that
                    // they are not better than our current best
                    // move. For this purpose we analyze them with a
                    // null window (alpha, alpha + 1). This is faster
                    // than a full window search. Only when we are
                    // certain that the move is better than our
                    // current best move, we do a full-window search.
                    match -try!(search(tt, p, moves, nc, report, -alpha - 1, -alpha, depth - 1)) {
                        x if x <= alpha => x,
                        _ => -try!(search(tt, p, moves, nc, report, -beta, -alpha, depth - 1)),
                    }
                };
                no_moves_yet = false;
                p.undo_move();

                if value >= beta {
                    // This move is too good, so that the opponent
                    // will not allow this line of play to
                    // happen. Therefore we can stop here.
                    alpha = beta;
                    bound_type = BOUND_LOWER;
                    move16 = m.move16();
                    break;
                }
                if value > alpha {
                    // We found ourselves a new best move.
                    alpha = value;
                    bound_type = BOUND_EXACT;
                    move16 = m.move16();
                }
            }
        }
        moves.restore();
        if no_moves_yet {
            // No legal moves -- this is a final position.
            alpha = p.evaluate_final();
        }
        // TODO: Do not store values with too small `depth`.
        tt.store(p.hash(),
                 EntryData::new(alpha, bound_type, depth, move16, 0));
        Ok(alpha)
    }
}

const NODE_COUNT_REPORT_INTERVAL: NodeCount = 10000;
<commit_msg>more work<commit_after>use std::cell::UnsafeCell;
use std::sync::mpsc::{Sender, Receiver, RecvError, TryRecvError};
use basetypes::*;
use chess_move::MoveStack;
use tt::*;
use position::Position;

pub struct Parameters {
    id: usize,
    position: Position,
    depth: u8,
    alpha: Value,
    beta: Value,
}

pub enum Command {
    Search(Parameters),
    Stop,
    Exit,
}

pub struct Progress {
    search_id: usize,
    searched_nodes: NodeCount,
}

pub struct Done {
    search_id: usize,
    value: Option<Value>,
}

pub fn run(tt: &TranspositionTable,
           commands: Receiver<Command>,
           reports: Sender<Progress>,
           results: Sender<Done>) {
    thread_local!(
        static MOVE_STACK: UnsafeCell<MoveStack> = UnsafeCell::new(MoveStack::new())
    );
    MOVE_STACK.with(|move_stack| {
        let mut move_stack = unsafe { &mut *move_stack.get() };
        let mut pending_command = None;
        loop {
            // If there is a pending command, we take it, otherwise we
            // block and wait to receive a new one.
            let command = pending_command.take()
                                         .unwrap_or(commands.recv()
                                                            .or::<RecvError>(Ok(Command::Exit))
                                                            .unwrap());
            match command {
                Command::Search(mut params) => {
                    move_stack.save();
                    let search_id = params.id;
                    let mut searched_nodes = 0;
                    results.send(Done {
                        search_id: search_id,
                        value: search(tt,
                                      &mut params.position,
                                      move_stack,
                                      &mut 0,
                                      &mut |nc| {
                                          searched_nodes += nc;
                                          reports.send(Progress {
                                              search_id: search_id,
                                              searched_nodes: searched_nodes,
                                          });
                                          match commands.try_recv() {
                                              Ok(x) => {
                                                  // There is a new command pending -- we
                                                  // should terminate the current search.
                                                  pending_command = Some(x);
                                                  Err(TerminatedSearch)
                                              }
                                              Err(_) => Ok(()),
                                          }
                                      },
                                      params.alpha,
                                      params.beta,
                                      params.depth)
                                   .ok(),
                    });
                    move_stack.restore();
                }
                Command::Stop => continue,
                Command::Exit => break,
            }
        }
    })
}

/// Represents a terminated search condition.
pub struct TerminatedSearch;

pub fn search(tt: &TranspositionTable,
              p: &mut Position,
              moves: &mut MoveStack,
              nc: &mut NodeCount,
              report: &mut FnMut(NodeCount) -> Result<(), TerminatedSearch>,
              mut alpha: Value, // lower bound
              beta: Value, // upper bound
              depth: u8)
              -> Result<Value, TerminatedSearch> {
    assert!(alpha < beta);
    if depth == 0 {
        // On leaf nodes, do quiescence search.
        let (value, nodes) = p.evaluate_quiescence(alpha, beta);
        *nc += nodes;
        Ok(value)
    } else {
        moves.save();
        p.generate_moves(moves);
        // TODO: Consult `tt` here.

        let mut bound_type = BOUND_UPPER;
        let mut move16 = 0;
        let mut no_moves_yet = true;
        while let Some(m) = moves.remove_best_move() {
            if p.do_move(m) {
                // From time to time, we report how many nodes had
                // been searched since the last report. This also
                // gives an opportunity for the search to be
                // terminated.
                *nc += 1;
                if *nc > NODE_COUNT_REPORT_INTERVAL {
                    try!(report(*nc));
                    *nc = 0;
                }

                let value = if no_moves_yet {
                    // The first move we analyze with a fully open
                    // window (alpha, beta).
                    -try!(search(tt, p, moves, nc, report, -beta, -alpha, depth - 1))
                } else {
                    // For the next moves we first try to prove that
                    // they are not better than our current best
                    // move. For this purpose we analyze them with a
                    // null window (alpha, alpha + 1). This is faster
                    // than a full window search. Only when we are
                    // certain that the move is better than our
                    // current best move, we do a full-window search.
                    match -try!(search(tt, p, moves, nc, report, -alpha - 1, -alpha, depth - 1)) {
                        x if x <= alpha => x,
                        _ => -try!(search(tt, p, moves, nc, report, -beta, -alpha, depth - 1)),
                    }
                };
                no_moves_yet = false;
                p.undo_move();

                if value >= beta {
                    // This move is too good, so that the opponent
                    // will not allow this line of play to
                    // happen. Therefore we can stop here.
                    alpha = beta;
                    bound_type = BOUND_LOWER;
                    move16 = m.move16();
                    break;
                }
                if value > alpha {
                    // We found ourselves a new best move.
                    alpha = value;
                    bound_type = BOUND_EXACT;
                    move16 = m.move16();
                }
            }
        }
        moves.restore();
        if no_moves_yet {
            // No legal moves -- this is a final position.
            alpha = p.evaluate_final();
        }
        // TODO: Do not store values with too small `depth`.
        tt.store(p.hash(),
                 EntryData::new(alpha, bound_type, depth, move16, 0));
        Ok(alpha)
    }
}

const NODE_COUNT_REPORT_INTERVAL: NodeCount = 10000;
<|endoftext|>