<commit_before>//!A raytracer.
#![feature(core, old_path, old_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,
    reflection: Reflection,
    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,
            reflection: self.reflection,
            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>>;
}

#[derive(Copy)]
struct Material {
    reflection: Reflection,
    emitted_radiance: f32
}

#[derive(Copy)]
enum Reflection {
    Diffuse,
    Specular
}

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

#[derive(Copy)]
enum SphereSource {
    Inside,
    Outside
}

impl Scene for Sphere {
    type ObjectId = SphereSource;
    fn intersect(&self, ray: Ray3, previous: Option<SphereSource>) -> Option<Intersection<SphereSource>> {
        if let Some(SphereSource::Outside) = 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. {
            return None;
        }

        let time = {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if previous.is_none() && t1 > 0. {
                t1
            } else if t2 > 0. {
                t2
            } else {
                return None;
            }
        };

        let p = ray.start + ray.dir * time;
        let normal = p - self.center;
        Some(Intersection {
            time: time,
            point: p,
            normal: normal,
            emitted: self.material.emitted_radiance,
            reflection: self.material.reflection,
            object: match previous {
                None => SphereSource::Outside,
                Some(source) => source
            }
        })
    }
}

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,
                    reflection: self.material.reflection,
                    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 = 200;
    let scene: (&[Sphere], &[Plane]) = (
        &[Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.0, 2.5, 0.5),
            radius: 1.0,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 20. }
        },
        Sphere {
            center: Point3::new(-1.5, 0.0, 3.5),
            radius: 1.0,
            material: Material { reflection: Reflection::Specular, emitted_radiance: 0. }
        }],
        &[Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 2.0, 0.0),
            normal: Vec3::new(0.0, -1.0, 0.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, -3.0, 0.0),
            normal: Vec3::new(0.0, 1.0, 0.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, -10.0),
            normal: Vec3::new(0.0, 0.0, 1.0),
            material: Material { reflection: Reflection::Diffuse, 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;

                    ray = match intersection.reflection {
                        Reflection::Specular => {
                            let projected = intersection.normal * ray.dir.dot(intersection.normal) / intersection.normal.mag2();
                            let new_dir = -ray.dir - projected * 2.;
                            Ray3 {
                                start: intersection.point,
                                dir: new_dir
                            }
                        },
                        Reflection::Diffuse => {
                            let cand_dir = rand_sphere(&mut rng);
                            let dir = if cand_dir.dot(intersection.normal) < 0. {
                                -cand_dir
                            } else {
                                cand_dir
                            };

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

                            Ray3 {
                                start: intersection.point,
                                dir: dir
                            }
                        }
                    }
                } 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>Parallelize!<commit_after>//!A raytracer.
#![feature(core, os, old_path, old_io)]
extern crate image;
extern crate rand;

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

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,
    reflection: Reflection,
    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,
            reflection: self.reflection,
            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>>;
}

#[derive(Copy)]
struct Material {
    reflection: Reflection,
    emitted_radiance: f32
}

#[derive(Copy)]
enum Reflection {
    Diffuse,
    Specular
}

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

#[derive(Copy)]
enum SphereSource {
    Inside,
    Outside
}

impl Scene for Sphere {
    type ObjectId = SphereSource;
    fn intersect(&self, ray: Ray3, previous: Option<SphereSource>) -> Option<Intersection<SphereSource>> {
        if let Some(SphereSource::Outside) = 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. {
            return None;
        }

        let time = {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if previous.is_none() && t1 > 0. {
                t1
            } else if t2 > 0. {
                t2
            } else {
                return None;
            }
        };

        let p = ray.start + ray.dir * time;
        let normal = p - self.center;
        Some(Intersection {
            time: time,
            point: p,
            normal: normal,
            emitted: self.material.emitted_radiance,
            reflection: self.material.reflection,
            object: match previous {
                None => SphereSource::Outside,
                Some(source) => source
            }
        })
    }
}

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,
                    reflection: self.material.reflection,
                    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 rays_per_pixel = 200;
    let scene: (&[Sphere], &[Plane]) = (
        &[Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.0, 2.5, 0.5),
            radius: 1.0,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 20. }
        },
        Sphere {
            center: Point3::new(-1.5, 0.0, 3.5),
            radius: 1.0,
            material: Material { reflection: Reflection::Specular, emitted_radiance: 0. }
        }],
        &[Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 2.0, 0.0),
            normal: Vec3::new(0.0, -1.0, 0.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, -3.0, 0.0),
            normal: Vec3::new(0.0, 1.0, 0.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, -10.0),
            normal: Vec3::new(0.0, 0.0, 1.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        }]
    );

    let num_threads = os::num_cpus();

    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::<image::Luma<u8>>::new(imgx, imgy);

    // Iterate over the pixels in parallel
    {
        let mut img_data = imgbuf.as_mut_slice();
        let chunk_size = img_data.len() / num_threads + 1;
        img_data.chunks_mut(chunk_size).enumerate().map(|(chunk_i, chunk)| {
            thread::scoped(move || {
                let mut rng = rand::weak_rng();

                let base = (chunk_i * chunk_size) as u32;
                let mut x = base % imgx;
                let mut y = base / imgx;
                for pixel in chunk.iter_mut() {
                    x += 1;
                    if x == imgx {
                        x = 0;
                        y += 1;
                    }
        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;

                    ray = match intersection.reflection {
                        Reflection::Specular => {
                            let projected = intersection.normal * ray.dir.dot(intersection.normal) / intersection.normal.mag2();
                            let new_dir = -ray.dir - projected * 2.;
                            Ray3 {
                                start: intersection.point,
                                dir: new_dir
                            }
                        },
                        Reflection::Diffuse => {
                            let cand_dir = rand_sphere(&mut rng);
                            let dir = if cand_dir.dot(intersection.normal) < 0. {
                                -cand_dir
                            } else {
                                cand_dir
                            };

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

                            Ray3 {
                                start: intersection.point,
                                dir: dir
                            }
                        }
                    }
                } else {
                    break;
                }
            }
        }

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

    // 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>#![cfg(test)]
use eth2_libp2p::*;
use futures::prelude::*;
use slog::{debug, Level};

mod common;

/* Gossipsub tests */
// Note: The aim of these tests is not to test the robustness of the gossip network
// but to check if the gossipsub implementation is behaving according to the specifications.

// Test if gossipsub message are forwarded by nodes with a simple linear topology.
//
//                Topology used in test
//
// node1 <-> node2 <-> node3 ..... <-> node(n-1) <-> node(n)

#[test]
fn test_gossipsub_forward() {
    // set up the logging. The level and enabled or not
    let log = common::build_log(Level::Info, false);

    let num_nodes = 20;
    let mut nodes = common::build_linear(log.clone(), num_nodes, Some(19000));
    let mut received_count = 0;
    let pubsub_message = PubsubMessage::Block(vec![0; 4]);
    let publishing_topic: String = "/eth2/beacon_block/ssz".into();
    let mut subscribed_count = 0;
    tokio::run(futures::future::poll_fn(move || -> Result<_, ()> {
        for node in nodes.iter_mut() {
            loop {
                match node.poll().unwrap() {
                    Async::Ready(Some(Libp2pEvent::PubsubMessage {
                        topics,
                        message,
                        source,
                        id,
                    })) => {
                        assert_eq!(topics.len(), 1);
                        // Assert topic is the published topic
                        assert_eq!(
                            topics.first().unwrap(),
                            &TopicHash::from_raw(publishing_topic.clone())
                        );
                        // Assert message received is the correct one
                        assert_eq!(message, pubsub_message.clone());
                        received_count += 1;
                        // Since `propagate_message` is false, need to propagate manually
                        node.swarm.propagate_message(&source, id);
                        // Test should succeed if all nodes except the publisher receive the message
                        if received_count == num_nodes - 1 {
                            debug!(log.clone(), "Received message at {} nodes", num_nodes - 1);
                            return Ok(Async::Ready(()));
                        }
                    }
                    Async::Ready(Some(Libp2pEvent::PeerSubscribed(_, topic))) => {
                        // Received topics is one of subscribed eth2 topics
                        assert!(topic.clone().into_string().starts_with("/eth2/"));
                        // Publish on beacon block topic
                        if topic == TopicHash::from_raw("/eth2/beacon_block/ssz") {
                            subscribed_count += 1;
                            // Every node except the corner nodes are connected to 2 nodes.
                            if subscribed_count == (num_nodes * 2) - 2 {
                                node.swarm.publish(
                                    &vec![Topic::new(topic.into_string())],
                                    pubsub_message.clone(),
                                );
                            }
                        }
                    }
                    _ => break,
                }
            }
        }
        Ok(Async::NotReady)
    }))
}

// Test publishing of a message with a full mesh for the topic
// Not very useful but this is the bare minimum functionality.
#[test]
fn test_gossipsub_full_mesh_publish() {
    // set up the logging. The level and enabled or not
    let log = common::build_log(Level::Info, false);

    let num_nodes = 20;
    let mut nodes = common::build_full_mesh(log, num_nodes, Some(11320));
    let mut publishing_node = nodes.pop().unwrap();
    let pubsub_message = PubsubMessage::Block(vec![0; 4]);
    let publishing_topic: String = "/eth2/beacon_block/ssz".into();
    let mut subscribed_count = 0;
    let mut received_count = 0;
    tokio::run(futures::future::poll_fn(move || -> Result<_, ()> {
        for node in nodes.iter_mut() {
            loop {
                match node.poll().unwrap() {
                    Async::Ready(Some(Libp2pEvent::PubsubMessage {
                        topics, message, ..
                    })) => {
                        assert_eq!(topics.len(), 1);
                        // Assert topic is the published topic
                        assert_eq!(
                            topics.first().unwrap(),
                            &TopicHash::from_raw(publishing_topic.clone())
                        );
                        // Assert message received is the correct one
                        assert_eq!(message, pubsub_message.clone());
                        received_count += 1;
                        if received_count == num_nodes - 1 {
                            return Ok(Async::Ready(()));
                        }
                    }
                    _ => break,
                }
            }
        }
        loop {
            match publishing_node.poll().unwrap() {
                Async::Ready(Some(Libp2pEvent::PeerSubscribed(_, topic))) => {
                    // Received topics is one of subscribed eth2 topics
                    assert!(topic.clone().into_string().starts_with("/eth2/"));
                    // Publish on beacon block topic
                    if topic == TopicHash::from_raw("/eth2/beacon_block/ssz") {
                        subscribed_count += 1;
                        if subscribed_count == num_nodes - 1 {
                            publishing_node.swarm.publish(
                                &vec![Topic::new(topic.into_string())],
                                pubsub_message.clone(),
                            );
                        }
                    }
                }
                _ => break,
            }
        }
        Ok(Async::NotReady)
    }))
}
<commit_msg>Reduced num_nodes in full_mesh gossipsub test (#718)<commit_after>#![cfg(test)]
use eth2_libp2p::*;
use futures::prelude::*;
use slog::{debug, Level};

mod common;

/* Gossipsub tests */
// Note: The aim of these tests is not to test the robustness of the gossip network
// but to check if the gossipsub implementation is behaving according to the specifications.

// Test if gossipsub message are forwarded by nodes with a simple linear topology.
//
//                Topology used in test
//
// node1 <-> node2 <-> node3 ..... <-> node(n-1) <-> node(n)

#[test]
fn test_gossipsub_forward() {
    // set up the logging. The level and enabled or not
    let log = common::build_log(Level::Info, false);

    let num_nodes = 20;
    let mut nodes = common::build_linear(log.clone(), num_nodes, Some(19000));
    let mut received_count = 0;
    let pubsub_message = PubsubMessage::Block(vec![0; 4]);
    let publishing_topic: String = "/eth2/beacon_block/ssz".into();
    let mut subscribed_count = 0;
    tokio::run(futures::future::poll_fn(move || -> Result<_, ()> {
        for node in nodes.iter_mut() {
            loop {
                match node.poll().unwrap() {
                    Async::Ready(Some(Libp2pEvent::PubsubMessage {
                        topics,
                        message,
                        source,
                        id,
                    })) => {
                        assert_eq!(topics.len(), 1);
                        // Assert topic is the published topic
                        assert_eq!(
                            topics.first().unwrap(),
                            &TopicHash::from_raw(publishing_topic.clone())
                        );
                        // Assert message received is the correct one
                        assert_eq!(message, pubsub_message.clone());
                        received_count += 1;
                        // Since `propagate_message` is false, need to propagate manually
                        node.swarm.propagate_message(&source, id);
                        // Test should succeed if all nodes except the publisher receive the message
                        if received_count == num_nodes - 1 {
                            debug!(log.clone(), "Received message at {} nodes", num_nodes - 1);
                            return Ok(Async::Ready(()));
                        }
                    }
                    Async::Ready(Some(Libp2pEvent::PeerSubscribed(_, topic))) => {
                        // Received topics is one of subscribed eth2 topics
                        assert!(topic.clone().into_string().starts_with("/eth2/"));
                        // Publish on beacon block topic
                        if topic == TopicHash::from_raw("/eth2/beacon_block/ssz") {
                            subscribed_count += 1;
                            // Every node except the corner nodes are connected to 2 nodes.
                            if subscribed_count == (num_nodes * 2) - 2 {
                                node.swarm.publish(
                                    &vec![Topic::new(topic.into_string())],
                                    pubsub_message.clone(),
                                );
                            }
                        }
                    }
                    _ => break,
                }
            }
        }
        Ok(Async::NotReady)
    }))
}

// Test publishing of a message with a full mesh for the topic
// Not very useful but this is the bare minimum functionality.
#[test]
fn test_gossipsub_full_mesh_publish() {
    // set up the logging. The level and enabled or not
    let log = common::build_log(Level::Info, false);

    // Note: This test does not propagate gossipsub messages.
    // Having `num_nodes` > `mesh_n_high` may give inconsistent results
    // as nodes may get pruned out of the mesh before the gossipsub message
    // is published to them.
    let num_nodes = 12;
    let mut nodes = common::build_full_mesh(log, num_nodes, Some(11320));
    let mut publishing_node = nodes.pop().unwrap();
    let pubsub_message = PubsubMessage::Block(vec![0; 4]);
    let publishing_topic: String = "/eth2/beacon_block/ssz".into();
    let mut subscribed_count = 0;
    let mut received_count = 0;
    tokio::run(futures::future::poll_fn(move || -> Result<_, ()> {
        for node in nodes.iter_mut() {
            loop {
                match node.poll().unwrap() {
                    Async::Ready(Some(Libp2pEvent::PubsubMessage {
                        topics, message, ..
                    })) => {
                        assert_eq!(topics.len(), 1);
                        // Assert topic is the published topic
                        assert_eq!(
                            topics.first().unwrap(),
                            &TopicHash::from_raw(publishing_topic.clone())
                        );
                        // Assert message received is the correct one
                        assert_eq!(message, pubsub_message.clone());
                        received_count += 1;
                        if received_count == num_nodes - 1 {
                            return Ok(Async::Ready(()));
                        }
                    }
                    _ => break,
                }
            }
        }
        loop {
            match publishing_node.poll().unwrap() {
                Async::Ready(Some(Libp2pEvent::PeerSubscribed(_, topic))) => {
                    // Received topics is one of subscribed eth2 topics
                    assert!(topic.clone().into_string().starts_with("/eth2/"));
                    // Publish on beacon block topic
                    if topic == TopicHash::from_raw("/eth2/beacon_block/ssz") {
                        subscribed_count += 1;
                        if subscribed_count == num_nodes - 1 {
                            publishing_node.swarm.publish(
                                &vec![Topic::new(topic.into_string())],
                                pubsub_message.clone(),
                            );
                        }
                    }
                }
                _ => break,
            }
        }
        Ok(Async::NotReady)
    }))
}
<|endoftext|>


<commit_before>// Copyright 2013 The noise-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::rand::{Rand, Rng, SeedableRng, XorShiftRng};
use std::num::SignedInt;

use math;

const TABLE_SIZE: uint = 256;

#[allow(missing_copy_implementations)]
pub struct Seed {
    values: [uint; TABLE_SIZE * 2],
}

impl Rand for Seed {
    fn rand<R: Rng>(rng: &mut R) -> Seed {
        let mut seq: Vec<uint> = range(0u, TABLE_SIZE).collect();
        for i in range(0, TABLE_SIZE) {
            let mut swap_i: uint = rng.gen();
            swap_i = swap_i % TABLE_SIZE;
            let swap = seq[swap_i];
            seq[swap_i] = seq[i];
            seq[i] = swap;
        }

        // It's unfortunate that this double-initializes the array, but Rust doesn't currently provide a
        // clean way to do this in one pass. Hopefully won't matter, as Seed creation will usually be a
        // one-time event.
        let mut new_seed = Seed {
            values: [0; TABLE_SIZE * 2],
        };
        for i in range(0, TABLE_SIZE * 2) {
            new_seed.values[i] = seq[i % TABLE_SIZE];
        }
        new_seed
    }
}

impl Seed {
    pub fn new(seed: u32) -> Seed {
        let mut rng: XorShiftRng = SeedableRng::from_seed([1, seed, seed, seed]);
        Rand::rand(&mut rng)
    }

    #[inline(always)]
    pub fn get1<T: SignedInt>(&self, x: T) -> uint {
        self.values[math::cast::<T, uint>(x) & (TABLE_SIZE - 1)]
    }

    #[inline(always)]
    pub fn get2<T: SignedInt>(&self, pos: math::Point2<T>) -> uint {
        self.values[self.get1(pos[0]) + (math::cast::<T, uint>(pos[1]) & (TABLE_SIZE - 1))]
    }

    #[inline(always)]
    pub fn get3<T: SignedInt>(&self, pos: math::Point3<T>) -> uint {
        self.values[self.get2([pos[0], pos[1]]) + (math::cast::<T, uint>(pos[2]) & (TABLE_SIZE - 1))]
    }

    #[inline(always)]
    pub fn get4<T: SignedInt>(&self, pos: math::Point4<T>) -> uint {
        self.values[self.get3([pos[0], pos[1], pos[2]]) + (math::cast::<T, uint>(pos[3]) & (TABLE_SIZE - 1))]
    }
}

#[cfg(test)]
mod tests {
    use std::rand::random;
    use perlin::perlin3;

    #[test]
    fn test_random_seed() {
        let _ = perlin3::<f32>(&random(), &[1.0, 2.0, 3.0]);
    }
}
<commit_msg>Fix panics with negative perlin parameters, and add a test.<commit_after>// Copyright 2013 The noise-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::rand::{Rand, Rng, SeedableRng, XorShiftRng};
use std::num::SignedInt;

use math;

const TABLE_SIZE: uint = 256;

#[allow(missing_copy_implementations)]
pub struct Seed {
    values: [uint; TABLE_SIZE * 2],
}

impl Rand for Seed {
    fn rand<R: Rng>(rng: &mut R) -> Seed {
        let mut seq: Vec<uint> = range(0u, TABLE_SIZE).collect();
        for i in range(0, TABLE_SIZE) {
            let mut swap_i: uint = rng.gen();
            swap_i = swap_i % TABLE_SIZE;
            let swap = seq[swap_i];
            seq[swap_i] = seq[i];
            seq[i] = swap;
        }

        // It's unfortunate that this double-initializes the array, but Rust doesn't currently provide a
        // clean way to do this in one pass. Hopefully won't matter, as Seed creation will usually be a
        // one-time event.
        let mut new_seed = Seed {
            values: [0; TABLE_SIZE * 2],
        };
        for i in range(0, TABLE_SIZE * 2) {
            new_seed.values[i] = seq[i % TABLE_SIZE];
        }
        new_seed
    }
}

impl Seed {
    pub fn new(seed: u32) -> Seed {
        let mut rng: XorShiftRng = SeedableRng::from_seed([1, seed, seed, seed]);
        Rand::rand(&mut rng)
    }

    #[inline(always)]
    pub fn get1<T: SignedInt>(&self, x: T) -> uint {
        self.values[math::cast::<T, uint>(x & math::cast(TABLE_SIZE - 1))]
    }

    #[inline(always)]
    pub fn get2<T: SignedInt>(&self, pos: math::Point2<T>) -> uint {
        self.values[self.get1(pos[0]) + math::cast(pos[1] & math::cast(TABLE_SIZE - 1))]
    }

    #[inline(always)]
    pub fn get3<T: SignedInt>(&self, pos: math::Point3<T>) -> uint {
        self.values[self.get2([pos[0], pos[1]]) + math::cast(pos[2] & math::cast(TABLE_SIZE - 1))]
    }

    #[inline(always)]
    pub fn get4<T: SignedInt>(&self, pos: math::Point4<T>) -> uint {
        self.values[self.get3([pos[0], pos[1], pos[2]]) + math::cast(pos[3] & math::cast(TABLE_SIZE - 1))]
    }
}

#[cfg(test)]
mod tests {
    use std::rand::random;
    use perlin::perlin3;
    use super::Seed;

    #[test]
    fn test_random_seed() {
        let _ = perlin3::<f32>(&random(), &[1.0, 2.0, 3.0]);
    }

    #[test]
    fn test_negative_params() {
        let _ = perlin3::<f32>(&Seed::new(0), &[-1.0, 2.0, 3.0]);
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use slog::slog_error;
use slog_scope::error;
use std::path::Path;

const STATE_CHANGE_CALLBACK: &str = "state-change-callback";

#[derive(Debug, PartialEq)]
pub(super) enum Transition {
    Continue,
    Cancel,
}

pub(super) fn state_change_callback(
    path: &Path,
    state: &'static str,
) -> Result<Transition, failure::Error> {
    use easy_process;
    use std::io;

    let callback = path.join(STATE_CHANGE_CALLBACK);
    if !callback.exists() {
        return Ok(Transition::Continue);
    }

    let output = easy_process::run(&format!("{} {}", &callback.to_string_lossy(), &state))?;
    for err in output.stderr.lines() {
        error!("{} (stderr): {}", path.display(), err);
    }

    match output.stdout.trim() {
        "cancel" => Ok(Transition::Cancel),
        "" => Ok(Transition::Continue),
        _ => Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!(
                "Invalid format found while running 'state-change-callback' \
                 hook for state '{}'",
                &state
            ),
        )
        .into()),
    }
}

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

    const CALLBACK_STATE_NAME: &str = "test_state";

    fn create_state_change_callback_hook(content: &str) -> tempfile::TempDir {
        use crate::firmware::tests::create_hook;

        let tmpdir = tempfile::tempdir().unwrap();
        let tmpdir = tmpdir;

        create_hook(tmpdir.path().join(STATE_CHANGE_CALLBACK), content);
        tmpdir
    }

    #[test]
    fn cancel() {
        let script = "#!/bin/sh\necho cancel";
        let tmpdir = create_state_change_callback_hook(&script);
        assert_eq!(
            state_change_callback(&tmpdir.path(), CALLBACK_STATE_NAME).unwrap(),
            Transition::Cancel,
            "Unexpected result using content {:?}",
            script,
        );
    }

    #[test]
    fn continue_transition() {
        let script = "#!/bin/sh\necho ";
        let tmpdir = create_state_change_callback_hook(&script);
        assert_eq!(
            state_change_callback(&tmpdir.path(), CALLBACK_STATE_NAME).unwrap(),
            Transition::Continue,
            "Unexpected result using content {:?}",
            script,
        );
    }

    #[test]
    fn non_existing_hook() {
        assert_eq!(
            state_change_callback(&Path::new("/NaN"), CALLBACK_STATE_NAME).unwrap(),
            Transition::Continue,
            "Unexpected result for non-existing hook",
        );
    }

    #[test]
    fn is_error() {
        for script in &["#!/bin/sh\necho 123", "#!/bin/sh\necho 123\ncancel"] {
            let tmpdir = create_state_change_callback_hook(script);
            assert!(state_change_callback(&tmpdir.path(), CALLBACK_STATE_NAME).is_err());
        }
    }
}
<commit_msg>states: Remove redundant use import of `easy_process`<commit_after>// Copyright (C) 2018 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

use slog::slog_error;
use slog_scope::error;
use std::path::Path;

const STATE_CHANGE_CALLBACK: &str = "state-change-callback";

#[derive(Debug, PartialEq)]
pub(super) enum Transition {
    Continue,
    Cancel,
}

pub(super) fn state_change_callback(
    path: &Path,
    state: &'static str,
) -> Result<Transition, failure::Error> {
    use std::io;

    let callback = path.join(STATE_CHANGE_CALLBACK);
    if !callback.exists() {
        return Ok(Transition::Continue);
    }

    let output = easy_process::run(&format!("{} {}", &callback.to_string_lossy(), &state))?;
    for err in output.stderr.lines() {
        error!("{} (stderr): {}", path.display(), err);
    }

    match output.stdout.trim() {
        "cancel" => Ok(Transition::Cancel),
        "" => Ok(Transition::Continue),
        _ => Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!(
                "Invalid format found while running 'state-change-callback' \
                 hook for state '{}'",
                &state
            ),
        )
        .into()),
    }
}

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

    const CALLBACK_STATE_NAME: &str = "test_state";

    fn create_state_change_callback_hook(content: &str) -> tempfile::TempDir {
        use crate::firmware::tests::create_hook;

        let tmpdir = tempfile::tempdir().unwrap();
        let tmpdir = tmpdir;

        create_hook(tmpdir.path().join(STATE_CHANGE_CALLBACK), content);
        tmpdir
    }

    #[test]
    fn cancel() {
        let script = "#!/bin/sh\necho cancel";
        let tmpdir = create_state_change_callback_hook(&script);
        assert_eq!(
            state_change_callback(&tmpdir.path(), CALLBACK_STATE_NAME).unwrap(),
            Transition::Cancel,
            "Unexpected result using content {:?}",
            script,
        );
    }

    #[test]
    fn continue_transition() {
        let script = "#!/bin/sh\necho ";
        let tmpdir = create_state_change_callback_hook(&script);
        assert_eq!(
            state_change_callback(&tmpdir.path(), CALLBACK_STATE_NAME).unwrap(),
            Transition::Continue,
            "Unexpected result using content {:?}",
            script,
        );
    }

    #[test]
    fn non_existing_hook() {
        assert_eq!(
            state_change_callback(&Path::new("/NaN"), CALLBACK_STATE_NAME).unwrap(),
            Transition::Continue,
            "Unexpected result for non-existing hook",
        );
    }

    #[test]
    fn is_error() {
        for script in &["#!/bin/sh\necho 123", "#!/bin/sh\necho 123\ncancel"] {
            let tmpdir = create_state_change_callback_hook(script);
            assert!(state_change_callback(&tmpdir.path(), CALLBACK_STATE_NAME).is_err());
        }
    }
}
<|endoftext|>


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

use std::rc::*;

use super::super::tree::*;

use super::component::*;
use super::subscriptionmanager::*;

///
/// Stores a registration of a consumer
///
#[derive(Clone)]
struct ConsumerRegistration {
    address: TreeAddress,
    extent: TreeExtent
}

///
/// Consumer for data written by an immediate publisher
///
struct ImmediateConsumer {
    ///
    /// Where subscriptions can be registered for this consumer
    ///
    subscriptions: Rc<SubscriptionManager<ConsumerRegistration>>
}

impl Consumer for ImmediateConsumer {
    ///
    /// Calls a function whenever a particular section of the tree has changed
    ///
    fn subscribe(&mut self, address: TreeAddress, extent: TreeExtent, callback: ConsumerCallback) {
        // Need to persuade rust that it can call the FnMut (assign parameter to a mutable variable)
        let mut also_callback = callback;

        self.subscriptions.add_subscription(ConsumerRegistration { address: address.clone(), extent: extent }, Box::new(move |change| {
            // The change we get from the subscription will have an address relative to the root of the tree
            // Make the subscription change relative to the address that was subscribed to
            let maybe_relative_change = change.relative_to(&address);
            if let Some(relative_change) = maybe_relative_change {
                also_callback(&relative_change);
            }
        }));
    }
}

///
/// Publisher that immediately sends changes to its consumers. Can be used as a consumer factory.
///
pub struct ImmediatePublisher {
    ///
    /// Subscriptions for this publisher
    ///
    subscriptions: Rc<SubscriptionManager<ConsumerRegistration>>
}

impl ImmediatePublisher {
    ///
    /// Creates a new immediate publisher
    ///
    pub fn new() -> Box<ImmediatePublisher> {
        Box::new(ImmediatePublisher { subscriptions: Rc::new(SubscriptionManager::new()) })
    }

    ///
    /// Creates a consumer that will receive notifications from this publisher
    ///
    pub fn create_consumer(&self) -> ConsumerRef {
        Box::new(ImmediateConsumer { subscriptions: self.subscriptions.clone() })
    }
}

impl Publisher for ImmediatePublisher {
    ///
    /// Publishes a change to the consumers of this component
    ///
    fn publish(&mut self, change: TreeChange) {
        self.subscriptions.call_subscriptions(&|registration| {
            change.applies_to(&registration.address, &registration.extent).unwrap_or(false)
        }, &change);
    }
}

#[cfg(test)]
mod immediate_publisher_tests {
    use std::cell::*;
    use std::rc::*;

    use super::super::super::component::*;
    use super::*;

    #[test]
    fn can_consume_published_item() {
        let mut publisher   = ImmediatePublisher::new();
        let mut consumer    = publisher.create_consumer();

        let our_count       = Rc::new(Cell::new(0));
        let their_count     = our_count.clone();

        let consumer_tree: RefCell<TreeRef> = RefCell::new(Rc::new("empty".to_tree_node()));

        // Subscribe to the second child of the root
        // Ie, tree should look like this:
        //
        // root
        //   +- Anything
        //   +- ConsumerTree
        //        +- add(value)
        consumer.subscribe(1.to_tree_address(), TreeExtent::SubTree, Box::new(move |change| {
            // Update the tree
            let mut tree = consumer_tree.borrow_mut();
            let new_tree = change.apply(&tree.clone());
            *tree = new_tree;

            // Tree can have an 'add' node that specifies how much to add to the count for this change
            let old_val     = their_count.get();
            let tree_value  = tree.get_child_ref_at("add").map(|val| { val.get_value().to_int(0) }).unwrap_or(0);

            their_count.set(old_val + tree_value);
        }));

        // count is initially 0
        assert!(our_count.get() == 0);

        // Publish an add of 1 to set the count to 1
        let just_add = ("add", 1).to_tree_node();

        // Change the child of the second child of the root to the 'just_add' tree
        let modify_child_of_subscribed_tree = TreeChange::new(&(0, 1).to_tree_address(), TreeChangeType::Child, Some(&just_add));
        assert!(!modify_child_of_subscribed_tree.relative_to(&1.to_tree_address()).is_none());
        publisher.publish(modify_child_of_subscribed_tree);

        assert!(our_count.get() == 1);

        // Publish an add of 1 to set the count to 1
        let whole_tree = tree!("root", "some_other_tree", tree!("consumer_target", ("add", 2)));

        // Replace the entire tree with the tree above
        let modify_entire_tree = TreeChange::new(&TreeAddress::Here, TreeChangeType::Child, Some(&whole_tree));
        publisher.publish(modify_entire_tree);

        assert!(our_count.get() == 3);
    }
}
<commit_msg>Now we're using FnMut, we can simplify the test for immediate_publisher a bit<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

use std::rc::*;

use super::super::tree::*;

use super::component::*;
use super::subscriptionmanager::*;

///
/// Stores a registration of a consumer
///
#[derive(Clone)]
struct ConsumerRegistration {
    address: TreeAddress,
    extent: TreeExtent
}

///
/// Consumer for data written by an immediate publisher
///
struct ImmediateConsumer {
    ///
    /// Where subscriptions can be registered for this consumer
    ///
    subscriptions: Rc<SubscriptionManager<ConsumerRegistration>>
}

impl Consumer for ImmediateConsumer {
    ///
    /// Calls a function whenever a particular section of the tree has changed
    ///
    fn subscribe(&mut self, address: TreeAddress, extent: TreeExtent, callback: ConsumerCallback) {
        // Need to persuade rust that it can call the FnMut (assign parameter to a mutable variable)
        let mut also_callback = callback;

        self.subscriptions.add_subscription(ConsumerRegistration { address: address.clone(), extent: extent }, Box::new(move |change| {
            // The change we get from the subscription will have an address relative to the root of the tree
            // Make the subscription change relative to the address that was subscribed to
            let maybe_relative_change = change.relative_to(&address);
            if let Some(relative_change) = maybe_relative_change {
                also_callback(&relative_change);
            }
        }));
    }
}

///
/// Publisher that immediately sends changes to its consumers. Can be used as a consumer factory.
///
pub struct ImmediatePublisher {
    ///
    /// Subscriptions for this publisher
    ///
    subscriptions: Rc<SubscriptionManager<ConsumerRegistration>>
}

impl ImmediatePublisher {
    ///
    /// Creates a new immediate publisher
    ///
    pub fn new() -> Box<ImmediatePublisher> {
        Box::new(ImmediatePublisher { subscriptions: Rc::new(SubscriptionManager::new()) })
    }

    ///
    /// Creates a consumer that will receive notifications from this publisher
    ///
    pub fn create_consumer(&self) -> ConsumerRef {
        Box::new(ImmediateConsumer { subscriptions: self.subscriptions.clone() })
    }
}

impl Publisher for ImmediatePublisher {
    ///
    /// Publishes a change to the consumers of this component
    ///
    fn publish(&mut self, change: TreeChange) {
        self.subscriptions.call_subscriptions(&|registration| {
            change.applies_to(&registration.address, &registration.extent).unwrap_or(false)
        }, &change);
    }
}

#[cfg(test)]
mod immediate_publisher_tests {
    use std::cell::*;
    use std::rc::*;

    use super::super::super::component::*;
    use super::*;

    #[test]
    fn can_consume_published_item() {
        let mut publisher   = ImmediatePublisher::new();
        let mut consumer    = publisher.create_consumer();

        let our_count       = Rc::new(Cell::new(0));
        let their_count     = our_count.clone();

        let mut consumer_tree = "empty".to_tree_node();

        // Subscribe to the second child of the root
        // Ie, tree should look like this:
        //
        // root
        //   +- Anything
        //   +- ConsumerTree
        //        +- add(value)
        consumer.subscribe(1.to_tree_address(), TreeExtent::SubTree, Box::new(move |change| {
            // Update the tree
            consumer_tree = change.apply(&consumer_tree);

            // Tree can have an 'add' node that specifies how much to add to the count for this change
            let old_val     = their_count.get();
            let tree_value  = consumer_tree.get_child_ref_at("add").map(|val| { val.get_value().to_int(0) }).unwrap_or(0);

            their_count.set(old_val + tree_value);
        }));

        // count is initially 0
        assert!(our_count.get() == 0);

        // Publish an add of 1 to set the count to 1
        let just_add = ("add", 1).to_tree_node();

        // Change the child of the second child of the root to the 'just_add' tree
        let modify_child_of_subscribed_tree = TreeChange::new(&(0, 1).to_tree_address(), TreeChangeType::Child, Some(&just_add));
        assert!(!modify_child_of_subscribed_tree.relative_to(&1.to_tree_address()).is_none());
        publisher.publish(modify_child_of_subscribed_tree);

        assert!(our_count.get() == 1);

        // Publish an add of 1 to set the count to 1
        let whole_tree = tree!("root", "some_other_tree", tree!("consumer_target", ("add", 2)));

        // Replace the entire tree with the tree above
        let modify_entire_tree = TreeChange::new(&TreeAddress::Here, TreeChangeType::Child, Some(&whole_tree));
        publisher.publish(modify_entire_tree);

        assert!(our_count.get() == 3);
    }
}
<|endoftext|>


<commit_before>use std::io::MemReader;
use std::task;

use {session, resolve, grammar, exec, dumpfile};

struct TestCode {
  step: exec::Step,
}

fn compile(source: &str) -> TestCode {
	let sess = session::Session::new();
  let mut ctx = resolve::Context::new(&sess);

  let module = grammar::module(source).unwrap();
  let prelude = resolve::Scope::new();

  let modscope = resolve::resolve_module(&mut ctx, &prelude, &module);
  let main = match *modscope.get("main").unwrap() {
    resolve::scope::DefItem(ref s) => s,
    _ => fail!("Main is not an event"),
  };

  let w = resolve::scope::EmptyItem;
  TestCode{ step: main.resolve_call(&mut ctx, &w, None) }
}

impl TestCode {
  fn up(&self, input: &'static str) -> bool {
    debug!("--- up")
    let (mut s1, mut s2) = exec::Connection::new();
    task::spawn(proc(){
      let mut reader = MemReader::new(input.as_bytes().to_vec());
      dumpfile::read_values(&mut reader, &mut s2);
    });
    exec::exec(&self.step, &mut s1)
  }

  fn down() -> String {
    unimplemented!();
  }

  fn up_pass(&self, _arg: &str, input: &'static str) {
    if !self.up(input) {
      fail!("up_pass test failed to match: {}", input);
    }
  }

  fn up_fail(&self, _arg: &str, input: &'static str) {
    if self.up(input) {
      fail!("up_fail test matched: {}", input);
    }
  }

  fn down_pass(&self, _arg: &str, _output: &str) {

  }
}

#[test]
fn test_seq() {
  let p = compile("
  def main (w) {
    #a
    #b
    #c
  }
    "
  );

  p.up_pass("", "#a \n #b \n #c");
  p.down_pass("", "#a \n #b \n #c");
  p.up_fail("", "#a \n #b \n #a");
  p.up_fail("", "#b \n #b \n #c");
}

#[test]
fn test_loop() {
  let p = compile("
  def main(w) {
    #a
    #b
    repeat {
      :> #c
      :> #d
    }
    :> #a
  }
  ");

  p.up_pass("", "#a \n #b \n #a");
  p.up_pass("", "#a \n #b \n #c \n #d \n #a");
  p.up_pass("", "#a \n #b \n #c \n #d \n #c \n #d \n #a");
  p.up_fail("", "#a \n #b \n #c \n #a");
  p.up_fail("", "#a \n #b \n #c \n #d");
}
<commit_msg>Add test for a nested loop<commit_after>use std::io::MemReader;
use std::task;

use {session, resolve, grammar, exec, dumpfile};

struct TestCode {
  step: exec::Step,
}

fn compile(source: &str) -> TestCode {
	let sess = session::Session::new();
  let mut ctx = resolve::Context::new(&sess);

  let module = grammar::module(source).unwrap();
  let prelude = resolve::Scope::new();

  let modscope = resolve::resolve_module(&mut ctx, &prelude, &module);
  let main = match *modscope.get("main").unwrap() {
    resolve::scope::DefItem(ref s) => s,
    _ => fail!("Main is not an event"),
  };

  let w = resolve::scope::EmptyItem;
  TestCode{ step: main.resolve_call(&mut ctx, &w, None) }
}

impl TestCode {
  fn up(&self, input: &'static str) -> bool {
    debug!("--- up")
    let (mut s1, mut s2) = exec::Connection::new();
    task::spawn(proc(){
      let mut reader = MemReader::new(input.as_bytes().to_vec());
      dumpfile::read_values(&mut reader, &mut s2);
    });
    exec::exec(&self.step, &mut s1)
  }

  fn down() -> String {
    unimplemented!();
  }

  fn up_pass(&self, _arg: &str, input: &'static str) {
    if !self.up(input) {
      fail!("up_pass test failed to match: {}", input);
    }
  }

  fn up_fail(&self, _arg: &str, input: &'static str) {
    if self.up(input) {
      fail!("up_fail test matched: {}", input);
    }
  }

  fn down_pass(&self, _arg: &str, _output: &str) {

  }
}

#[test]
fn test_seq() {
  let p = compile("
  def main (w) {
    #a
    #b
    #c
  }
    "
  );

  p.up_pass("", "#a \n #b \n #c");
  p.down_pass("", "#a \n #b \n #c");
  p.up_fail("", "#a \n #b \n #a");
  p.up_fail("", "#b \n #b \n #c");
}

#[test]
fn test_loop() {
  let p = compile("
  def main(w) {
    #a
    #b
    repeat {
      :> #c
      :> #d
    }
    :> #a
  }
  ");

  p.up_pass("", "#a \n #b \n #a");
  p.up_pass("", "#a \n #b \n #c \n #d \n #a");
  p.up_pass("", "#a \n #b \n #c \n #d \n #c \n #d \n #a");
  p.up_fail("", "#a \n #b \n #c \n #a");
  p.up_fail("", "#a \n #b \n #c \n #d");
}

#[test]
fn test_nested_loop() {
  let p = compile("
  def main(w) {
    #a
    repeat {
      repeat {
        :> #b
      }
      repeat {
        :> #c
      }
      :> #d
    }
    :> #e
  }
  ");

  p.up_pass("", "#a \n #e");
  p.up_pass("", "#a \n #b \n #c \n #d \n #e");
  p.up_pass("", "#a \n #b \n #b \n #c \n #c \n #c \n #d \n #b \n #d \n #e");
  p.up_fail("", "#a \n #b \n #c");
}
<|endoftext|>


<commit_before>//! Implementation of a single Todo item.

/// Data Structure for a simple todo.
///
/// A `Todo` item is the atomic unit within the `tdo` microcosm.
/// It represents a single todo or task, which is identified by an ID.
/// Information about its state (_done_ or _undone_) can be derived from
/// the data structure as well as the title of the todo item.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Todo {
    /// Unique identifier for every Todo.
    pub id: u32,
    /// Title of the todo.
    pub name: String,
    /// Status of the todo.
    pub done: bool,
    /// Optional GitHub issue.
    pub github: Option<GitHub>,
}

impl Todo {
    /// Constructor. Creates a new Todo item.
    pub fn new(id: u32, name: &str, github: Option<GitHub>) -> Todo {
        Todo {
            id: id,
            name: name.to_string(),
            done: false,
            github: github,
        }
    }

    /// Edit the title of a given Todo.
    pub fn edit(&mut self, new_name: &str) {
        self.name = new_name.to_string();
    }

    /// Set the status of a Todo item to _done_.
    pub fn set_done(&mut self) {
        self.done = true;
    }

    /// Mark a todo item as _undone_.
    pub fn set_undone(&mut self) {
        self.done = false;
    }
}

/// Data Structure for a represented Github issue in an todo.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GitHub {
    /// Name of the repository (owner/repo).
    pub repo: String,
    /// Number of the issue.
    pub issue_number: u32,
}

impl GitHub {
    /// Constructor. Creates a new GitHub item.
    pub fn new(repo: &str, issue_number: u32) -> GitHub {
        GitHub {
            repo: repo.to_owned(),
            issue_number: issue_number,
        }
    }
}

/// Data Structure to parse responses from the Github API.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GHIssueResponse {
    /// Repository URL.
    pub url: String,
    /// Issue number.
    pub number: u32,
    /// Current state of the Issue.
    pub state: String,
}
<commit_msg>Adding issue title to GHIssueResponse<commit_after>//! Implementation of a single Todo item.

/// Data Structure for a simple todo.
///
/// A `Todo` item is the atomic unit within the `tdo` microcosm.
/// It represents a single todo or task, which is identified by an ID.
/// Information about its state (_done_ or _undone_) can be derived from
/// the data structure as well as the title of the todo item.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Todo {
    /// Unique identifier for every Todo.
    pub id: u32,
    /// Title of the todo.
    pub name: String,
    /// Status of the todo.
    pub done: bool,
    /// Optional GitHub issue.
    pub github: Option<GitHub>,
}

impl Todo {
    /// Constructor. Creates a new Todo item.
    pub fn new(id: u32, name: &str, github: Option<GitHub>) -> Todo {
        Todo {
            id: id,
            name: name.to_string(),
            done: false,
            github: github,
        }
    }

    /// Edit the title of a given Todo.
    pub fn edit(&mut self, new_name: &str) {
        self.name = new_name.to_string();
    }

    /// Set the status of a Todo item to _done_.
    pub fn set_done(&mut self) {
        self.done = true;
    }

    /// Mark a todo item as _undone_.
    pub fn set_undone(&mut self) {
        self.done = false;
    }
}

/// Data Structure for a represented Github issue in an todo.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GitHub {
    /// Name of the repository (owner/repo).
    pub repo: String,
    /// Number of the issue.
    pub issue_number: u32,
}

impl GitHub {
    /// Constructor. Creates a new GitHub item.
    pub fn new(repo: &str, issue_number: u32) -> GitHub {
        GitHub {
            repo: repo.to_owned(),
            issue_number: issue_number,
        }
    }
}

/// Data Structure to parse responses from the Github API.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GHIssueResponse {
    /// Repository URL.
    pub url: String,
    /// Issue number.
    pub number: u32,
    /// Current state of the Issue.
    pub state: String,
    /// Title of the Issue.
    pub title: String,
}
<|endoftext|>


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

use devicemapper::{DM, DevId, DeviceInfo, DmFlags};

use engine::{EngineError, EngineResult, ErrorEnum};
use engine::strat_engine::blockdev::blkdev_size;

use std::fmt;
use std::fs::File;
use std::path::PathBuf;

use super::blockdev::BlockDev;
use types::{Bytes, Sectors};

pub struct LinearDev {
    name: String,
    dev_info: DeviceInfo,
}

impl fmt::Debug for LinearDev {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.name())
    }
}

/// Use DM to concatenate a set of blockdevs together into a
/// /dev/mapper/xxx block device of continuous sectors.
impl LinearDev {
    /// Construct a new block device by concatenating the given block_devs
    /// into linear space.  Use DM to reserve enough space for the stratis
    /// metadata on each BlockDev.
    pub fn new(name: &str, dm: &DM, block_devs: &Vec<&BlockDev>) -> EngineResult<LinearDev> {

        try!(dm.device_create(&name, None, DmFlags::empty()));
        let table = LinearDev::dm_table(block_devs);
        let id = &DevId::Name(&name);
        let dev_info = try!(dm.table_load(id, &table));
        try!(dm.device_suspend(id, DmFlags::empty()));

        BlockDev::wait_for_dm();
        Ok(LinearDev {
            name: name.to_owned(),
            dev_info: dev_info,
        })
    }

    /// Generate a Vec<> to be passed to DM.  The format of the Vec entries is:
    /// <logical start sec> <length> "linear" /dev/xxx <start offset>
    fn dm_table(block_devs: &Vec<&BlockDev>) -> Vec<(u64, u64, String, String)> {
        let mut table = Vec::new();
        let mut logical_start_sector = Sectors(0);
        for block_dev in block_devs {
            let (start, length) = block_dev.avail_range();
            let dstr = block_dev.dstr();
            let line = (*logical_start_sector,
                        *length,
                        "linear".to_owned(),
                        format!("{} {}", dstr, *start));
            debug!("dmtable line : {:?}", line);
            table.push(line);
            logical_start_sector = logical_start_sector + length;
        }

        table
    }

    pub fn name(&self) -> &str {
        self.dev_info.name()
    }

    pub fn size(&self) -> EngineResult<Bytes> {

        let blockdev_path = try!(self.path());
        let f = match File::open(blockdev_path) {
            Ok(file) => file,
            Err(e) => {
                let error_message = format!("{:?} Failed to open blockdev {:?}", e, self.path());
                return Err(EngineError::Engine(ErrorEnum::FailedToOpen, error_message.into()));
            }
        };

        match blkdev_size(&f) {
            Ok(bytes) => return Ok(bytes),
            Err(e) => {
                let error_message = format!("{:?} for device {:?}", e, self.path());
                return Err(EngineError::Engine(ErrorEnum::Error, error_message.into()));
            }
        };
    }

    pub fn path(&self) -> EngineResult<PathBuf> {
        match self.dev_info.device().path() {
            Some(path) => return Ok(path),
            None => {
                return Err(EngineError::Engine(ErrorEnum::Invalid,
                                               "No path associated with dev_info".into()))
            }
        }
    }

    pub fn teardown(&self, dm: &DM) -> EngineResult<()> {
        try!(dm.device_remove(&DevId::Name(&self.name), DmFlags::empty()));

        Ok(())
    }
}
<commit_msg>Change Vec parameter to slice parameter<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use devicemapper::{DM, DevId, DeviceInfo, DmFlags};

use engine::{EngineError, EngineResult, ErrorEnum};
use engine::strat_engine::blockdev::blkdev_size;

use std::fmt;
use std::fs::File;
use std::path::PathBuf;

use super::blockdev::BlockDev;
use types::{Bytes, Sectors};

pub struct LinearDev {
    name: String,
    dev_info: DeviceInfo,
}

impl fmt::Debug for LinearDev {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.name())
    }
}

/// Use DM to concatenate a set of blockdevs together into a
/// /dev/mapper/xxx block device of continuous sectors.
impl LinearDev {
    /// Construct a new block device by concatenating the given block_devs
    /// into linear space.  Use DM to reserve enough space for the stratis
    /// metadata on each BlockDev.
    pub fn new(name: &str, dm: &DM, block_devs: &[&BlockDev]) -> EngineResult<LinearDev> {

        try!(dm.device_create(&name, None, DmFlags::empty()));
        let table = LinearDev::dm_table(block_devs);
        let id = &DevId::Name(&name);
        let dev_info = try!(dm.table_load(id, &table));
        try!(dm.device_suspend(id, DmFlags::empty()));

        BlockDev::wait_for_dm();
        Ok(LinearDev {
            name: name.to_owned(),
            dev_info: dev_info,
        })
    }

    /// Generate a Vec<> to be passed to DM.  The format of the Vec entries is:
    /// <logical start sec> <length> "linear" /dev/xxx <start offset>
    fn dm_table(block_devs: &[&BlockDev]) -> Vec<(u64, u64, String, String)> {
        let mut table = Vec::new();
        let mut logical_start_sector = Sectors(0);
        for block_dev in block_devs {
            let (start, length) = block_dev.avail_range();
            let dstr = block_dev.dstr();
            let line = (*logical_start_sector,
                        *length,
                        "linear".to_owned(),
                        format!("{} {}", dstr, *start));
            debug!("dmtable line : {:?}", line);
            table.push(line);
            logical_start_sector = logical_start_sector + length;
        }

        table
    }

    pub fn name(&self) -> &str {
        self.dev_info.name()
    }

    pub fn size(&self) -> EngineResult<Bytes> {

        let blockdev_path = try!(self.path());
        let f = match File::open(blockdev_path) {
            Ok(file) => file,
            Err(e) => {
                let error_message = format!("{:?} Failed to open blockdev {:?}", e, self.path());
                return Err(EngineError::Engine(ErrorEnum::FailedToOpen, error_message.into()));
            }
        };

        match blkdev_size(&f) {
            Ok(bytes) => return Ok(bytes),
            Err(e) => {
                let error_message = format!("{:?} for device {:?}", e, self.path());
                return Err(EngineError::Engine(ErrorEnum::Error, error_message.into()));
            }
        };
    }

    pub fn path(&self) -> EngineResult<PathBuf> {
        match self.dev_info.device().path() {
            Some(path) => return Ok(path),
            None => {
                return Err(EngineError::Engine(ErrorEnum::Invalid,
                                               "No path associated with dev_info".into()))
            }
        }
    }

    pub fn teardown(&self, dm: &DM) -> EngineResult<()> {
        try!(dm.device_remove(&DevId::Name(&self.name), DmFlags::empty()));

        Ok(())
    }
}
<|endoftext|>


<commit_before>#![allow(deprecated)] // old_io, os

use libc::{c_void, FILE};
use std::ptr;
use std::fmt::Error;
/// A structure that wraps a native object
pub trait NativeRef {
    /// Returns the native reference encapsulated by this object
    unsafe fn as_ptr(&self) -> *mut c_void;
    /// Returns a wrapped version of the native reference given, even if the reference is null
    unsafe fn from_ptr(ptr:*mut c_void) -> Self;
}
#[inline(always)]
pub unsafe fn from_ptr<T>(ptr: *mut c_void) -> T where T:NativeRef {
    NativeRef::from_ptr(ptr)
}
impl<T> NativeRef for Option<T> where T:NativeRef {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> *mut c_void {
        match *self {
            Some(ref v) => v.as_ptr(),
            None => ptr::null_mut()
        }
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:*mut c_void) -> Option<T> {
        if ptr.is_null() {
            None
        } else {
            Some(from_ptr(ptr))
        }
    }
}

pub fn dump<F>(cb: F) -> Result<String, Error> where F:FnOnce(*mut FILE) {
    use std::old_io::pipe::PipeStream;
    use std::os;
    use libc::{fdopen, fclose};
    unsafe {
        let pair = os::pipe().unwrap();
        let file = fdopen(pair.writer, b"w".as_ptr() as *const i8);
        cb(file);
        fclose(file);
        match PipeStream::open(pair.reader).read_to_end() {
            Ok(v) => Ok(String::from_utf8_unchecked(v)),
            Err(_) => Err(Error)
        }
    }
}
<commit_msg>old_io::Reader is no longer in the prelude.<commit_after>#![allow(deprecated)] // old_io, os

use libc::{c_void, FILE};
use std::ptr;
use std::fmt::Error;
/// A structure that wraps a native object
pub trait NativeRef {
    /// Returns the native reference encapsulated by this object
    unsafe fn as_ptr(&self) -> *mut c_void;
    /// Returns a wrapped version of the native reference given, even if the reference is null
    unsafe fn from_ptr(ptr:*mut c_void) -> Self;
}
#[inline(always)]
pub unsafe fn from_ptr<T>(ptr: *mut c_void) -> T where T:NativeRef {
    NativeRef::from_ptr(ptr)
}
impl<T> NativeRef for Option<T> where T:NativeRef {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> *mut c_void {
        match *self {
            Some(ref v) => v.as_ptr(),
            None => ptr::null_mut()
        }
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:*mut c_void) -> Option<T> {
        if ptr.is_null() {
            None
        } else {
            Some(from_ptr(ptr))
        }
    }
}

pub fn dump<F>(cb: F) -> Result<String, Error> where F:FnOnce(*mut FILE) {
    use std::old_io::pipe::PipeStream;
    use std::old_io::Reader;
    use std::os;
    use libc::{fdopen, fclose};
    unsafe {
        let pair = os::pipe().unwrap();
        let file = fdopen(pair.writer, b"w".as_ptr() as *const i8);
        cb(file);
        fclose(file);
        match PipeStream::open(pair.reader).read_to_end() {
            Ok(v) => Ok(String::from_utf8_unchecked(v)),
            Err(_) => Err(Error)
        }
    }
}
<|endoftext|>


<commit_before>use log::{Log, LogLevel, LogRecord, LogMetadata};

pub struct ImagLogger {
    lvl: LogLevel,
}

impl ImagLogger {

    pub fn new(lvl: LogLevel) -> ImagLogger {
        ImagLogger {
            lvl: lvl,
        }
    }

}

impl Log for ImagLogger {

    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.lvl
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            // TODO: This is just simple logging. Maybe we can enhance this lateron
            println!("[imag][{: <5}]: {}", record.level(), record.args());
        }
    }
}

<commit_msg>Fix: libimagrt: Logging messages to stderr<commit_after>use std::io::Write;
use std::io::stderr;

use log::{Log, LogLevel, LogRecord, LogMetadata};

pub struct ImagLogger {
    lvl: LogLevel,
}

impl ImagLogger {

    pub fn new(lvl: LogLevel) -> ImagLogger {
        ImagLogger {
            lvl: lvl,
        }
    }

}

impl Log for ImagLogger {

    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.lvl
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            // TODO: This is just simple logging. Maybe we can enhance this lateron
            writeln!(stderr(), "[imag][{: <5}]: {}", record.level(), record.args());
        }
    }
}

<|endoftext|>


<commit_before>// https://leetcode.com/problems/best-poker-hand/
pub fn best_hand(ranks: Vec<i32>, suits: Vec<char>) -> String {
    todo!()
}

fn main() {
    println!(
        "{}",
        best_hand(vec![13, 2, 3, 1, 9], vec!['a', 'a', 'a', 'a', 'a'])
    ); // "Flush"
    println!(
        "{}",
        best_hand(vec![4, 4, 2, 4, 4], vec!['d', 'a', 'a', 'b', 'c'])
    ); // "Three of a Kind"
    println!(
        "{}",
        best_hand(vec![10, 10, 2, 12, 9], vec!['a', 'b', 'c', 'a', 'd'])
    ); // "Pair"
}
<commit_msg>Solve problem 2347<commit_after>use std::collections::HashMap;
use std::hash::Hash;

// https://leetcode.com/problems/best-poker-hand/
pub fn best_hand(ranks: Vec<i32>, suits: Vec<char>) -> String {
    fn build_map_counts<T>(v: &Vec<T>) -> HashMap<T, i32>
    where
        T: Copy + Eq + Hash,
    {
        let mut map_counts: HashMap<T, i32> = HashMap::new();
        v.iter().for_each(|e| {
            match map_counts.get(e) {
                Some(count) => map_counts.insert(*e, count + 1),
                None => map_counts.insert(*e, 1),
            };
        });
        return map_counts;
    }

    let suit_counts = build_map_counts(&suits);
    let rank_counts = build_map_counts(&ranks);
    if suit_counts.len() == 1 {
        "Flush".to_string()
    } else {
        let count = rank_counts.iter().max_by(|a, b| a.1.cmp(b.1)).unwrap().1;
        if *count >= 3 {
            "Three of a Kind".to_string()
        } else if *count == 2 {
            "Pair".to_string()
        } else {
            "High Card".to_string()
        }
    }
}

fn main() {
    println!(
        "{}",
        best_hand(vec![13, 2, 3, 1, 9], vec!['a', 'a', 'a', 'a', 'a'])
    ); // "Flush"
    println!(
        "{}",
        best_hand(vec![4, 4, 2, 4, 4], vec!['d', 'a', 'a', 'b', 'c'])
    ); // "Three of a Kind"
    println!(
        "{}",
        best_hand(vec![10, 10, 2, 12, 9], vec!['a', 'b', 'c', 'a', 'd'])
    ); // "Pair"
}
<|endoftext|>


<commit_before>//! Manager for XDG shell v6 client.

use libc;
use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::wlr_xdg_surface_v6;

use super::xdg_shell_v6_handler::XdgV6Shell;
use {Surface, SurfaceHandle, XdgV6ShellHandler, XdgV6ShellSurface};
use compositor::{Compositor, COMPOSITOR_PTR};

pub trait XdgV6ShellManagerHandler {
    /// Callback that is triggered when a new XDG shell v6 surface appears.
    fn new_surface(&mut self,
                   &mut Compositor,
                   &mut XdgV6ShellSurface,
                   &mut Surface)
                   -> Option<Box<XdgV6ShellHandler>>;

    /// Callback that is triggered when an XDG shell v6 surface is destroyed.
    fn surface_destroyed(&mut self, &mut Compositor, &mut XdgV6ShellSurface, &mut Surface);
}

wayland_listener!(XdgV6ShellManager, (Vec<Box<XdgV6Shell>>, Box<XdgV6ShellManagerHandler>), [
    add_listener => add_notify: |this: &mut XdgV6ShellManager, data: *mut libc::c_void,|
    unsafe {
        let remove_listener = this.remove_listener() as *mut _ as _;
        let (ref mut shells, ref mut manager) = this.data;
        let data = data as *mut wlr_xdg_surface_v6;
        wlr_log!(L_DEBUG, "New xdg_shell_v6_surface request {:p}", data);
        let compositor = &mut *COMPOSITOR_PTR;
        let mut surface = Surface::new((*data).surface);
        let mut shell_surface = XdgV6ShellSurface::new(data);
        surface.set_lock(true);
        shell_surface.set_lock(true);
        let new_surface_res = manager.new_surface(compositor, &mut shell_surface, &mut surface);
        surface.set_lock(false);
        shell_surface.set_lock(false);
        if let Some(shell_surface_handler) = new_surface_res {
            let mut shell_surface = XdgV6Shell::new((shell_surface,
                                                     surface,
                                                     shell_surface_handler));
            // Hook the destroy event into this manager.
            wl_signal_add(&mut (*data).events.destroy as *mut _ as _,
                          remove_listener);

            wl_signal_add(&mut (*data).events.ping_timeout as *mut _ as _,
                          shell_surface.ping_timeout_listener() as _);
            wl_signal_add(&mut (*data).events.new_popup as *mut _ as _,
                          shell_surface.new_popup_listener() as _);
            wl_signal_add(&mut (*data).events.request_maximize as *mut _ as _,
                          shell_surface.maximize_listener() as _);
            wl_signal_add(&mut (*data).events.request_fullscreen as *mut _ as _,
                          shell_surface.fullscreen_listener() as _);
            wl_signal_add(&mut (*data).events.request_minimize as *mut _ as _,
                          shell_surface.minimize_listener() as _);
            wl_signal_add(&mut (*data).events.request_move as *mut _ as _,
                          shell_surface.move_listener() as _);
            wl_signal_add(&mut (*data).events.request_resize as *mut _ as _,
                          shell_surface.resize_listener() as _);
            wl_signal_add(&mut (*data).events.request_show_window_menu as *mut _ as _,
                          shell_surface.show_window_menu_listener() as _);
            shells.push(shell_surface);
        }
    };
    remove_listener => remove_notify: |this: &mut XdgV6ShellManager, data: *mut libc::c_void,|
    unsafe {
        let (ref mut shells, ref mut manager) = this.data;
        let data = data as *mut wlr_xdg_surface_v6;
        let mut surface = SurfaceHandle::from_ptr((*data).surface);
        let compositor = &mut *COMPOSITOR_PTR;
        if let Some(shell) = shells.iter_mut().find(|shell| shell.surface_ptr() == data) {
            let mut shell_surface = shell.surface_mut();
            shell_surface.set_lock(true);
            surface.run(|mut surface| {
                manager.surface_destroyed(compositor, &mut shell_surface, &mut surface);
            }).expect("Surface was invalid")
        }
        if let Some(index) = shells.iter().position(|shell| shell.surface_ptr() == data) {
            let mut removed_shell = shells.remove(index);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.ping_timeout_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.new_popup_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.maximize_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.fullscreen_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.minimize_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.move_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.resize_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.show_window_menu_listener()).link as *mut _ as _);
        }
        // TODO Remove from list using iter().position
    };
]);
<commit_msg>Comment out the setup for xdg shell for now<commit_after>//! Manager for XDG shell v6 client.

use libc;
use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::wlr_xdg_surface_v6;

use super::xdg_shell_v6_handler::XdgV6Shell;
use {Surface, SurfaceHandle, XdgV6ShellHandler, XdgV6ShellSurface};
use compositor::{Compositor, COMPOSITOR_PTR};

pub trait XdgV6ShellManagerHandler {
    /// Callback that is triggered when a new XDG shell v6 surface appears.
    fn new_surface(&mut self,
                   &mut Compositor,
                   &mut XdgV6ShellSurface,
                   &mut Surface)
                   -> Option<Box<XdgV6ShellHandler>>;

    /// Callback that is triggered when an XDG shell v6 surface is destroyed.
    fn surface_destroyed(&mut self, &mut Compositor, &mut XdgV6ShellSurface, &mut Surface);
}

wayland_listener!(XdgV6ShellManager, (Vec<Box<XdgV6Shell>>, Box<XdgV6ShellManagerHandler>), [
    add_listener => add_notify: |this: &mut XdgV6ShellManager, data: *mut libc::c_void,|
    unsafe {
        let remove_listener = this.remove_listener() as *mut _ as _;
        let (ref mut shells, ref mut manager) = this.data;
        let data = data as *mut wlr_xdg_surface_v6;
        wlr_log!(L_DEBUG, "New xdg_shell_v6_surface request {:p}", data);
        let compositor = &mut *COMPOSITOR_PTR;
        let mut surface = Surface::new((*data).surface);
        let mut shell_surface = XdgV6ShellSurface::new(data);
        surface.set_lock(true);
        shell_surface.set_lock(true);
        let new_surface_res = manager.new_surface(compositor, &mut shell_surface, &mut surface);
        surface.set_lock(false);
        shell_surface.set_lock(false);
        if let Some(shell_surface_handler) = new_surface_res {
            let mut shell_surface = XdgV6Shell::new((shell_surface,
                                                     surface,
                                                     shell_surface_handler));
            // Hook the destroy event into this manager.
            wl_signal_add(&mut (*data).events.destroy as *mut _ as _,
                          remove_listener);

            wl_signal_add(&mut (*data).events.ping_timeout as *mut _ as _,
                          shell_surface.ping_timeout_listener() as _);
            wl_signal_add(&mut (*data).events.new_popup as *mut _ as _,
                          shell_surface.new_popup_listener() as _);
            // TODO We gotta costruct a top level / popup here and store it in the
            // XdgV6Shell so that the listeners can work properly....
            //
            // FIXME Consider the possiblity of borrowing the specific type during an
            // event fire? Aliasing possible? Not sure

            //wl_signal_add(&mut (*data).events.request_maximize as *mut _ as _,
            //              shell_surface.maximize_listener() as _);
            //wl_signal_add(&mut (*data).events.request_fullscreen as *mut _ as _,
            //              shell_surface.fullscreen_listener() as _);
            //wl_signal_add(&mut (*data).events.request_minimize as *mut _ as _,
            //              shell_surface.minimize_listener() as _);
            //wl_signal_add(&mut (*data).events.request_move as *mut _ as _,
            //              shell_surface.move_listener() as _);
            //wl_signal_add(&mut (*data).events.request_resize as *mut _ as _,
            //              shell_surface.resize_listener() as _);
            //wl_signal_add(&mut (*data).events.request_show_window_menu as *mut _ as _,
            //              shell_surface.show_window_menu_listener() as _);
            shells.push(shell_surface);
        }
    };
    remove_listener => remove_notify: |this: &mut XdgV6ShellManager, data: *mut libc::c_void,|
    unsafe {
        let (ref mut shells, ref mut manager) = this.data;
        let data = data as *mut wlr_xdg_surface_v6;
        let mut surface = SurfaceHandle::from_ptr((*data).surface);
        let compositor = &mut *COMPOSITOR_PTR;
        if let Some(shell) = shells.iter_mut().find(|shell| shell.surface_ptr() == data) {
            let mut shell_surface = shell.surface_mut();
            shell_surface.set_lock(true);
            surface.run(|mut surface| {
                manager.surface_destroyed(compositor, &mut shell_surface, &mut surface);
            }).expect("Surface was invalid")
        }
        if let Some(index) = shells.iter().position(|shell| shell.surface_ptr() == data) {
            let mut removed_shell = shells.remove(index);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.ping_timeout_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.new_popup_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.maximize_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.fullscreen_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.minimize_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.move_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.resize_listener()).link as *mut _ as _);
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*removed_shell.show_window_menu_listener()).link as *mut _ as _);
        }
        // TODO Remove from list using iter().position
    };
]);
<|endoftext|>


<commit_before>use syntax;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;

/// Create a fake ExtCtxt to perform macro quasiquotes outside of rustc plugins
pub fn with_fake_extctxt<T, F: Fn(&ExtCtxt) -> T>(f: F) -> T {
  let ps = syntax::parse::ParseSess::new();

  let mut cx = syntax::ext::base::ExtCtxt::new(&ps, Vec::new(),
    syntax::ext::expand::ExpansionConfig::default("rust-peg".to_string())
  );

  cx.bt_push(syntax::codemap::ExpnInfo{
    call_site: DUMMY_SP,
    callee: syntax::codemap::NameAndSpan {
      name: "".to_string(),
      format: syntax::codemap::MacroBang,
      span: None,
      allow_internal_unstable: false,
    }
  });

  f(&cx)
}
<commit_msg>Add newly-required additional argument to ExtCtxt::new().<commit_after>use syntax;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;
use syntax::feature_gate::GatedCfg;

/// Create a fake ExtCtxt to perform macro quasiquotes outside of rustc plugins
pub fn with_fake_extctxt<T, F: Fn(&ExtCtxt) -> T>(f: F) -> T {
  let ps = syntax::parse::ParseSess::new();
  let mut fg_cfg = Vec::<GatedCfg>::new();

  let mut cx = syntax::ext::base::ExtCtxt::new(&ps, Vec::new(),
    syntax::ext::expand::ExpansionConfig::default("rust-peg".to_string()),
    &mut fg_cfg
  );

  cx.bt_push(syntax::codemap::ExpnInfo{
    call_site: DUMMY_SP,
    callee: syntax::codemap::NameAndSpan {
      name: "".to_string(),
      format: syntax::codemap::MacroBang,
      span: None,
      allow_internal_unstable: false,
    }
  });

  f(&cx)
}
<|endoftext|>