<commit_before>//! A simple connection pool

use std::cell::RefCell;
use sync::MutexArc;

use {PostgresNotifications,
     PostgresCancelData,
     PostgresConnection,
     NormalPostgresStatement,
     PostgresTransaction,
     SslMode};
use error::{PostgresConnectError, PostgresError};
use types::ToSql;

struct InnerConnectionPool {
    url: ~str,
    ssl: SslMode,
    pool: ~[PostgresConnection],
}

impl InnerConnectionPool {
    fn new_connection(&mut self) -> Option<PostgresConnectError> {
        match PostgresConnection::try_connect(self.url, &self.ssl) {
            Ok(conn) => {
                self.pool.push(conn);
                None
            }
            Err(err) => Some(err)
        }
    }
}

/// A simple fixed-size Postgres connection pool.
///
/// It can be shared across tasks.
///
/// # Example
///
/// ```rust,no_run
/// # use postgres::NoSsl;
/// # use postgres::pool::PostgresConnectionPool;
/// let pool = PostgresConnectionPool::new("postgres://postgres@localhost",
///                                        NoSsl, 5);
/// for _ in range(0, 10) {
///     let pool = pool.clone();
///     spawn(proc() {
///         let conn = pool.get_connection();
///         conn.execute("UPDATE foo SET bar = 1", []);
///     });
/// }
/// ```
#[deriving(Clone)]
pub struct PostgresConnectionPool {
    priv pool: MutexArc<InnerConnectionPool>
}

impl PostgresConnectionPool {
    /// Attempts to create a new pool with the specified number of connections.
    ///
    /// Returns an error if the specified number of connections cannot be
    /// created.
    pub fn try_new(url: &str, ssl: SslMode, pool_size: uint)
            -> Result<PostgresConnectionPool, PostgresConnectError> {
        let mut pool = InnerConnectionPool {
            url: url.to_owned(),
            ssl: ssl,
            pool: ~[],
        };

        for _ in range(0, pool_size) {
            match pool.new_connection() {
                None => (),
                Some(err) => return Err(err)
            }
        }

        Ok(PostgresConnectionPool {
            pool: MutexArc::new(pool)
        })
    }

    /// A convenience function wrapping `try_new`.
    ///
    /// # Failure
    ///
    /// Fails if the pool cannot be created.
    pub fn new(url: &str, ssl: SslMode, pool_size: uint)
            -> PostgresConnectionPool {
        match PostgresConnectionPool::try_new(url, ssl, pool_size) {
            Ok(pool) => pool,
            Err(err) => fail!("Unable to initialize pool: {}", err)
        }
    }

    /// Retrieves a connection from the pool.
    ///
    /// If all connections are in use, blocks until one becomes available.
    pub fn get_connection(&self) -> PooledPostgresConnection {
        let conn = self.pool.access_cond(|pool, cvar| {
            while pool.pool.is_empty() {
                cvar.wait();
            }

            pool.pool.pop().unwrap()
        });

        PooledPostgresConnection {
            pool: self.clone(),
            conn: Some(conn)
        }
    }
}

/// A Postgres connection pulled from a connection pool.
///
/// It will be returned to the pool when it falls out of scope, even due to
/// task failure.
pub struct PooledPostgresConnection {
    priv pool: PostgresConnectionPool,
    // TODO remove the Option wrapper when drop takes self by value
    priv conn: Option<PostgresConnection>
}

impl Drop for PooledPostgresConnection {
    fn drop(&mut self) {
        let conn = RefCell::new(self.conn.take());
        self.pool.pool.access(|pool| {
            pool.pool.push(conn.borrow_mut().take_unwrap());
        })
    }
}

impl PooledPostgresConnection {
    /// Like `PostgresConnection::try_prepare`.
    pub fn try_prepare<'a>(&'a self, query: &str)
            -> Result<NormalPostgresStatement<'a>, PostgresError> {
        self.conn.get_ref().try_prepare(query)
    }

    /// Like `PostgresConnection::prepare`.
    pub fn prepare<'a>(&'a self, query: &str) -> NormalPostgresStatement<'a> {
        self.conn.get_ref().prepare(query)
    }

    /// Like `PostgresConnection::try_execute`.
    pub fn try_execute(&self, query: &str, params: &[&ToSql])
            -> Result<uint, PostgresError> {
        self.conn.get_ref().try_execute(query, params)
    }

    /// Like `PostgresConnection::execute`.
    pub fn execute(&self, query: &str, params: &[&ToSql]) -> uint {
        self.conn.get_ref().execute(query, params)
    }

    /// Like `PostgresConnection::try_transaction`.
    pub fn try_transaction<'a>(&'a self)
            -> Result<PostgresTransaction<'a>, PostgresError> {
        self.conn.get_ref().try_transaction()
    }

    /// Like `PostgresConnection::transaction`.
    pub fn transaction<'a>(&'a self) -> PostgresTransaction<'a> {
        self.conn.get_ref().transaction()
    }

    /// Like `PostgresConnection::notifications`.
    pub fn notifications<'a>(&'a self) -> PostgresNotifications<'a> {
        self.conn.get_ref().notifications()
    }

    /// Like `PostgresConnection::cancel_data`.
    pub fn cancel_data(&self) -> PostgresCancelData {
        self.conn.get_ref().cancel_data()
    }

    /// Like `PostgresConnection::is_desynchronized`.
    pub fn is_desynchronized(&self) -> bool {
        self.conn.get_ref().is_desynchronized()
    }
}
<commit_msg>Update for sync changes<commit_after>//! A simple connection pool

use std::cast;
use sync::{Arc, Mutex};

use {PostgresNotifications,
     PostgresCancelData,
     PostgresConnection,
     NormalPostgresStatement,
     PostgresTransaction,
     SslMode};
use error::{PostgresConnectError, PostgresError};
use types::ToSql;

struct InnerConnectionPool {
    url: ~str,
    ssl: SslMode,
    // Actually Vec<~PostgresConnection>
    pool: Vec<*()>,
}

impl Drop for InnerConnectionPool {
    fn drop(&mut self) {
        loop {
            match self.pool.pop() {
                Some(conn) => unsafe {
                    drop(cast::transmute::<*(), ~PostgresConnection>(conn));
                },
                None => break
            }
        }
    }
}

impl InnerConnectionPool {
    fn new_connection(&mut self) -> Option<PostgresConnectError> {
        match PostgresConnection::try_connect(self.url, &self.ssl) {
            Ok(conn) => {
                unsafe { self.pool.push(cast::transmute(~conn)) };
                None
            }
            Err(err) => Some(err)
        }
    }
}

/// A simple fixed-size Postgres connection pool.
///
/// It can be shared across tasks.
///
/// # Example
///
/// ```rust,no_run
/// # use postgres::NoSsl;
/// # use postgres::pool::PostgresConnectionPool;
/// let pool = PostgresConnectionPool::new("postgres://postgres@localhost",
///                                        NoSsl, 5);
/// for _ in range(0, 10) {
///     let pool = pool.clone();
///     spawn(proc() {
///         let conn = pool.get_connection();
///         conn.execute("UPDATE foo SET bar = 1", []);
///     });
/// }
/// ```
#[deriving(Clone)]
pub struct PostgresConnectionPool {
    priv pool: Arc<Mutex<InnerConnectionPool>>
}

impl PostgresConnectionPool {
    /// Attempts to create a new pool with the specified number of connections.
    ///
    /// Returns an error if the specified number of connections cannot be
    /// created.
    pub fn try_new(url: &str, ssl: SslMode, pool_size: uint)
            -> Result<PostgresConnectionPool, PostgresConnectError> {
        let mut pool = InnerConnectionPool {
            url: url.to_owned(),
            ssl: ssl,
            pool: Vec::new(),
        };

        for _ in range(0, pool_size) {
            match pool.new_connection() {
                None => (),
                Some(err) => return Err(err)
            }
        }

        Ok(PostgresConnectionPool {
            pool: Arc::new(Mutex::new(pool))
        })
    }

    /// A convenience function wrapping `try_new`.
    ///
    /// # Failure
    ///
    /// Fails if the pool cannot be created.
    pub fn new(url: &str, ssl: SslMode, pool_size: uint)
            -> PostgresConnectionPool {
        match PostgresConnectionPool::try_new(url, ssl, pool_size) {
            Ok(pool) => pool,
            Err(err) => fail!("Unable to initialize pool: {}", err)
        }
    }

    /// Retrieves a connection from the pool.
    ///
    /// If all connections are in use, blocks until one becomes available.
    pub fn get_connection(&self) -> PooledPostgresConnection {
        let mut pool = self.pool.lock();

        while pool.pool.is_empty() {
            pool.cond.wait();
        }

        PooledPostgresConnection {
            pool: self.clone(),
            conn: Some(unsafe { cast::transmute(pool.pool.pop().unwrap()) })
        }
    }
}

/// A Postgres connection pulled from a connection pool.
///
/// It will be returned to the pool when it falls out of scope, even due to
/// task failure.
pub struct PooledPostgresConnection {
    priv pool: PostgresConnectionPool,
    // TODO remove the Option wrapper when drop takes self by value
    priv conn: Option<~PostgresConnection>
}

impl Drop for PooledPostgresConnection {
    fn drop(&mut self) {
        let conn = unsafe { cast::transmute(self.conn.take_unwrap()) };
        self.pool.pool.lock().pool.push(conn);
    }
}

impl PooledPostgresConnection {
    /// Like `PostgresConnection::try_prepare`.
    pub fn try_prepare<'a>(&'a self, query: &str)
            -> Result<NormalPostgresStatement<'a>, PostgresError> {
        self.conn.get_ref().try_prepare(query)
    }

    /// Like `PostgresConnection::prepare`.
    pub fn prepare<'a>(&'a self, query: &str) -> NormalPostgresStatement<'a> {
        self.conn.get_ref().prepare(query)
    }

    /// Like `PostgresConnection::try_execute`.
    pub fn try_execute(&self, query: &str, params: &[&ToSql])
            -> Result<uint, PostgresError> {
        self.conn.get_ref().try_execute(query, params)
    }

    /// Like `PostgresConnection::execute`.
    pub fn execute(&self, query: &str, params: &[&ToSql]) -> uint {
        self.conn.get_ref().execute(query, params)
    }

    /// Like `PostgresConnection::try_transaction`.
    pub fn try_transaction<'a>(&'a self)
            -> Result<PostgresTransaction<'a>, PostgresError> {
        self.conn.get_ref().try_transaction()
    }

    /// Like `PostgresConnection::transaction`.
    pub fn transaction<'a>(&'a self) -> PostgresTransaction<'a> {
        self.conn.get_ref().transaction()
    }

    /// Like `PostgresConnection::notifications`.
    pub fn notifications<'a>(&'a self) -> PostgresNotifications<'a> {
        self.conn.get_ref().notifications()
    }

    /// Like `PostgresConnection::cancel_data`.
    pub fn cancel_data(&self) -> PostgresCancelData {
        self.conn.get_ref().cancel_data()
    }

    /// Like `PostgresConnection::is_desynchronized`.
    pub fn is_desynchronized(&self) -> bool {
        self.conn.get_ref().is_desynchronized()
    }
}
<|endoftext|>


<commit_before>//!A raytracer.
#![feature(path, io)]
extern crate image;
extern crate rand;

use std::old_io::File;
use std::num::Float;
use std::f32::consts::PI_2;

use rand::distributions::IndependentSample;
use rand::Rng;

use point::Point3;
use vec::Vec3;

mod vec;
mod point;

#[derive(Copy)]
struct Ray3 {
    start: Point3,
    dir: Vec3
}

struct Intersection<ObjectId> {
    time: f32,
    point: Point3,
    normal: Vec3,
    emitted: f32,
    object: ObjectId
}

trait Scene {
    // TODO: Should this have a "not present" id?
    type ObjectId: Copy;

    fn intersect(&self, ray: Ray3, previous: Option<Self::ObjectId>) -> Option<Intersection<Self::ObjectId>>;
}

struct Material {
    emitted_radiance: f32
}

struct Sphere {
    center: Point3,
    radius: f32,
    material: Material
}

impl Scene for Sphere {
    type ObjectId = ();
    fn intersect(&self, ray: Ray3, previous: Option<()>) -> Option<Intersection<()>> {
        if let Some(()) = previous {
            return None;
        }

        let offset = ray.start - self.center;

        let a = ray.dir.mag2();
        let b = 2. * offset.dot(ray.dir);
        let c = offset.mag2() - self.radius*self.radius;

        let descrim = b*b - 4.*a*c;
        if descrim > 0. {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if t1 > 0. {
                let p = ray.start + ray.dir * t1;
                let normal = p - self.center;
                Some(Intersection {
                    time: t1,
                    point: p,
                    normal: normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else if t2 > 0. {
                let p = ray.start + ray.dir * t2;
                let normal = p - self.center;
                Some(Intersection {
                    time: t2,
                    point: p,
                    normal: normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else {
                None
            }
        } else {
            None
        }
    }
}

struct Plane {
    origin: Point3,
    normal: Vec3,
    material: Material
}

impl Scene for Plane {
    type ObjectId = ();
    fn intersect(&self, ray: Ray3, previous: Option<()>) -> Option<Intersection<()>> {
        if let Some(()) = previous {
            return None;
        }

        let divisor = ray.dir.dot(self.normal);
        if divisor == 0. {
            None
        } else {
            let offset = ray.start - self.origin;
            let time = -offset.dot(self.normal) / divisor;
            if time > 0. {
                Some(Intersection {
                    time: time,
                    point: ray.start + ray.dir * time,
                    normal: self.normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else {
                None
            }
        }
    }
}

#[derive(Copy)]
enum Choice<A, B> {
    OptA(A),
    OptB(B)
}

impl<A: Scene, B: Scene> Scene for (A, B) {
    type ObjectId = Choice<A::ObjectId, B::ObjectId>;
    fn intersect(&self, ray: Ray3, previous: Option<Choice<A::ObjectId, B::ObjectId>>) -> Option<Intersection<Choice<A::ObjectId, B::ObjectId>>> {
        let (aid, bid) = match previous {
            None => (None, None),
            Some(Choice::OptA(aid)) => (Some(aid), None),
            Some(Choice::OptB(bid)) => (None, Some(bid))
        };

        match self.0.intersect(ray, aid) {
            Some(ai) => {
                match self.1.intersect(ray, bid) {
                    Some(bi) => if ai.time < bi.time {
                        Some(Intersection {
                            time: ai.time,
                            normal: ai.normal,
                            point: ai.point,
                            emitted: ai.emitted,
                            object: Choice::OptA(ai.object)
                        })
                    } else {
                        Some(Intersection {
                            time: bi.time,
                            normal: bi.normal,
                            point: bi.point,
                            emitted: bi.emitted,
                            object: Choice::OptB(bi.object)
                        })
                    },
                    None => Some(Intersection {
                        time: ai.time,
                        normal: ai.normal,
                        point: ai.point,
                        emitted: ai.emitted,
                        object: Choice::OptA(ai.object)
                    })
                }
            },
            None => match self.1.intersect(ray, bid) {
                Some(bi) => Some(Intersection {
                    time: bi.time,
                    normal: bi.normal,
                    point: bi.point,
                    emitted: bi.emitted,
                    object: Choice::OptB(bi.object)
                }),
                None => None
            }
        }
    }
}

impl<T: Scene> Scene for [T] {
    type ObjectId = (usize, T::ObjectId);
    fn intersect(&self, ray: Ray3, previous: Option<(usize, T::ObjectId)>) -> Option<Intersection<(usize, T::ObjectId)>> {
        let mut best: Option<Intersection<(usize, T::ObjectId)>> = None;

        for (id, obj) in self.iter().enumerate() {
            let prev = match previous {
                Some((prev_index, prev_obj)) => if prev_index == id {
                    Some(prev_obj)
                } else {
                    None
                },
                None => None
            };

            if let Some(intersection) = obj.intersect(ray, prev) {
                let new_best = match best {
                    Some(ref cur_best) => intersection.time < cur_best.time,
                    None => true
                };

                if new_best {
                    best = Some(Intersection {
                        time: intersection.time,
                        normal: intersection.normal,
                        point: intersection.point,
                        emitted: intersection.emitted,
                        object: (id, intersection.object)
                    });
                }
            }
        }

        best
    }
}

impl<'a, T: ?Sized + Scene> Scene for &'a T {
    type ObjectId = T::ObjectId;
    fn intersect(&self, ray: Ray3, previous: Option<T::ObjectId>) -> Option<Intersection<T::ObjectId>> {
        (*self).intersect(ray, previous)
    }
}

fn clamp(val: f32) -> f32 {
    if val > 1. {
        1.
    } else if val < 0. {
        0.
    } else {
        val
    }
}

fn rand_sphere<R: rand::Rng>(rng: &mut R) -> Vec3 {
    let z = rand::distributions::Range::new(-1., 1.).ind_sample(rng);
    let r = (1. - z*z).sqrt();
    let angle = rand::distributions::Range::new(0., PI_2).ind_sample(rng);
    Vec3::new(r*angle.cos(), r*angle.sin(), z)
}

fn main() {
    let mut rng = rand::weak_rng();

    let rays_per_pixel = 100;
    let scene: (&[Sphere], &[Plane]) = (
        &[Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3,
            material: Material { emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35,
            material: Material { emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.0, 2.5, 0.5),
            radius: 1.0,
            material: Material { emitted_radiance: 20. }
        }],
        &[Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 2.0, 0.0),
            normal: Vec3::new(0.0, -1.0, 0.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, -3.0, 0.0),
            normal: Vec3::new(0.0, 1.0, 0.0),
            material: Material { emitted_radiance: 0. }
        }]
    );

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::new(imgx, imgy);

    // Iterate over the coordiantes and pixels of the image
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let cy = -(y as f32 * scaley - 2.0);
        let cx = x as f32 * scalex - 2.0;

        let mut total_light = 0.;
        for _ in 0..rays_per_pixel {
            let mut ray = Ray3 {
                start: Point3::new(0., 0., -8.0),
                dir: Vec3::new(cx, cy, 8.0)
            };
            let mut prev_object = None;
            let mut scale = 1.;
            loop {
                if let Some(intersection) = scene.intersect(ray, prev_object) {
                    prev_object = Some(intersection.object);

                    total_light += scale * intersection.emitted;

                    let cand_dir = rand_sphere(&mut rng);
                    let dir = if cand_dir.dot(intersection.normal) < 0. {
                        -cand_dir
                    } else {
                        cand_dir
                    };
                    ray = Ray3 {
                        start: intersection.point,
                        dir: dir
                    };

                    let p = dir.dot(intersection.normal) / intersection.normal.mag2().sqrt();
                    if scale > 0.2 {
                        scale *= p;
                    } else if rng.next_f32() > p {
                        break;
                    }
                } else {
                    break;
                }
            }
        }

        // Create an 8bit pixel of type Luma and value i
        // and assign in to the pixel at position (x, y)
        *pixel = image::Luma([(clamp(total_light / rays_per_pixel as f32)*255.) as u8]);
    }

    // Save the image as “out.png”
    let ref mut fout = File::create(&Path::new("out.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _ = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}
<commit_msg>Clean up scene union code (pairs and arrays)<commit_after>//!A raytracer.
#![feature(path, io)]
extern crate image;
extern crate rand;

use std::old_io::File;
use std::num::Float;
use std::f32::consts::PI_2;

use rand::distributions::IndependentSample;
use rand::Rng;

use point::Point3;
use vec::Vec3;

mod vec;
mod point;

#[derive(Copy)]
struct Ray3 {
    start: Point3,
    dir: Vec3
}

struct Intersection<ObjectId> {
    time: f32,
    point: Point3,
    normal: Vec3,
    emitted: f32,
    object: ObjectId
}

impl<ObjectId> Intersection<ObjectId> {
    fn map_obj<NewObjectId, F: FnOnce(ObjectId) -> NewObjectId>(self, func: F) -> Intersection<NewObjectId> {
        Intersection {
            time: self.time,
            point: self.point,
            normal: self.normal,
            emitted: self.emitted,
            object: func(self.object)
        }
    }
}

trait Scene {
    // TODO: Should this have a "not present" id?
    type ObjectId: Copy;

    fn intersect(&self, ray: Ray3, previous: Option<Self::ObjectId>) -> Option<Intersection<Self::ObjectId>>;
}

struct Material {
    emitted_radiance: f32
}

struct Sphere {
    center: Point3,
    radius: f32,
    material: Material
}

impl Scene for Sphere {
    type ObjectId = ();
    fn intersect(&self, ray: Ray3, previous: Option<()>) -> Option<Intersection<()>> {
        if let Some(()) = previous {
            return None;
        }

        let offset = ray.start - self.center;

        let a = ray.dir.mag2();
        let b = 2. * offset.dot(ray.dir);
        let c = offset.mag2() - self.radius*self.radius;

        let descrim = b*b - 4.*a*c;
        if descrim > 0. {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if t1 > 0. {
                let p = ray.start + ray.dir * t1;
                let normal = p - self.center;
                Some(Intersection {
                    time: t1,
                    point: p,
                    normal: normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else if t2 > 0. {
                let p = ray.start + ray.dir * t2;
                let normal = p - self.center;
                Some(Intersection {
                    time: t2,
                    point: p,
                    normal: normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else {
                None
            }
        } else {
            None
        }
    }
}

struct Plane {
    origin: Point3,
    normal: Vec3,
    material: Material
}

impl Scene for Plane {
    type ObjectId = ();
    fn intersect(&self, ray: Ray3, previous: Option<()>) -> Option<Intersection<()>> {
        if let Some(()) = previous {
            return None;
        }

        let divisor = ray.dir.dot(self.normal);
        if divisor == 0. {
            None
        } else {
            let offset = ray.start - self.origin;
            let time = -offset.dot(self.normal) / divisor;
            if time > 0. {
                Some(Intersection {
                    time: time,
                    point: ray.start + ray.dir * time,
                    normal: self.normal,
                    emitted: self.material.emitted_radiance,
                    object: ()
                })
            } else {
                None
            }
        }
    }
}

#[derive(Copy)]
enum Choice<A, B> {
    OptA(A),
    OptB(B)
}

impl<A: Scene, B: Scene> Scene for (A, B) {
    type ObjectId = Choice<A::ObjectId, B::ObjectId>;
    fn intersect(&self, ray: Ray3, previous: Option<Choice<A::ObjectId, B::ObjectId>>) -> Option<Intersection<Choice<A::ObjectId, B::ObjectId>>> {
        let (aid, bid) = match previous {
            None => (None, None),
            Some(Choice::OptA(aid)) => (Some(aid), None),
            Some(Choice::OptB(bid)) => (None, Some(bid))
        };

        match (self.0.intersect(ray, aid), self.1.intersect(ray, bid)) {
            (Some(ai), Some(bi)) => if ai.time < bi.time {
                Some(ai.map_obj(Choice::OptA))
            } else {
                Some(bi.map_obj(Choice::OptB))
            },
            (Some(ai), None) => Some(ai.map_obj(Choice::OptA)),
            (None, Some(bi)) => Some(bi.map_obj(Choice::OptB)),
            (None, None) => None
        }
    }
}

impl<T: Scene> Scene for [T] {
    type ObjectId = (usize, T::ObjectId);
    fn intersect(&self, ray: Ray3, previous: Option<(usize, T::ObjectId)>) -> Option<Intersection<(usize, T::ObjectId)>> {
        let mut best: Option<Intersection<(usize, T::ObjectId)>> = None;

        for (id, obj) in self.iter().enumerate() {
            let prev = match previous {
                Some((prev_index, prev_obj)) => if prev_index == id {
                    Some(prev_obj)
                } else {
                    None
                },
                None => None
            };

            if let Some(intersection) = obj.intersect(ray, prev) {
                let new_best = match best {
                    Some(ref cur_best) => intersection.time < cur_best.time,
                    None => true
                };

                if new_best {
                    best = Some(intersection.map_obj(|obj| (id, obj)));
                }
            }
        }

        best
    }
}

impl<'a, T: ?Sized + Scene> Scene for &'a T {
    type ObjectId = T::ObjectId;
    fn intersect(&self, ray: Ray3, previous: Option<T::ObjectId>) -> Option<Intersection<T::ObjectId>> {
        (*self).intersect(ray, previous)
    }
}

fn clamp(val: f32) -> f32 {
    if val > 1. {
        1.
    } else if val < 0. {
        0.
    } else {
        val
    }
}

fn rand_sphere<R: rand::Rng>(rng: &mut R) -> Vec3 {
    let z = rand::distributions::Range::new(-1., 1.).ind_sample(rng);
    let r = (1. - z*z).sqrt();
    let angle = rand::distributions::Range::new(0., PI_2).ind_sample(rng);
    Vec3::new(r*angle.cos(), r*angle.sin(), z)
}

fn main() {
    let mut rng = rand::weak_rng();

    let rays_per_pixel = 100;
    let scene: (&[Sphere], &[Plane]) = (
        &[Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3,
            material: Material { emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35,
            material: Material { emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.0, 2.5, 0.5),
            radius: 1.0,
            material: Material { emitted_radiance: 20. }
        }],
        &[Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 2.0, 0.0),
            normal: Vec3::new(0.0, -1.0, 0.0),
            material: Material { emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, -3.0, 0.0),
            normal: Vec3::new(0.0, 1.0, 0.0),
            material: Material { emitted_radiance: 0. }
        }]
    );

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::new(imgx, imgy);

    // Iterate over the coordiantes and pixels of the image
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let cy = -(y as f32 * scaley - 2.0);
        let cx = x as f32 * scalex - 2.0;

        let mut total_light = 0.;
        for _ in 0..rays_per_pixel {
            let mut ray = Ray3 {
                start: Point3::new(0., 0., -8.0),
                dir: Vec3::new(cx, cy, 8.0)
            };
            let mut prev_object = None;
            let mut scale = 1.;
            loop {
                if let Some(intersection) = scene.intersect(ray, prev_object) {
                    prev_object = Some(intersection.object);

                    total_light += scale * intersection.emitted;

                    let cand_dir = rand_sphere(&mut rng);
                    let dir = if cand_dir.dot(intersection.normal) < 0. {
                        -cand_dir
                    } else {
                        cand_dir
                    };
                    ray = Ray3 {
                        start: intersection.point,
                        dir: dir
                    };

                    let p = dir.dot(intersection.normal) / intersection.normal.mag2().sqrt();
                    if scale > 0.2 {
                        scale *= p;
                    } else if rng.next_f32() > p {
                        break;
                    }
                } else {
                    break;
                }
            }
        }

        // Create an 8bit pixel of type Luma and value i
        // and assign in to the pixel at position (x, y)
        *pixel = image::Luma([(clamp(total_light / rays_per_pixel as f32)*255.) as u8]);
    }

    // Save the image as “out.png”
    let ref mut fout = File::create(&Path::new("out.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _ = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use length::Length;

use point::Point2D;
use size::Size2D;
use std::cmp::{PartialEq, PartialOrd};
use std::fmt;
use std::num::Zero;

#[deriving(Clone, Decodable, Encodable, PartialEq)]
pub struct Rect<T> {
    pub origin: Point2D<T>,
    pub size: Size2D<T>,
}

impl<T: fmt::Show> fmt::Show for Rect<T> {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Rect({} at {})", self.size, self.origin)
    }
}

pub fn Rect<T:Clone>(origin: Point2D<T>, size: Size2D<T>) -> Rect<T> {
    Rect {
        origin: origin,
        size: size
    }
}

impl<T: Clone + PartialOrd + Add<T,T> + Sub<T,T>> Rect<T> {
    #[inline]
    pub fn intersects(&self, other: &Rect<T>) -> bool {
        self.origin.x < other.origin.x + other.size.width &&
       other.origin.x <  self.origin.x + self.size.width &&
        self.origin.y < other.origin.y + other.size.height &&
       other.origin.y <  self.origin.y + self.size.height
    }

    #[inline]
    pub fn max_x(&self) -> T {
        self.origin.x + self.size.width
    }

    #[inline]
    pub fn min_x(&self) -> T {
        self.origin.x.clone()
    }

    #[inline]
    pub fn max_y(&self) -> T {
        self.origin.y + self.size.height
    }

    #[inline]
    pub fn min_y(&self) -> T {
        self.origin.y.clone()
    }

    #[inline]
    pub fn intersection(&self, other: &Rect<T>) -> Option<Rect<T>> {
        if !self.intersects(other) {
            return None;
        }

        let upper_left = Point2D(max(self.min_x(), other.min_x()),
                                 max(self.min_y(), other.min_y()));

        let lower_right = Point2D(min(self.max_x(), other.max_x()),
                                  min(self.max_y(), other.max_y()));

        Some(Rect(upper_left.clone(), Size2D(lower_right.x - upper_left.x,
                                             lower_right.y - upper_left.y)))
    }

    #[inline]
    pub fn union(&self, other: &Rect<T>) -> Rect<T> {
        let upper_left = Point2D(min(self.min_x(), other.min_x()),
                                 min(self.min_y(), other.min_y()));

        let lower_right = Point2D(max(self.max_x(), other.max_x()),
                                  max(self.max_y(), other.max_y()));

        Rect {
            origin: upper_left.clone(),
            size: Size2D(lower_right.x - upper_left.x, lower_right.y - upper_left.y)
        }
    }

    #[inline]
    pub fn translate(&self, other: &Point2D<T>) -> Rect<T> {
        Rect {
            origin: Point2D(self.origin.x + other.x, self.origin.y + other.y),
            size: self.size.clone()
        }
    }

    #[inline]
    pub fn contains(&self, other: &Point2D<T>) -> bool {
        self.origin.x <= other.x && other.x < self.origin.x + self.size.width &&
        self.origin.y <= other.y && other.y < self.origin.y + self.size.height
    }
}

impl<Scale, T: Clone + Mul<Scale,T>> Rect<T> {
    #[inline]
    pub fn scale(&self, x: Scale, y: Scale) -> Rect<T> {
        Rect {
            origin: Point2D { x: self.origin.x * x, y: self.origin.y * y},
            size: Size2D { width: self.size.width * x, height: self.size.height * y}
        }
    }
}

impl<T:Clone + Zero> Rect<T> {
    pub fn zero() -> Rect<T> {
        Rect {
            origin: Zero::zero(),
            size: Size2D::zero(),
        }
    }

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

pub fn min<T:Clone + PartialOrd>(x: T, y: T) -> T {
    if x <= y { x } else { y }
}

pub fn max<T:Clone + PartialOrd>(x: T, y: T) -> T {
    if x >= y { x } else { y }
}

impl<Scale, T0: Mul<Scale, T1>, T1: Clone> Mul<Scale, Rect<T1>> for Rect<T0> {
    #[inline]
    fn mul(&self, scale: &Scale) -> Rect<T1> {
        Rect(self.origin * *scale, self.size * *scale)
    }
}

impl<Scale, T0: Div<Scale, T1>, T1: Clone> Div<Scale, Rect<T1>> for Rect<T0> {
    #[inline]
    fn div(&self, scale: &Scale) -> Rect<T1> {
        Rect(self.origin / *scale, self.size / *scale)
    }
}

// Convenient aliases for Rect with typed units
pub type TypedRect<Unit, T> = Rect<Length<Unit, T>>;

impl<Unit, T: Clone> Rect<Length<Unit, T>> {
    /// Drop the units, preserving only the numeric value.
    pub fn to_untyped(&self) -> Rect<T> {
        Rect(self.origin.to_untyped(), self.size.to_untyped())
    }

    /// Tag a unitless value with units.
    pub fn from_untyped(r: &Rect<T>) -> TypedRect<Unit, T> {
        Rect(Point2D::from_untyped(&r.origin), Size2D::from_untyped(&r.size))
    }
}

impl<Unit, T0: NumCast + Clone, T1: NumCast + Clone> Rect<Length<Unit, T0>> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast(&self) -> Option<Rect<Length<Unit, T1>>> {
        match (self.origin.cast(), self.size.cast()) {
            (Some(origin), Some(size)) => Some(Rect(origin, size)),
            _ => None
        }
    }
}

// Convenience functions for common casts
impl<Unit, T: NumCast + Clone> Rect<Length<Unit, T>> {
    pub fn as_f32(&self) -> Rect<Length<Unit, f32>> {
        self.cast().unwrap()
    }

    pub fn as_uint(&self) -> Rect<Length<Unit, uint>> {
        self.cast().unwrap()
    }
}

#[test]
fn test_min_max() {
    assert!(min(0u32, 1u32) == 0u32);
    assert!(min(-1.0f32, 0.0f32) == -1.0f32);

    assert!(max(0u32, 1u32) == 1u32);
    assert!(max(-1.0f32, 0.0f32) == 0.0f32);
}

#[test]
fn test_translate() {
    let p = Rect(Point2D(0u32, 0u32), Size2D(50u32, 40u32));
    let pp = p.translate(&Point2D(10,15));

    assert!(pp.size.width == 50);
    assert!(pp.size.height == 40);
    assert!(pp.origin.x == 10);
    assert!(pp.origin.y == 15);

    let r = Rect(Point2D(-10i32, -5i32), Size2D(50i32, 40i32));
    let rr = r.translate(&Point2D(0,-10));

    assert!(rr.size.width == 50);
    assert!(rr.size.height == 40);
    assert!(rr.origin.x == -10);
    assert!(rr.origin.y == -15);
}

#[test]
fn test_union() {
    let p = Rect(Point2D(0i32, 0i32), Size2D(50i32, 40i32));
    let q = Rect(Point2D(20i32 ,20i32), Size2D(5i32, 5i32));
    let r = Rect(Point2D(-15i32, -30i32), Size2D(200i32, 15i32));
    let s = Rect(Point2D(20i32, -15i32), Size2D(250i32, 200i32));

    let pq = p.union(&q);
    assert!(pq.origin == Point2D(0, 0));
    assert!(pq.size == Size2D(50, 40));

    let pr = p.union(&r);
    assert!(pr.origin == Point2D(-15, -30));
    assert!(pr.size == Size2D(200, 70));

    let ps = p.union(&s);
    assert!(ps.origin == Point2D(0, -15));
    assert!(ps.size == Size2D(270, 200));

}

#[test]
fn test_intersection() {
    let p = Rect(Point2D(0i32, 0i32), Size2D(10i32, 20i32));
    let q = Rect(Point2D(5i32, 15i32), Size2D(10i32, 10i32));
    let r = Rect(Point2D(-5i32, -5i32), Size2D(8i32, 8i32));

    let pq = p.intersection(&q);
    assert!(pq.is_some());
    let pq = pq.unwrap();
    assert!(pq.origin == Point2D(5, 15));
    assert!(pq.size == Size2D(5, 5));

    let pr = p.intersection(&r);
    assert!(pr.is_some());
    let pr = pr.unwrap();
    assert!(pr.origin == Point2D(0, 0));
    assert!(pr.size == Size2D(3, 3));

    let qr = q.intersection(&r);
    assert!(qr.is_none());
}

#[test]
fn test_contains() {
    let r = Rect(Point2D(-20i32, 15i32), Size2D(100i32, 200i32));

    assert!(r.contains(&Point2D(0, 50)));
    assert!(r.contains(&Point2D(-10, 200)));

    // The `contains` method is inclusive of the top/left edges, but not the
    // bottom/right edges.
    assert!(r.contains(&Point2D(-20, 15)));
    assert!(!r.contains(&Point2D(80, 15)));
    assert!(!r.contains(&Point2D(80, 215)));
    assert!(!r.contains(&Point2D(-20, 215)));

    // Points beyond the top-left corner.
    assert!(!r.contains(&Point2D(-25, 15)));
    assert!(!r.contains(&Point2D(-15, 10)));

    // Points beyond the top-right corner.
    assert!(!r.contains(&Point2D(85, 20)));
    assert!(!r.contains(&Point2D(75, 10)));

    // Points beyond the bottom-right corner.
    assert!(!r.contains(&Point2D(85, 210)));
    assert!(!r.contains(&Point2D(75, 220)));

    // Points beyond the bottom-left corner.
    assert!(!r.contains(&Point2D(-25, 210)));
    assert!(!r.contains(&Point2D(-15, 220)));
}

#[test]
fn test_scale() {
    let p = Rect(Point2D(0u32, 0u32), Size2D(50u32, 40u32));
    let pp = p.scale(10, 15);

    assert!(pp.size.width == 500);
    assert!(pp.size.height == 600);
    assert!(pp.origin.x == 0);
    assert!(pp.origin.y == 0);

    let r = Rect(Point2D(-10i32, -5i32), Size2D(50i32, 40i32));
    let rr = r.scale(1, 20);

    assert!(rr.size.width == 50);
    assert!(rr.size.height == 800);
    assert!(rr.origin.x == -10);
    assert!(rr.origin.y == -100);
}

#[test]
fn test_min_max_x_y() {
    let p = Rect(Point2D(0u32, 0u32), Size2D(50u32, 40u32));
    assert!(p.max_y() == 40);
    assert!(p.min_y() == 0);
    assert!(p.max_x() == 50);
    assert!(p.min_x() == 0);

    let r = Rect(Point2D(-10i32, -5i32), Size2D(50i32, 40i32));
    assert!(r.max_y() == 35);
    assert!(r.min_y() == -5);
    assert!(r.max_x() == 40);
    assert!(r.min_x() == -10);
}
<commit_msg>Add an inflate method to Rect<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use length::Length;

use point::Point2D;
use size::Size2D;
use std::cmp::{PartialEq, PartialOrd};
use std::fmt;
use std::num::Zero;

#[deriving(Clone, Decodable, Encodable, PartialEq)]
pub struct Rect<T> {
    pub origin: Point2D<T>,
    pub size: Size2D<T>,
}

impl<T: fmt::Show> fmt::Show for Rect<T> {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Rect({} at {})", self.size, self.origin)
    }
}

pub fn Rect<T:Clone>(origin: Point2D<T>, size: Size2D<T>) -> Rect<T> {
    Rect {
        origin: origin,
        size: size
    }
}

impl<T: Clone + PartialOrd + Add<T,T> + Sub<T,T>> Rect<T> {
    #[inline]
    pub fn intersects(&self, other: &Rect<T>) -> bool {
        self.origin.x < other.origin.x + other.size.width &&
       other.origin.x <  self.origin.x + self.size.width &&
        self.origin.y < other.origin.y + other.size.height &&
       other.origin.y <  self.origin.y + self.size.height
    }

    #[inline]
    pub fn max_x(&self) -> T {
        self.origin.x + self.size.width
    }

    #[inline]
    pub fn min_x(&self) -> T {
        self.origin.x.clone()
    }

    #[inline]
    pub fn max_y(&self) -> T {
        self.origin.y + self.size.height
    }

    #[inline]
    pub fn min_y(&self) -> T {
        self.origin.y.clone()
    }

    #[inline]
    pub fn intersection(&self, other: &Rect<T>) -> Option<Rect<T>> {
        if !self.intersects(other) {
            return None;
        }

        let upper_left = Point2D(max(self.min_x(), other.min_x()),
                                 max(self.min_y(), other.min_y()));

        let lower_right = Point2D(min(self.max_x(), other.max_x()),
                                  min(self.max_y(), other.max_y()));

        Some(Rect(upper_left.clone(), Size2D(lower_right.x - upper_left.x,
                                             lower_right.y - upper_left.y)))
    }

    #[inline]
    pub fn union(&self, other: &Rect<T>) -> Rect<T> {
        let upper_left = Point2D(min(self.min_x(), other.min_x()),
                                 min(self.min_y(), other.min_y()));

        let lower_right = Point2D(max(self.max_x(), other.max_x()),
                                  max(self.max_y(), other.max_y()));

        Rect {
            origin: upper_left.clone(),
            size: Size2D(lower_right.x - upper_left.x, lower_right.y - upper_left.y)
        }
    }

    #[inline]
    pub fn translate(&self, other: &Point2D<T>) -> Rect<T> {
        Rect {
            origin: Point2D(self.origin.x + other.x, self.origin.y + other.y),
            size: self.size.clone()
        }
    }

    #[inline]
    pub fn contains(&self, other: &Point2D<T>) -> bool {
        self.origin.x <= other.x && other.x < self.origin.x + self.size.width &&
        self.origin.y <= other.y && other.y < self.origin.y + self.size.height
    }

    #[inline]
    pub fn inflate(&self, width: T, height: T) -> Rect<T> {
        Rect {
            origin: Point2D(self.origin.x - width, self.origin.y - height),
            size: Size2D(self.size.width + width + width, self.size.height + height + height),
        }
    }
}

impl<Scale, T: Clone + Mul<Scale,T>> Rect<T> {
    #[inline]
    pub fn scale(&self, x: Scale, y: Scale) -> Rect<T> {
        Rect {
            origin: Point2D { x: self.origin.x * x, y: self.origin.y * y},
            size: Size2D { width: self.size.width * x, height: self.size.height * y}
        }
    }
}

impl<T:Clone + Zero> Rect<T> {
    pub fn zero() -> Rect<T> {
        Rect {
            origin: Zero::zero(),
            size: Size2D::zero(),
        }
    }

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

pub fn min<T:Clone + PartialOrd>(x: T, y: T) -> T {
    if x <= y { x } else { y }
}

pub fn max<T:Clone + PartialOrd>(x: T, y: T) -> T {
    if x >= y { x } else { y }
}

impl<Scale, T0: Mul<Scale, T1>, T1: Clone> Mul<Scale, Rect<T1>> for Rect<T0> {
    #[inline]
    fn mul(&self, scale: &Scale) -> Rect<T1> {
        Rect(self.origin * *scale, self.size * *scale)
    }
}

impl<Scale, T0: Div<Scale, T1>, T1: Clone> Div<Scale, Rect<T1>> for Rect<T0> {
    #[inline]
    fn div(&self, scale: &Scale) -> Rect<T1> {
        Rect(self.origin / *scale, self.size / *scale)
    }
}

// Convenient aliases for Rect with typed units
pub type TypedRect<Unit, T> = Rect<Length<Unit, T>>;

impl<Unit, T: Clone> Rect<Length<Unit, T>> {
    /// Drop the units, preserving only the numeric value.
    pub fn to_untyped(&self) -> Rect<T> {
        Rect(self.origin.to_untyped(), self.size.to_untyped())
    }

    /// Tag a unitless value with units.
    pub fn from_untyped(r: &Rect<T>) -> TypedRect<Unit, T> {
        Rect(Point2D::from_untyped(&r.origin), Size2D::from_untyped(&r.size))
    }
}

impl<Unit, T0: NumCast + Clone, T1: NumCast + Clone> Rect<Length<Unit, T0>> {
    /// Cast from one numeric representation to another, preserving the units.
    pub fn cast(&self) -> Option<Rect<Length<Unit, T1>>> {
        match (self.origin.cast(), self.size.cast()) {
            (Some(origin), Some(size)) => Some(Rect(origin, size)),
            _ => None
        }
    }
}

// Convenience functions for common casts
impl<Unit, T: NumCast + Clone> Rect<Length<Unit, T>> {
    pub fn as_f32(&self) -> Rect<Length<Unit, f32>> {
        self.cast().unwrap()
    }

    pub fn as_uint(&self) -> Rect<Length<Unit, uint>> {
        self.cast().unwrap()
    }
}

#[test]
fn test_min_max() {
    assert!(min(0u32, 1u32) == 0u32);
    assert!(min(-1.0f32, 0.0f32) == -1.0f32);

    assert!(max(0u32, 1u32) == 1u32);
    assert!(max(-1.0f32, 0.0f32) == 0.0f32);
}

#[test]
fn test_translate() {
    let p = Rect(Point2D(0u32, 0u32), Size2D(50u32, 40u32));
    let pp = p.translate(&Point2D(10,15));

    assert!(pp.size.width == 50);
    assert!(pp.size.height == 40);
    assert!(pp.origin.x == 10);
    assert!(pp.origin.y == 15);

    let r = Rect(Point2D(-10i32, -5i32), Size2D(50i32, 40i32));
    let rr = r.translate(&Point2D(0,-10));

    assert!(rr.size.width == 50);
    assert!(rr.size.height == 40);
    assert!(rr.origin.x == -10);
    assert!(rr.origin.y == -15);
}

#[test]
fn test_union() {
    let p = Rect(Point2D(0i32, 0i32), Size2D(50i32, 40i32));
    let q = Rect(Point2D(20i32 ,20i32), Size2D(5i32, 5i32));
    let r = Rect(Point2D(-15i32, -30i32), Size2D(200i32, 15i32));
    let s = Rect(Point2D(20i32, -15i32), Size2D(250i32, 200i32));

    let pq = p.union(&q);
    assert!(pq.origin == Point2D(0, 0));
    assert!(pq.size == Size2D(50, 40));

    let pr = p.union(&r);
    assert!(pr.origin == Point2D(-15, -30));
    assert!(pr.size == Size2D(200, 70));

    let ps = p.union(&s);
    assert!(ps.origin == Point2D(0, -15));
    assert!(ps.size == Size2D(270, 200));

}

#[test]
fn test_intersection() {
    let p = Rect(Point2D(0i32, 0i32), Size2D(10i32, 20i32));
    let q = Rect(Point2D(5i32, 15i32), Size2D(10i32, 10i32));
    let r = Rect(Point2D(-5i32, -5i32), Size2D(8i32, 8i32));

    let pq = p.intersection(&q);
    assert!(pq.is_some());
    let pq = pq.unwrap();
    assert!(pq.origin == Point2D(5, 15));
    assert!(pq.size == Size2D(5, 5));

    let pr = p.intersection(&r);
    assert!(pr.is_some());
    let pr = pr.unwrap();
    assert!(pr.origin == Point2D(0, 0));
    assert!(pr.size == Size2D(3, 3));

    let qr = q.intersection(&r);
    assert!(qr.is_none());
}

#[test]
fn test_contains() {
    let r = Rect(Point2D(-20i32, 15i32), Size2D(100i32, 200i32));

    assert!(r.contains(&Point2D(0, 50)));
    assert!(r.contains(&Point2D(-10, 200)));

    // The `contains` method is inclusive of the top/left edges, but not the
    // bottom/right edges.
    assert!(r.contains(&Point2D(-20, 15)));
    assert!(!r.contains(&Point2D(80, 15)));
    assert!(!r.contains(&Point2D(80, 215)));
    assert!(!r.contains(&Point2D(-20, 215)));

    // Points beyond the top-left corner.
    assert!(!r.contains(&Point2D(-25, 15)));
    assert!(!r.contains(&Point2D(-15, 10)));

    // Points beyond the top-right corner.
    assert!(!r.contains(&Point2D(85, 20)));
    assert!(!r.contains(&Point2D(75, 10)));

    // Points beyond the bottom-right corner.
    assert!(!r.contains(&Point2D(85, 210)));
    assert!(!r.contains(&Point2D(75, 220)));

    // Points beyond the bottom-left corner.
    assert!(!r.contains(&Point2D(-25, 210)));
    assert!(!r.contains(&Point2D(-15, 220)));
}

#[test]
fn test_scale() {
    let p = Rect(Point2D(0u32, 0u32), Size2D(50u32, 40u32));
    let pp = p.scale(10, 15);

    assert!(pp.size.width == 500);
    assert!(pp.size.height == 600);
    assert!(pp.origin.x == 0);
    assert!(pp.origin.y == 0);

    let r = Rect(Point2D(-10i32, -5i32), Size2D(50i32, 40i32));
    let rr = r.scale(1, 20);

    assert!(rr.size.width == 50);
    assert!(rr.size.height == 800);
    assert!(rr.origin.x == -10);
    assert!(rr.origin.y == -100);
}

#[test]
fn test_inflate() {
    let p = Rect(Point2D(0i32, 0i32), Size2D(10i32, 10i32));
    let pp = p.inflate(10, 20);

    assert!(pp.size.width == 30);
    assert!(pp.size.height == 50);
    assert!(pp.origin.x == -10);
    assert!(pp.origin.y == -20);

    let r = Rect(Point2D(0i32, 0i32), Size2D(10i32, 20i32));
    let rr = r.inflate(-2, -5);

    assert!(rr.size.width == 6);
    assert!(rr.size.height == 10);
    assert!(rr.origin.x == 2);
    assert!(rr.origin.y == 5);
}

#[test]
fn test_min_max_x_y() {
    let p = Rect(Point2D(0u32, 0u32), Size2D(50u32, 40u32));
    assert!(p.max_y() == 40);
    assert!(p.min_y() == 0);
    assert!(p.max_x() == 50);
    assert!(p.min_x() == 0);

    let r = Rect(Point2D(-10i32, -5i32), Size2D(50i32, 40i32));
    assert!(r.max_y() == 35);
    assert!(r.min_y() == -5);
    assert!(r.max_x() == 40);
    assert!(r.min_x() == -10);
}
<|endoftext|>


<commit_before>// Copyright © 2015, Peter Atashian

/// An NX file header.
#[repr(packed)]
#[allow(dead_code)]
pub struct Header {
    pub magic: u32,
    pub nodecount: u32,
    pub nodeoffset: u64,
    pub stringcount: u32,
    pub stringoffset: u64,
    pub bitmapcount: u32,
    pub bitmapoffset: u64,
    pub audiocount: u32,
    pub audiooffset: u64,
}

/// The data contained by an NX node.
#[repr(packed)]
pub struct Node {
    pub name: u32,
    pub children: u32,
    pub count: u16,
    pub dtype: u16,
    pub data: u64,
}

/// The types of NX nodes.
#[repr(u16)]
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum Type {
    /// A node containing no data.
    Empty = 0,
    /// A node containing integer data.
    Integer = 1,
    /// A node containing floating-point data.
    Float = 2,
    /// A node containing string data.
    String = 3,
    /// A node containing vector (or point) data.
    Vector = 4,
    /// A node containing bitmap data.
    Bitmap = 5,
    /// A node containing audio data.
    Audio = 6,
}

#[repr(packed)]
pub struct Integer {
    pub value: i64,
}

#[repr(packed)]
pub struct Float {
    pub value: f64,
}

#[repr(packed)]
pub struct String {
    pub index: u32,
    pub _padding: u32,
}

#[repr(packed)]
pub struct Vector {
    pub x: i32,
    pub y: i32,
}

#[repr(packed)]
#[allow(dead_code)]
pub struct Bitmap {
    pub index: u32,
    pub width: u16,
    pub height: u16,
}

#[repr(packed)]
#[allow(dead_code)]
pub struct Audio {
    pub index: u32,
    pub length: u32,
}
<commit_msg>Add debug to node type<commit_after>// Copyright © 2015, Peter Atashian

/// An NX file header.
#[repr(packed)]
#[allow(dead_code)]
pub struct Header {
    pub magic: u32,
    pub nodecount: u32,
    pub nodeoffset: u64,
    pub stringcount: u32,
    pub stringoffset: u64,
    pub bitmapcount: u32,
    pub bitmapoffset: u64,
    pub audiocount: u32,
    pub audiooffset: u64,
}

/// The data contained by an NX node.
#[repr(packed)]
pub struct Node {
    pub name: u32,
    pub children: u32,
    pub count: u16,
    pub dtype: u16,
    pub data: u64,
}

/// The types of NX nodes.
#[repr(u16)]
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Type {
    /// A node containing no data.
    Empty = 0,
    /// A node containing integer data.
    Integer = 1,
    /// A node containing floating-point data.
    Float = 2,
    /// A node containing string data.
    String = 3,
    /// A node containing vector (or point) data.
    Vector = 4,
    /// A node containing bitmap data.
    Bitmap = 5,
    /// A node containing audio data.
    Audio = 6,
}

#[repr(packed)]
pub struct Integer {
    pub value: i64,
}

#[repr(packed)]
pub struct Float {
    pub value: f64,
}

#[repr(packed)]
pub struct String {
    pub index: u32,
    pub _padding: u32,
}

#[repr(packed)]
pub struct Vector {
    pub x: i32,
    pub y: i32,
}

#[repr(packed)]
#[allow(dead_code)]
pub struct Bitmap {
    pub index: u32,
    pub width: u16,
    pub height: u16,
}

#[repr(packed)]
#[allow(dead_code)]
pub struct Audio {
    pub index: u32,
    pub length: u32,
}
<|endoftext|>


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

use super::error::SBError;
use super::event::SBEvent;
use super::frame::SBFrame;
use super::process::SBProcess;
use super::queue::SBQueue;
use super::stream::SBStream;
use super::value::SBValue;
use super::{lldb_tid_t, StopReason};
use std::ffi::CStr;
use std::fmt;
use sys;

/// A thread of execution.
///
/// `SBThread`s can be referred to by their ID, which maps to the system
/// specific thread identifier, or by `IndexID`.  The ID may or may not
/// be unique depending on whether the system reuses its thread identifiers.
/// The `IndexID` is a monotonically increasing identifier that will always
/// uniquely reference a particular thread, and when that thread goes
/// away it will not be reused.
///
/// # Thread State
///
/// ...
///
/// # Execution Control
///
/// ...
///
/// # Frames
///
/// The thread contains [stack frames]. These can be iterated
/// over with [`frames`]:
///
/// ```no_run
/// # use lldb::{SBFrame, SBThread};
/// # fn look_at_frames(thread: SBThread) {
/// // Iterate over the frames...
/// for frame in thread.frames() {
///     println!("Hello {:?}!", frame);
/// }
/// // Or collect them into a vector!
/// let frames = thread.frames().collect::<Vec<SBFrame>>();
/// # }
/// ```
///
/// Some functions operate on the 'currently selected frame'. This can
/// retrieved via [`selected_frame`] and set via [`set_selected_frame`].
///
///
/// # Events
///
/// ...
///
/// [stack frames]: struct.SBFrame.html
/// [`frames`]: #method.frames
/// [`selected_frame`]: #method.selected_frame
/// [`set_selected_frame`]: #method.set_selected_frame
pub struct SBThread {
    /// The underlying raw `SBThreadRef`.
    pub raw: sys::SBThreadRef,
}

impl SBThread {
    /// Construct a new `Some(SBThread)` or `None`.
    pub fn maybe_wrap(raw: sys::SBThreadRef) -> Option<SBThread> {
        if unsafe { sys::SBThreadIsValid(raw) } {
            Some(SBThread { raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBThread` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBThreadIsValid(self.raw) }
    }

    #[allow(missing_docs)]
    pub fn broadcaster_class_name() -> &'static str {
        unsafe {
            match CStr::from_ptr(sys::SBThreadGetBroadcasterClassName()).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// Get the stop reason for this thread.
    pub fn stop_reason(&self) -> StopReason {
        unsafe { sys::SBThreadGetStopReason(self.raw) }
    }

    /// The return value from the last stop if we just stopped due
    /// to stepping out of a function
    pub fn stop_return_value(&self) -> Option<SBValue> {
        SBValue::maybe_wrap(unsafe { sys::SBThreadGetStopReturnValue(self.raw) })
    }

    /// Returns a unique thread identifier for the current `SBThread`
    /// that will remain constant throughout the thread's lifetime in
    /// this process and will not be reused by another thread during this
    /// process lifetime.  On Mac OS X systems, this is a system-wide
    /// unique thread identifier; this identifier is also used by
    /// other tools like sample which helps to associate data from
    /// those tools with lldb.  See related `SBThread::index_id`.
    pub fn thread_id(&self) -> lldb_tid_t {
        unsafe { sys::SBThreadGetThreadID(self.raw) }
    }

    /// Return the index number for this `SBThread`.  The index
    /// number is the same thing that a user gives as an argument
    /// to `thread select` in the command line lldb.
    ///
    /// These numbers start at `1` (for the first thread lldb sees
    /// in a debug session) and increments up throughout the process
    /// lifetime.  An index number will not be reused for a different
    /// thread later in a process - thread 1 will always be associated
    /// with the same thread.  See related `SBThread::thread_id`.
    pub fn index_id(&self) -> u32 {
        unsafe { sys::SBThreadGetIndexID(self.raw) }
    }

    /// The name associated with the thread, if any.
    pub fn name(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBThreadGetName(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// Return the queue associated with this thread, if any.
    ///
    /// If this `SBThread` is actually a history thread, then there may be
    /// a queue ID and name available, but not a full `SBQueue` as the
    /// individual attributes may have been saved, but without enough
    /// information to reconstitute the entire `SBQueue` at that time.
    pub fn queue(&self) -> Option<SBQueue> {
        SBQueue::maybe_wrap(unsafe { sys::SBThreadGetQueue(self.raw) })
    }

    /// Return the queue name associated with this thread, if any.
    ///
    /// For example, this would report a libdispatch (Grand Central Dispatch)
    /// queue name.
    pub fn queue_name(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBThreadGetQueueName(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// Return the `dispatch_queue_id` for this thread, if any.
    ///
    /// For example, this would report a libdispatch (Grand Central Dispatch)
    /// queue ID.
    pub fn queue_id(&self) -> u64 {
        unsafe { sys::SBThreadGetQueueID(self.raw) }
    }

    /// Set the user resume state for this thread to suspend.
    ///
    /// LLDB currently supports process centric debugging which means when any
    /// thread in a process stops, all other threads are stopped. The `suspend`
    /// call here tells our process to suspend a thread and not let it run when
    /// the other threads in a process are allowed to run. So when
    /// `SBProcess::continue()` is called, any threads that aren't suspended will
    /// be allowed to run. If any of the `SBThread` functions for stepping are
    /// called (`step_over`, `step_into`, `step_out`, `step_instruction`,
    /// `run_to_address`), the thread will not be allowed to run and these
    /// functions will simply return.
    pub fn suspend(&self) -> bool {
        let error: SBError = SBError::new();
        unsafe { sys::SBThreadSuspend(self.raw, error.raw) }
    }

    /// Set the user resume state for this to allow it to run again.
    ///
    /// See the discussion on `suspend` for further details.
    pub fn resume(&self) -> bool {
        let error: SBError = SBError::new();
        unsafe { sys::SBThreadResume(self.raw, error.raw) }
    }

    /// Is this thread set to the suspended user resume state?
    ///
    /// See the discussion on `suspend` for further details.
    pub fn is_suspended(&self) -> bool {
        unsafe { sys::SBThreadIsSuspended(self.raw) }
    }

    /// Is this thread stopped?
    pub fn is_stopped(&self) -> bool {
        unsafe { sys::SBThreadIsStopped(self.raw) }
    }

    /// Get an iterator over the [frames] known to this thread instance.
    ///
    /// [frames]: struct.SBFrame.html
    pub fn frames(&self) -> SBThreadFrameIter {
        SBThreadFrameIter {
            thread: self,
            idx: 0,
        }
    }

    /// Get the currently selected frame for this thread.
    pub fn selected_frame(&self) -> SBFrame {
        SBFrame::from(unsafe { sys::SBThreadGetSelectedFrame(self.raw) })
    }

    /// Set the currently selected frame for this thread. This takes a frame index.
    pub fn set_selected_frame(&self, frame_index: u32) -> Option<SBFrame> {
        SBFrame::maybe_wrap(unsafe { sys::SBThreadSetSelectedFrame(self.raw, frame_index) })
    }

    /// Get the process in which this thread is running.
    pub fn process(&self) -> SBProcess {
        SBProcess::from(unsafe { sys::SBThreadGetProcess(self.raw) })
    }

    /// If the given event is a thread event, return it as an
    /// `SBThreadEvent`. Otherwise, return `None`.
    pub fn event_as_thread_event(event: &SBEvent) -> Option<SBThreadEvent> {
        if unsafe { sys::SBThreadEventIsThreadEvent(event.raw) } {
            Some(SBThreadEvent::new(event))
        } else {
            None
        }
    }
}

/// Iterate over the [frames] in a [thread].
///
/// [frames]: struct.SBFrame.html
/// [thread]: struct.SBThread.html
pub struct SBThreadFrameIter<'d> {
    thread: &'d SBThread,
    idx: usize,
}

impl<'d> Iterator for SBThreadFrameIter<'d> {
    type Item = SBFrame;

    fn next(&mut self) -> Option<SBFrame> {
        if self.idx < unsafe { sys::SBThreadGetNumFrames(self.thread.raw) as usize } {
            let r = Some(SBFrame::from(unsafe {
                sys::SBThreadGetFrameAtIndex(self.thread.raw, self.idx as u32)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBThreadGetNumFrames(self.thread.raw) } as usize;
        (sz - self.idx, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBThreadFrameIter<'d> {}

impl Clone for SBThread {
    fn clone(&self) -> SBThread {
        SBThread {
            raw: unsafe { sys::CloneSBThread(self.raw) },
        }
    }
}

impl fmt::Debug for SBThread {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBThreadGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBThread {{ {} }}", stream.data())
    }
}

impl Drop for SBThread {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBThread(self.raw) };
    }
}

impl From<sys::SBThreadRef> for SBThread {
    fn from(raw: sys::SBThreadRef) -> SBThread {
        SBThread { raw }
    }
}

unsafe impl Send for SBThread {}
unsafe impl Sync for SBThread {}

/// A thread event.
pub struct SBThreadEvent<'e> {
    event: &'e SBEvent,
}

impl<'e> SBThreadEvent<'e> {
    /// Construct a new `SBThreadEvent`.
    pub fn new(event: &'e SBEvent) -> Self {
        SBThreadEvent { event }
    }

    /// Get the thread from this thread event.
    pub fn thread(&self) -> SBThread {
        SBThread::from(unsafe { sys::SBThreadGetThreadFromEvent(self.event.raw) })
    }

    /// Get the frame from this thread event.
    pub fn frame(&self) -> Option<SBFrame> {
        SBFrame::maybe_wrap(unsafe { sys::SBThreadGetStackFrameFromEvent(self.event.raw) })
    }
}

#[cfg(feature = "graphql")]
graphql_object!(SBThread: super::debugger::SBDebugger | &self | {
    field is_valid() -> bool {
        self.is_valid()
    }

    // TODO(bm): This should be u64
    field thread_id() -> i32 {
        self.thread_id() as i32
    }

    // TODO(bm) This should be u32
    field index_id() -> i32 {
        self.index_id() as i32
    }

    field frames() -> Vec<SBFrame> {
        self.frames().collect()
    }

    field selected_frame() -> SBFrame {
        self.selected_frame()
    }

    field process() -> SBProcess {
        self.process()
    }
});
<commit_msg>Improve SBThread doc linking.<commit_after>// 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.

use super::error::SBError;
use super::event::SBEvent;
use super::frame::SBFrame;
use super::process::SBProcess;
use super::queue::SBQueue;
use super::stream::SBStream;
use super::value::SBValue;
use super::{lldb_tid_t, StopReason};
use std::ffi::CStr;
use std::fmt;
use sys;

/// A thread of execution.
///
/// `SBThread`s can be referred to by their ID, which maps to the system
/// specific thread identifier, or by `IndexID`.  The ID may or may not
/// be unique depending on whether the system reuses its thread identifiers.
/// The `IndexID` is a monotonically increasing identifier that will always
/// uniquely reference a particular thread, and when that thread goes
/// away it will not be reused.
///
/// # Thread State
///
/// ...
///
/// # Execution Control
///
/// ...
///
/// # Frames
///
/// The thread contains [stack frames]. These can be iterated
/// over with [`frames`]:
///
/// ```no_run
/// # use lldb::{SBFrame, SBThread};
/// # fn look_at_frames(thread: SBThread) {
/// // Iterate over the frames...
/// for frame in thread.frames() {
///     println!("Hello {:?}!", frame);
/// }
/// // Or collect them into a vector!
/// let frames = thread.frames().collect::<Vec<SBFrame>>();
/// # }
/// ```
///
/// Some functions operate on the 'currently selected frame'. This can
/// retrieved via [`selected_frame`] and set via [`set_selected_frame`].
///
///
/// # Events
///
/// ...
///
/// [stack frames]: struct.SBFrame.html
/// [`frames`]: #method.frames
/// [`selected_frame`]: #method.selected_frame
/// [`set_selected_frame`]: #method.set_selected_frame
pub struct SBThread {
    /// The underlying raw `SBThreadRef`.
    pub raw: sys::SBThreadRef,
}

impl SBThread {
    /// Construct a new `Some(SBThread)` or `None`.
    pub fn maybe_wrap(raw: sys::SBThreadRef) -> Option<SBThread> {
        if unsafe { sys::SBThreadIsValid(raw) } {
            Some(SBThread { raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBThread` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBThreadIsValid(self.raw) }
    }

    #[allow(missing_docs)]
    pub fn broadcaster_class_name() -> &'static str {
        unsafe {
            match CStr::from_ptr(sys::SBThreadGetBroadcasterClassName()).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// Get the stop reason for this thread.
    pub fn stop_reason(&self) -> StopReason {
        unsafe { sys::SBThreadGetStopReason(self.raw) }
    }

    /// The return value from the last stop if we just stopped due
    /// to stepping out of a function
    pub fn stop_return_value(&self) -> Option<SBValue> {
        SBValue::maybe_wrap(unsafe { sys::SBThreadGetStopReturnValue(self.raw) })
    }

    /// Returns a unique thread identifier for the current `SBThread`
    /// that will remain constant throughout the thread's lifetime in
    /// this process and will not be reused by another thread during this
    /// process lifetime.  On Mac OS X systems, this is a system-wide
    /// unique thread identifier; this identifier is also used by
    /// other tools like sample which helps to associate data from
    /// those tools with lldb.  See related [`SBThread::index_id`].
    pub fn thread_id(&self) -> lldb_tid_t {
        unsafe { sys::SBThreadGetThreadID(self.raw) }
    }

    /// Return the index number for this `SBThread`.  The index
    /// number is the same thing that a user gives as an argument
    /// to `thread select` in the command line lldb.
    ///
    /// These numbers start at `1` (for the first thread lldb sees
    /// in a debug session) and increments up throughout the process
    /// lifetime.  An index number will not be reused for a different
    /// thread later in a process - thread 1 will always be associated
    /// with the same thread.  See related [`SBThread::thread_id`].
    pub fn index_id(&self) -> u32 {
        unsafe { sys::SBThreadGetIndexID(self.raw) }
    }

    /// The name associated with the thread, if any.
    pub fn name(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBThreadGetName(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// Return the queue associated with this thread, if any.
    ///
    /// If this `SBThread` is actually a history thread, then there may be
    /// a queue ID and name available, but not a full [`SBQueue`] as the
    /// individual attributes may have been saved, but without enough
    /// information to reconstitute the entire `SBQueue` at that time.
    pub fn queue(&self) -> Option<SBQueue> {
        SBQueue::maybe_wrap(unsafe { sys::SBThreadGetQueue(self.raw) })
    }

    /// Return the queue name associated with this thread, if any.
    ///
    /// For example, this would report a `libdispatch` (Grand Central Dispatch)
    /// queue name.
    pub fn queue_name(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBThreadGetQueueName(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// Return the `dispatch_queue_id` for this thread, if any.
    ///
    /// For example, this would report a `libdispatch` (Grand Central Dispatch)
    /// queue ID.
    pub fn queue_id(&self) -> u64 {
        unsafe { sys::SBThreadGetQueueID(self.raw) }
    }

    /// Set the user resume state for this thread to suspend.
    ///
    /// LLDB currently supports process centric debugging which means when any
    /// thread in a process stops, all other threads are stopped. The `suspend`
    /// call here tells our process to suspend a thread and not let it run when
    /// the other threads in a process are allowed to run. So when
    /// [`SBProcess::continue_execution()`] is called, any threads that
    /// aren't suspended will be allowed to run. If any of the `SBThread`
    /// functions for stepping are called (`step_over`, `step_into`,
    /// `step_out`, `step_instruction`, `run_to_address`), the thread will
    /// not be allowed to run and these functions will simply return.
    pub fn suspend(&self) -> bool {
        let error: SBError = SBError::new();
        unsafe { sys::SBThreadSuspend(self.raw, error.raw) }
    }

    /// Set the user resume state for this to allow it to run again.
    ///
    /// See the discussion on [`SBThread::suspend()`] for further details.
    pub fn resume(&self) -> bool {
        let error: SBError = SBError::new();
        unsafe { sys::SBThreadResume(self.raw, error.raw) }
    }

    /// Is this thread set to the suspended user resume state?
    ///
    /// See the discussion on [`SBThread::suspend()`] for further details.
    pub fn is_suspended(&self) -> bool {
        unsafe { sys::SBThreadIsSuspended(self.raw) }
    }

    /// Is this thread stopped?
    pub fn is_stopped(&self) -> bool {
        unsafe { sys::SBThreadIsStopped(self.raw) }
    }

    /// Get an iterator over the [frames] known to this thread instance.
    ///
    /// [frames]: struct.SBFrame.html
    pub fn frames(&self) -> SBThreadFrameIter {
        SBThreadFrameIter {
            thread: self,
            idx: 0,
        }
    }

    /// Get the currently selected frame for this thread.
    pub fn selected_frame(&self) -> SBFrame {
        SBFrame::from(unsafe { sys::SBThreadGetSelectedFrame(self.raw) })
    }

    /// Set the currently selected frame for this thread. This takes a frame index.
    pub fn set_selected_frame(&self, frame_index: u32) -> Option<SBFrame> {
        SBFrame::maybe_wrap(unsafe { sys::SBThreadSetSelectedFrame(self.raw, frame_index) })
    }

    /// Get the process in which this thread is running.
    pub fn process(&self) -> SBProcess {
        SBProcess::from(unsafe { sys::SBThreadGetProcess(self.raw) })
    }

    /// If the given event is a thread event, return it as an
    /// `SBThreadEvent`. Otherwise, return `None`.
    pub fn event_as_thread_event(event: &SBEvent) -> Option<SBThreadEvent> {
        if unsafe { sys::SBThreadEventIsThreadEvent(event.raw) } {
            Some(SBThreadEvent::new(event))
        } else {
            None
        }
    }
}

/// Iterate over the [frames] in a [thread].
///
/// [frames]: struct.SBFrame.html
/// [thread]: struct.SBThread.html
pub struct SBThreadFrameIter<'d> {
    thread: &'d SBThread,
    idx: usize,
}

impl<'d> Iterator for SBThreadFrameIter<'d> {
    type Item = SBFrame;

    fn next(&mut self) -> Option<SBFrame> {
        if self.idx < unsafe { sys::SBThreadGetNumFrames(self.thread.raw) as usize } {
            let r = Some(SBFrame::from(unsafe {
                sys::SBThreadGetFrameAtIndex(self.thread.raw, self.idx as u32)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBThreadGetNumFrames(self.thread.raw) } as usize;
        (sz - self.idx, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBThreadFrameIter<'d> {}

impl Clone for SBThread {
    fn clone(&self) -> SBThread {
        SBThread {
            raw: unsafe { sys::CloneSBThread(self.raw) },
        }
    }
}

impl fmt::Debug for SBThread {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBThreadGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBThread {{ {} }}", stream.data())
    }
}

impl Drop for SBThread {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBThread(self.raw) };
    }
}

impl From<sys::SBThreadRef> for SBThread {
    fn from(raw: sys::SBThreadRef) -> SBThread {
        SBThread { raw }
    }
}

unsafe impl Send for SBThread {}
unsafe impl Sync for SBThread {}

/// A thread event.
pub struct SBThreadEvent<'e> {
    event: &'e SBEvent,
}

impl<'e> SBThreadEvent<'e> {
    /// Construct a new `SBThreadEvent`.
    pub fn new(event: &'e SBEvent) -> Self {
        SBThreadEvent { event }
    }

    /// Get the thread from this thread event.
    pub fn thread(&self) -> SBThread {
        SBThread::from(unsafe { sys::SBThreadGetThreadFromEvent(self.event.raw) })
    }

    /// Get the frame from this thread event.
    pub fn frame(&self) -> Option<SBFrame> {
        SBFrame::maybe_wrap(unsafe { sys::SBThreadGetStackFrameFromEvent(self.event.raw) })
    }
}

#[cfg(feature = "graphql")]
graphql_object!(SBThread: super::debugger::SBDebugger | &self | {
    field is_valid() -> bool {
        self.is_valid()
    }

    // TODO(bm): This should be u64
    field thread_id() -> i32 {
        self.thread_id() as i32
    }

    // TODO(bm) This should be u32
    field index_id() -> i32 {
        self.index_id() as i32
    }

    field frames() -> Vec<SBFrame> {
        self.frames().collect()
    }

    field selected_frame() -> SBFrame {
        self.selected_frame()
    }

    field process() -> SBProcess {
        self.process()
    }
});
<|endoftext|>


<commit_before>use std::ptr::null;
use libc::{c_int, c_char, c_double};
use std::ffi::CString;
use std::sync::{StaticMutex, MUTEX_INIT};
use utils::_string;

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *const c_char, bUpdate: c_int, pahDriverList: *const ()) -> *const ();
    fn OGR_DS_GetLayerCount(hDS: *const ()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *const ());
    fn OGR_DS_GetLayer(hDS: *const (), iLayer: c_int) -> *const ();
    fn OGR_L_GetLayerDefn(hLayer: *const ()) -> *const ();
    fn OGR_L_GetNextFeature(hLayer: *const ()) -> *const ();
    fn OGR_FD_GetFieldCount(hDefn: *const ()) -> c_int;
    fn OGR_FD_GetFieldDefn(hDefn: *const (), iField: c_int) -> *const ();
    fn OGR_F_GetFieldIndex(hFeat: *const (), pszName: *const c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *const (), i: c_int) -> *const ();
    fn OGR_F_GetFieldAsString(hFeat: *const (), iField: c_int) -> *const c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *const (), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *const ()) -> *const ();
    fn OGR_F_Destroy(hFeat: *const ());
    fn OGR_G_ExportToWkt(hGeom: *const (), ppszSrcText: *const *const c_char) -> c_int;
    fn OGR_G_ExportToJson(hGeometry: *const ()) -> *const c_char;
    fn OGR_Fld_GetNameRef(hDefn: *const ()) -> *const c_char;
    fn OGR_Fld_GetType(hDefn: *const ()) -> c_int;
    fn OGRFree(ptr: *const ());
    fn VSIFree(ptr: *const ());
}

const OFT_REAL:             c_int = 2;
const OFT_STRING:           c_int = 4;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *const (),
}

impl VectorDataset {
    pub fn count(&self) -> isize {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as isize;
    }

    pub fn layer<'a>(&'a self, idx: isize) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{_vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    _vector_dataset: &'a VectorDataset,
    c_layer: *const (),
}

impl<'a> Layer<'a> {
    pub fn fields(&'a self) -> FieldIterator<'a> {
        let c_feature_defn = unsafe { OGR_L_GetLayerDefn(self.c_layer) };
        let total = unsafe { OGR_FD_GetFieldCount(c_feature_defn) } as isize;
        return FieldIterator{
            layer: self,
            c_feature_defn: c_feature_defn,
            next_id: 0,
            total: total
        };
    }

    pub fn features(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FieldIterator<'a> {
    layer: &'a Layer<'a>,
    c_feature_defn: *const (),
    next_id: isize,
    total: isize,
}

impl<'a> Iterator for FieldIterator<'a> {
    type Item = Field<'a>;

    #[inline]
    fn next(&mut self) -> Option<Field<'a>> {
        if self.next_id == self.total {
            return None;
        }
        let field = Field{
            _layer: self.layer,
            c_field_defn: unsafe { OGR_FD_GetFieldDefn(
                self.c_feature_defn,
                self.next_id as c_int
            ) }
        };
        self.next_id += 1;
        return Some(field);
    }
}

pub struct Field<'a> {
    _layer: &'a Layer<'a>,
    c_field_defn: *const (),
}

impl<'a> Field<'a> {
    pub fn name(&'a self) -> String {
        let rv = unsafe { OGR_Fld_GetNameRef(self.c_field_defn) };
        return _string(rv);
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator for FeatureIterator<'a> {
    type Item = Feature<'a>;

    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{_layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    _layer: &'a Layer<'a>,
    c_feature: *const (),
}

impl<'a> Feature<'a> {
    pub fn field(&self, name: &str) -> Option<FieldValue> {
        let c_name = CString::from_slice(name.as_bytes());
        let field_id = unsafe { OGR_F_GetFieldIndex(self.c_feature, c_name.as_ptr()) };
        if field_id == -1 {
            return None;
        }
        let field_defn = unsafe { OGR_F_GetFieldDefnRef(self.c_feature, field_id) };
        let field_type = unsafe { OGR_Fld_GetType(field_defn) };
        return match field_type {
            OFT_STRING => {
                let rv = unsafe { OGR_F_GetFieldAsString(self.c_feature, field_id) };
                return Some(FieldValue::StringValue(_string(rv)));
            },
            OFT_REAL => {
                let rv = unsafe { OGR_F_GetFieldAsDouble(self.c_feature, field_id) };
                return Some(FieldValue::RealValue(rv as f64));
            },
            _ => panic!("Unknown field type {}", field_type)
        }
    }

    pub fn wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *const c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = _string(c_wkt);
            OGRFree(c_wkt as *const ());
            return wkt;
        }
    }

    pub fn json(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_json = OGR_G_ExportToJson(c_geom);
            let json = _string(c_json);
            VSIFree(c_json as *const ());
            return json;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_filename = CString::from_slice(filename.as_bytes());
    let c_dataset = unsafe { OGROpen(c_filename.as_ptr(), 0, null()) };
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

pub enum FieldValue {
    StringValue(String),
    RealValue(f64),
}

impl FieldValue {
    pub fn as_string(self) -> String {
        match self {
            FieldValue::StringValue(rv) => rv,
            _ => panic!("not a StringValue")
        }
    }

    pub fn as_real(self) -> f64 {
        match self {
            FieldValue::RealValue(rv) => rv,
            _ => panic!("not a RealValue")
        }
    }
}

#[cfg(test)]
mod test {
    use std::path::Path;
    use super::{Feature, FeatureIterator, open};

    fn fixtures() -> Path {
        return Path::new(file!()).dir_path().dir_path().join("fixtures");
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixtures().join("roads.geojson")).unwrap();
        assert_eq!(ds.count(), 1);
    }

    fn with_features<F>(fixture: &str, f: F) where F: Fn(FeatureIterator) {
        let ds = open(&fixtures().join(fixture)).unwrap();
        let layer = ds.layer(0).unwrap();
        f(layer.features());
    }

    fn with_first_feature<F>(fixture: &str, f: F) where F: Fn(Feature) {
        with_features(fixture, |mut features| f(features.next().unwrap()));
    }

    #[test]
    fn test_iterate_features() {
        with_features("roads.geojson", |features| {
            let feature_vec: Vec<Feature> = features.collect();
            assert_eq!(feature_vec.len(), 21);
        });
    }

    #[test]
    fn test_string_field() {
        with_features("roads.geojson", |mut features| {
            let feature = features.next().unwrap();
            assert_eq!(feature.field("highway")
                              .unwrap()
                              .as_string(),
                       "footway".to_string());
            assert_eq!(
                features.filter(|field| {
                    let highway = field.field("highway")
                                       .unwrap()
                                       .as_string();
                    highway == "residential".to_string() })
                    .count(),
                2);
        });
    }

    #[test]
    fn test_float_field() {
        with_first_feature("roads.geojson", |feature| {
            assert_almost_eq(
                feature.field("sort_key")
                       .unwrap()
                       .as_real(),
                -9.0
            );
        });
    }

    #[test]
    fn test_missing_field() {
        with_first_feature("roads.geojson", |feature| {
            assert!(feature.field("no such field").is_none());
        });
    }

    #[test]
    fn test_wkt() {
        with_first_feature("roads.geojson", |feature| {
            let wkt = feature.wkt();
            let wkt_ok = format!("{}{}",
                "LINESTRING (26.1019276 44.4302748,",
                "26.1019382 44.4303191,26.1020002 44.4304202)"
                ).to_string();
            assert_eq!(wkt, wkt_ok);
        });
    }

    #[test]
    fn test_json() {
        with_first_feature("roads.geojson", |feature| {
            let json = feature.json();
            let json_ok = format!("{}{}{}{}",
                "{ \"type\": \"LineString\", \"coordinates\": [ ",
                "[ 26.1019276, 44.4302748 ], ",
                "[ 26.1019382, 44.4303191 ], ",
                "[ 26.1020002, 44.4304202 ] ] }"
                ).to_string();
            assert_eq!(json, json_ok);
        });
    }

    #[test]
    fn test_schema() {
        let ds = open(&fixtures().join("roads.geojson")).unwrap();
        let layer = ds.layer(0).unwrap();
        let name_list: Vec<String> = layer
            .fields()
            .map(|f| f.name())
            .collect();
        let ok_names: Vec<String> = vec!(
            "kind", "sort_key", "is_link", "is_tunnel",
            "is_bridge", "railway", "highway")
            .iter().map(|s| s.to_string()).collect();
        assert_eq!(name_list, ok_names);
    }
}
<commit_msg>OGR_G_ExportToWkt expects a mutable pointer<commit_after>use std::ptr::null;
use libc::{c_int, c_char, c_double};
use std::ffi::CString;
use std::sync::{StaticMutex, MUTEX_INIT};
use utils::_string;

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *const c_char, bUpdate: c_int, pahDriverList: *const ()) -> *const ();
    fn OGR_DS_GetLayerCount(hDS: *const ()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *const ());
    fn OGR_DS_GetLayer(hDS: *const (), iLayer: c_int) -> *const ();
    fn OGR_L_GetLayerDefn(hLayer: *const ()) -> *const ();
    fn OGR_L_GetNextFeature(hLayer: *const ()) -> *const ();
    fn OGR_FD_GetFieldCount(hDefn: *const ()) -> c_int;
    fn OGR_FD_GetFieldDefn(hDefn: *const (), iField: c_int) -> *const ();
    fn OGR_F_GetFieldIndex(hFeat: *const (), pszName: *const c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *const (), i: c_int) -> *const ();
    fn OGR_F_GetFieldAsString(hFeat: *const (), iField: c_int) -> *const c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *const (), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *const ()) -> *const ();
    fn OGR_F_Destroy(hFeat: *const ());
    fn OGR_G_ExportToWkt(hGeom: *const (), ppszSrcText: &mut *const c_char) -> c_int;
    fn OGR_G_ExportToJson(hGeometry: *const ()) -> *const c_char;
    fn OGR_Fld_GetNameRef(hDefn: *const ()) -> *const c_char;
    fn OGR_Fld_GetType(hDefn: *const ()) -> c_int;
    fn OGRFree(ptr: *const ());
    fn VSIFree(ptr: *const ());
}

const OFT_REAL:             c_int = 2;
const OFT_STRING:           c_int = 4;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *const (),
}

impl VectorDataset {
    pub fn count(&self) -> isize {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as isize;
    }

    pub fn layer<'a>(&'a self, idx: isize) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{_vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    _vector_dataset: &'a VectorDataset,
    c_layer: *const (),
}

impl<'a> Layer<'a> {
    pub fn fields(&'a self) -> FieldIterator<'a> {
        let c_feature_defn = unsafe { OGR_L_GetLayerDefn(self.c_layer) };
        let total = unsafe { OGR_FD_GetFieldCount(c_feature_defn) } as isize;
        return FieldIterator{
            layer: self,
            c_feature_defn: c_feature_defn,
            next_id: 0,
            total: total
        };
    }

    pub fn features(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FieldIterator<'a> {
    layer: &'a Layer<'a>,
    c_feature_defn: *const (),
    next_id: isize,
    total: isize,
}

impl<'a> Iterator for FieldIterator<'a> {
    type Item = Field<'a>;

    #[inline]
    fn next(&mut self) -> Option<Field<'a>> {
        if self.next_id == self.total {
            return None;
        }
        let field = Field{
            _layer: self.layer,
            c_field_defn: unsafe { OGR_FD_GetFieldDefn(
                self.c_feature_defn,
                self.next_id as c_int
            ) }
        };
        self.next_id += 1;
        return Some(field);
    }
}

pub struct Field<'a> {
    _layer: &'a Layer<'a>,
    c_field_defn: *const (),
}

impl<'a> Field<'a> {
    pub fn name(&'a self) -> String {
        let rv = unsafe { OGR_Fld_GetNameRef(self.c_field_defn) };
        return _string(rv);
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator for FeatureIterator<'a> {
    type Item = Feature<'a>;

    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{_layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    _layer: &'a Layer<'a>,
    c_feature: *const (),
}

impl<'a> Feature<'a> {
    pub fn field(&self, name: &str) -> Option<FieldValue> {
        let c_name = CString::from_slice(name.as_bytes());
        let field_id = unsafe { OGR_F_GetFieldIndex(self.c_feature, c_name.as_ptr()) };
        if field_id == -1 {
            return None;
        }
        let field_defn = unsafe { OGR_F_GetFieldDefnRef(self.c_feature, field_id) };
        let field_type = unsafe { OGR_Fld_GetType(field_defn) };
        return match field_type {
            OFT_STRING => {
                let rv = unsafe { OGR_F_GetFieldAsString(self.c_feature, field_id) };
                return Some(FieldValue::StringValue(_string(rv)));
            },
            OFT_REAL => {
                let rv = unsafe { OGR_F_GetFieldAsDouble(self.c_feature, field_id) };
                return Some(FieldValue::RealValue(rv as f64));
            },
            _ => panic!("Unknown field type {}", field_type)
        }
    }

    pub fn wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let mut c_wkt: *const c_char = null();
            OGR_G_ExportToWkt(c_geom, &mut c_wkt);
            let wkt = _string(c_wkt);
            OGRFree(c_wkt as *const ());
            return wkt;
        }
    }

    pub fn json(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_json = OGR_G_ExportToJson(c_geom);
            let json = _string(c_json);
            VSIFree(c_json as *const ());
            return json;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_filename = CString::from_slice(filename.as_bytes());
    let c_dataset = unsafe { OGROpen(c_filename.as_ptr(), 0, null()) };
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

pub enum FieldValue {
    StringValue(String),
    RealValue(f64),
}

impl FieldValue {
    pub fn as_string(self) -> String {
        match self {
            FieldValue::StringValue(rv) => rv,
            _ => panic!("not a StringValue")
        }
    }

    pub fn as_real(self) -> f64 {
        match self {
            FieldValue::RealValue(rv) => rv,
            _ => panic!("not a RealValue")
        }
    }
}

#[cfg(test)]
mod test {
    use std::path::Path;
    use super::{Feature, FeatureIterator, open};

    fn fixtures() -> Path {
        return Path::new(file!()).dir_path().dir_path().join("fixtures");
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixtures().join("roads.geojson")).unwrap();
        assert_eq!(ds.count(), 1);
    }

    fn with_features<F>(fixture: &str, f: F) where F: Fn(FeatureIterator) {
        let ds = open(&fixtures().join(fixture)).unwrap();
        let layer = ds.layer(0).unwrap();
        f(layer.features());
    }

    fn with_first_feature<F>(fixture: &str, f: F) where F: Fn(Feature) {
        with_features(fixture, |mut features| f(features.next().unwrap()));
    }

    #[test]
    fn test_iterate_features() {
        with_features("roads.geojson", |features| {
            let feature_vec: Vec<Feature> = features.collect();
            assert_eq!(feature_vec.len(), 21);
        });
    }

    #[test]
    fn test_string_field() {
        with_features("roads.geojson", |mut features| {
            let feature = features.next().unwrap();
            assert_eq!(feature.field("highway")
                              .unwrap()
                              .as_string(),
                       "footway".to_string());
            assert_eq!(
                features.filter(|field| {
                    let highway = field.field("highway")
                                       .unwrap()
                                       .as_string();
                    highway == "residential".to_string() })
                    .count(),
                2);
        });
    }

    #[test]
    fn test_float_field() {
        with_first_feature("roads.geojson", |feature| {
            assert_almost_eq(
                feature.field("sort_key")
                       .unwrap()
                       .as_real(),
                -9.0
            );
        });
    }

    #[test]
    fn test_missing_field() {
        with_first_feature("roads.geojson", |feature| {
            assert!(feature.field("no such field").is_none());
        });
    }

    #[test]
    fn test_wkt() {
        with_first_feature("roads.geojson", |feature| {
            let wkt = feature.wkt();
            let wkt_ok = format!("{}{}",
                "LINESTRING (26.1019276 44.4302748,",
                "26.1019382 44.4303191,26.1020002 44.4304202)"
                ).to_string();
            assert_eq!(wkt, wkt_ok);
        });
    }

    #[test]
    fn test_json() {
        with_first_feature("roads.geojson", |feature| {
            let json = feature.json();
            let json_ok = format!("{}{}{}{}",
                "{ \"type\": \"LineString\", \"coordinates\": [ ",
                "[ 26.1019276, 44.4302748 ], ",
                "[ 26.1019382, 44.4303191 ], ",
                "[ 26.1020002, 44.4304202 ] ] }"
                ).to_string();
            assert_eq!(json, json_ok);
        });
    }

    #[test]
    fn test_schema() {
        let ds = open(&fixtures().join("roads.geojson")).unwrap();
        let layer = ds.layer(0).unwrap();
        let name_list: Vec<String> = layer
            .fields()
            .map(|f| f.name())
            .collect();
        let ok_names: Vec<String> = vec!(
            "kind", "sort_key", "is_link", "is_tunnel",
            "is_bridge", "railway", "highway")
            .iter().map(|s| s.to_string()).collect();
        assert_eq!(name_list, ok_names);
    }
}
<|endoftext|>