<commit_before>//! A brush for generative fine art.

mod gpu;
mod noise_traits;
mod raster;
mod render;

pub mod canvas;
pub mod forms;
pub mod paint;
pub mod path;
pub mod shaders;
pub mod transforms;
pub mod uniforms;

/// Exhuastive set of imports for painting.
pub mod prelude {
    pub use self::{
        canvas::*,
        forms::*,
        paint::*,
        path::*,
        shaders::*,
        transforms::*,
        uniforms::*,
    };
    pub use super::*;
    pub use euclid::{self, Rect};
    pub use noise::{self, *};
    pub use noise_traits::*;
    pub use rayon::{self, prelude::*};

    pub use palette::{
        self,
        encoding::Srgb,
        Alpha,
        Blend,
        ComponentWise,
        Hue,
        IntoColor,
        LinSrgb,
        LinSrgba,
        Saturate,
        *,
    };
    pub use rand::{self, rngs::StdRng, Rng, SeedableRng};
    pub use structopt::StructOpt;

    pub use std::f32::consts::PI;
}

pub use self::{
    gpu::{Gpu, Shader},
    render::Context,
    shaders::ShaderProgram,
};

use self::{gpu::*, prelude::*, raster::Method};
use euclid::{Point3D, Size2D, UnknownUnit, Vector2D, Vector3D};
use failure::Error;
use lyon_path::math::Point;
use render::*;
use std::{path::PathBuf, time::Duration};

/// A two dimensional point.
pub type P2 = Point;

/// A three dimensional point.
pub type P3 = Point3D<f32, UnknownUnit>;

/// A two dimensional vector.
pub type V2 = Vector2D<f32, UnknownUnit>;

/// A three dimensional vector.
pub type V3 = Vector3D<f32, UnknownUnit>;

/// A two dimensional size.
pub type S2 = Size2D<f32, UnknownUnit>;

/// An angle.
pub type Angle = euclid::Angle<f32>;

/// A compiled GLSL program.
pub type Program = glium::program::Program;

/// A value or an error.
pub type Result<T> = std::result::Result<T, Error>;

/// Command line options for a painting run.
///
/// Construct with `Options::from_args()` to run the CLI.
#[derive(StructOpt, Debug, Clone)]
#[structopt(name = "valora")]
pub struct Options {
    #[structopt(flatten)]
    pub world: World,

    /// In brainstorm mode:
    ///
    ///   * When rendering a limited number of frames to screen, the preview will not close.
    ///
    ///   * When rendering to file, every frame will be rendered with a different seed.
    #[structopt(short = "b", long = "brainstorm")]
    pub brainstorm: bool,

    /// The number of frames to delay saving to file. For example, if delay=100,
    /// 100 frames will be rendered silently and then the 101st and those after it
    /// will be saved to file.
    #[structopt(short = "d", long = "delay", default_value = "0")]
    pub delay: usize,

    /// Prefix of output path. Output is <prefix>/<seed>/<frame_number>.png
    #[structopt(short = "o", long = "output", parse(from_os_str))]
    pub output: Option<PathBuf>,
}

/// The world in which the painting takes place.
#[derive(StructOpt, Debug, Copy, Clone)]
#[structopt(name = "world")]
pub struct World {
    /// The RNG seed for this painting.
    #[structopt(short = "e", long = "seed", default_value = "0")]
    pub seed: u64,

    /// The width in coordinate space of the painting.
    ///
    /// Coordinate space may differ from output space. If width is 500 but scale is 10, the painting
    /// will have a coordinate space width of 500, but the final output will have a width of 5000 pixels.
    #[structopt(short = "w", long = "width", default_value = "512")]
    pub width: f32,
    /// The height in coordinate space of the painting.
    ///
    /// Coordinate space may differ from output space. If height is 500 but scale is 10, the painting
    /// will have a coordinate space height of 500, but the final output will have a height of 5000 pixels.
    #[structopt(short = "h", long = "height", default_value = "650")]
    pub height: f32,

    /// The scale of the output.
    ///
    /// The final output space is (width*scale)x(height*scale). This value is useful for painting
    /// and doing work at one quickly rendering resolution, and later exporting at a much higher
    /// resolution while preserving the composition exactly.
    ///
    /// This value may be needed when writing shaders or using other raster graphics, to adjust them
    /// for the real output size. Vector painting such as with paths should not need to consider this.
    #[structopt(short = "s", long = "scale", default_value = "1.0")]
    pub scale: f32,

    /// The total number of frames in this painting.
    #[structopt(short = "f", long = "frames")]
    pub frames: Option<usize>,

    /// The number of frames (to try) to render per second.
    #[structopt(short = "r", long = "frames_per_second", default_value = "24")]
    pub framerate: usize,
}

impl World {
    /// Normalizes coordinates into the range [0, 1] by dividing them by the coordinate space dimensions.
    pub fn normalize(&self, p: P2) -> P2 { P2::new(p.x / self.width, p.y / self.height) }

    /// Returns the center of the coordinate space.
    pub fn center(&self) -> P2 { P2::new(self.width / 2.0, self.height / 2.0) }
}

/// Draws a rectangle path covering the entire canvas.
impl Paint for World {
    fn paint(&self, comp: &mut Canvas) {
        comp.line_to(P2::new(0.0, 0.0));
        comp.line_to(P2::new(self.width, 0.0));
        comp.line_to(P2::new(self.width, self.height));
        comp.line_to(P2::new(0.0, self.height));
        comp.line_to(P2::new(0.0, 0.0));
    }
}

/// A trait for types which paint canvases.
pub trait Artist: Sized {
    /// Constructs the artist.
    ///
    /// This would be a place to compile any GLSL or construct any expensive
    /// resources needed across the whole composition.
    fn setup(gpu: Gpu, world: World, rng: &mut StdRng) -> Result<Self>;

    /// Paints a single frame.
    fn paint(&mut self, ctx: Context, canvas: &mut Canvas);
}

/// Run an artist defined by raw functions.
///
/// Takes a function that produces the function that should paint each frame.
pub fn run_fn<F>(options: Options, f: impl Fn(Gpu, World, &mut StdRng) -> Result<F>) -> Result<()>
where
    F: FnMut(Context, &mut Canvas),
{
    let (output_width, output_height) = (
        (options.world.width as f32 * options.world.scale) as u32,
        (options.world.height as f32 * options.world.scale) as u32,
    );

    let number_width = options
        .world
        .frames
        .unwrap_or(0)
        .to_string()
        .chars()
        .count();

    let (gpu, mut strategy) = if let Some(base_path) = options.output.clone() {
        let (gpu, _) = Gpu::new()?;
        let buffer = gpu.build_texture(output_width, output_height)?;

        (
            gpu,
            RenderStrategy::File {
                buffer,
                output_path: move |frame_number: usize, seed: u64| {
                    let mut base_path = base_path.clone();
                    base_path.push(format!("{}", seed));
                    std::fs::create_dir_all(&base_path)
                        .expect(&format!("To create save directory {:?}", base_path));
                    base_path.push(format!(
                        "{number:>0width$}.png",
                        number = frame_number,
                        width = number_width
                    ));
                    base_path
                },
            },
        )
    } else {
        let (gpu, events_loop, (screen_width, screen_height)) =
            Gpu::with_window(output_width, output_height)?;
        let buffer = gpu.build_texture(screen_width, screen_height)?;

        let wait = Duration::from_secs_f64(1. / options.world.framerate as f64);
        let gpu_clone = gpu.clone();

        let texture_glsl = include_str!("shaders/texture.frag");
        let texture_program = gpu.compile_glsl(texture_glsl)?;

        (
            gpu,
            RenderStrategy::Screen {
                events_loop,
                wait,
                buffer,
                texture_program,
                get_frame: move || {
                    gpu_clone
                        .get_frame()
                        .expect("To get frame from windowed gpu")
                },
            },
        )
    };

    let mut current_seed = options.world.seed;
    loop {
        let mut rng = StdRng::seed_from_u64(current_seed);
        let mut paint_fn = f(gpu.clone(), options.world, &mut rng)?;

        let mut renderer = Renderer {
            strategy: &mut strategy,
            gpu: &gpu,
            options: Options {
                world: World {
                    seed: current_seed,
                    ..options.world
                },
                ..options.clone()
            },
            rng: &mut rng,
            output_width: output_width,
            output_height: output_height,
        };

        let report = renderer.render_frames(|ctx, canvas| paint_fn(ctx, canvas))?;

        if let Some(rebuild) = report.rebuild {
            match rebuild {
                Rebuild::NewSeed(new_seed) => {
                    current_seed = new_seed;
                }
            }
        } else if report.explicit_quit || !options.brainstorm || options.output.is_some() {
            break;
        }
    }

    Ok(())
}

/// Run an artist.
pub fn run<A: Artist>(options: Options) -> Result<()> {
    run_fn(options, |gpu, world, rng| {
        let mut artist = A::setup(gpu, world, rng)?;
        Ok(move |ctx: Context, canvas: &mut Canvas| artist.paint(ctx, canvas))
    })
}
<commit_msg>Render each seed in brainstorm to file mode<commit_after>//! A brush for generative fine art.

mod gpu;
mod noise_traits;
mod raster;
mod render;

pub mod canvas;
pub mod forms;
pub mod paint;
pub mod path;
pub mod shaders;
pub mod transforms;
pub mod uniforms;

/// Exhuastive set of imports for painting.
pub mod prelude {
    pub use self::{
        canvas::*,
        forms::*,
        paint::*,
        path::*,
        shaders::*,
        transforms::*,
        uniforms::*,
    };
    pub use super::*;
    pub use euclid::{self, Rect};
    pub use noise::{self, *};
    pub use noise_traits::*;
    pub use rayon::{self, prelude::*};

    pub use palette::{
        self,
        encoding::Srgb,
        Alpha,
        Blend,
        ComponentWise,
        Hue,
        IntoColor,
        LinSrgb,
        LinSrgba,
        Saturate,
        *,
    };
    pub use rand::{self, rngs::StdRng, Rng, SeedableRng};
    pub use structopt::StructOpt;

    pub use std::f32::consts::PI;
}

pub use self::{
    gpu::{Gpu, Shader},
    render::Context,
    shaders::ShaderProgram,
};

use self::{gpu::*, prelude::*, raster::Method};
use euclid::{Point3D, Size2D, UnknownUnit, Vector2D, Vector3D};
use failure::Error;
use lyon_path::math::Point;
use render::*;
use std::{path::PathBuf, time::Duration};

/// A two dimensional point.
pub type P2 = Point;

/// A three dimensional point.
pub type P3 = Point3D<f32, UnknownUnit>;

/// A two dimensional vector.
pub type V2 = Vector2D<f32, UnknownUnit>;

/// A three dimensional vector.
pub type V3 = Vector3D<f32, UnknownUnit>;

/// A two dimensional size.
pub type S2 = Size2D<f32, UnknownUnit>;

/// An angle.
pub type Angle = euclid::Angle<f32>;

/// A compiled GLSL program.
pub type Program = glium::program::Program;

/// A value or an error.
pub type Result<T> = std::result::Result<T, Error>;

/// Command line options for a painting run.
///
/// Construct with `Options::from_args()` to run the CLI.
#[derive(StructOpt, Debug, Clone)]
#[structopt(name = "valora")]
pub struct Options {
    #[structopt(flatten)]
    pub world: World,

    /// In brainstorm mode:
    ///
    ///   * When rendering a limited number of frames to screen, the preview will not close.
    ///
    ///   * When rendering to file, every frame will be rendered with a different seed.
    #[structopt(short = "b", long = "brainstorm")]
    pub brainstorm: bool,

    /// The number of frames to delay saving to file. For example, if delay=100,
    /// 100 frames will be rendered silently and then the 101st and those after it
    /// will be saved to file.
    #[structopt(short = "d", long = "delay", default_value = "0")]
    pub delay: usize,

    /// Prefix of output path. Output is <prefix>/<seed>/<frame_number>.png
    #[structopt(short = "o", long = "output", parse(from_os_str))]
    pub output: Option<PathBuf>,
}

/// The world in which the painting takes place.
#[derive(StructOpt, Debug, Copy, Clone)]
#[structopt(name = "world")]
pub struct World {
    /// The RNG seed for this painting.
    #[structopt(short = "e", long = "seed", default_value = "0")]
    pub seed: u64,

    /// The width in coordinate space of the painting.
    ///
    /// Coordinate space may differ from output space. If width is 500 but scale is 10, the painting
    /// will have a coordinate space width of 500, but the final output will have a width of 5000 pixels.
    #[structopt(short = "w", long = "width", default_value = "512")]
    pub width: f32,
    /// The height in coordinate space of the painting.
    ///
    /// Coordinate space may differ from output space. If height is 500 but scale is 10, the painting
    /// will have a coordinate space height of 500, but the final output will have a height of 5000 pixels.
    #[structopt(short = "h", long = "height", default_value = "650")]
    pub height: f32,

    /// The scale of the output.
    ///
    /// The final output space is (width*scale)x(height*scale). This value is useful for painting
    /// and doing work at one quickly rendering resolution, and later exporting at a much higher
    /// resolution while preserving the composition exactly.
    ///
    /// This value may be needed when writing shaders or using other raster graphics, to adjust them
    /// for the real output size. Vector painting such as with paths should not need to consider this.
    #[structopt(short = "s", long = "scale", default_value = "1.0")]
    pub scale: f32,

    /// The total number of frames in this painting.
    #[structopt(short = "f", long = "frames")]
    pub frames: Option<usize>,

    /// The number of frames (to try) to render per second.
    #[structopt(short = "r", long = "frames_per_second", default_value = "24")]
    pub framerate: usize,
}

impl World {
    /// Normalizes coordinates into the range [0, 1] by dividing them by the coordinate space dimensions.
    pub fn normalize(&self, p: P2) -> P2 { P2::new(p.x / self.width, p.y / self.height) }

    /// Returns the center of the coordinate space.
    pub fn center(&self) -> P2 { P2::new(self.width / 2.0, self.height / 2.0) }
}

/// Draws a rectangle path covering the entire canvas.
impl Paint for World {
    fn paint(&self, comp: &mut Canvas) {
        comp.line_to(P2::new(0.0, 0.0));
        comp.line_to(P2::new(self.width, 0.0));
        comp.line_to(P2::new(self.width, self.height));
        comp.line_to(P2::new(0.0, self.height));
        comp.line_to(P2::new(0.0, 0.0));
    }
}

/// A trait for types which paint canvases.
pub trait Artist: Sized {
    /// Constructs the artist.
    ///
    /// This would be a place to compile any GLSL or construct any expensive
    /// resources needed across the whole composition.
    fn setup(gpu: Gpu, world: World, rng: &mut StdRng) -> Result<Self>;

    /// Paints a single frame.
    fn paint(&mut self, ctx: Context, canvas: &mut Canvas);
}

/// Run an artist defined by raw functions.
///
/// Takes a function that produces the function that should paint each frame.
pub fn run_fn<F>(options: Options, f: impl Fn(Gpu, World, &mut StdRng) -> Result<F>) -> Result<()>
where
    F: FnMut(Context, &mut Canvas),
{
    let (output_width, output_height) = (
        (options.world.width as f32 * options.world.scale) as u32,
        (options.world.height as f32 * options.world.scale) as u32,
    );

    let number_width = options
        .world
        .frames
        .unwrap_or(0)
        .to_string()
        .chars()
        .count();

    let (gpu, mut strategy) = if let Some(base_path) = options.output.clone() {
        let (gpu, _) = Gpu::new()?;
        let buffer = gpu.build_texture(output_width, output_height)?;

        (
            gpu,
            RenderStrategy::File {
                buffer,
                output_path: move |frame_number: usize, seed: u64| {
                    let mut base_path = base_path.clone();
                    base_path.push(format!("{}", seed));
                    std::fs::create_dir_all(&base_path)
                        .expect(&format!("To create save directory {:?}", base_path));
                    base_path.push(format!(
                        "{number:>0width$}.png",
                        number = frame_number,
                        width = number_width
                    ));
                    base_path
                },
            },
        )
    } else {
        let (gpu, events_loop, (screen_width, screen_height)) =
            Gpu::with_window(output_width, output_height)?;
        let buffer = gpu.build_texture(screen_width, screen_height)?;

        let wait = Duration::from_secs_f64(1. / options.world.framerate as f64);
        let gpu_clone = gpu.clone();

        let texture_glsl = include_str!("shaders/texture.frag");
        let texture_program = gpu.compile_glsl(texture_glsl)?;

        (
            gpu,
            RenderStrategy::Screen {
                events_loop,
                wait,
                buffer,
                texture_program,
                get_frame: move || {
                    gpu_clone
                        .get_frame()
                        .expect("To get frame from windowed gpu")
                },
            },
        )
    };

    let mut current_seed = options.world.seed;
    let mut render_count = 0;
    loop {
        let mut rng = StdRng::seed_from_u64(current_seed);
        let mut paint_fn = f(gpu.clone(), options.world, &mut rng)?;

        let mut renderer = Renderer {
            strategy: &mut strategy,
            gpu: &gpu,
            options: Options {
                world: World {
                    seed: current_seed,
                    frames: match (options.brainstorm, options.output.as_ref()) {
                        (true, Some(_)) => Some(1),
                        _ => options.world.frames,
                    },
                    ..options.world
                },
                ..options.clone()
            },
            rng: &mut rng,
            output_width: output_width,
            output_height: output_height,
        };

        let report = renderer.render_frames(|ctx, canvas| paint_fn(ctx, canvas))?;

        if let Some(rebuild) = report.rebuild {
            match rebuild {
                Rebuild::NewSeed(new_seed) => {
                    current_seed = new_seed;
                }
            }
        } else if options.brainstorm
            && options.output.is_some()
            && render_count < options.world.frames.unwrap_or(usize::max_value())
        {
            current_seed += 1;
        } else if report.explicit_quit || !options.brainstorm || options.output.is_some() {
            break;
        }

        render_count += 1;
    }

    Ok(())
}

/// Run an artist.
pub fn run<A: Artist>(options: Options) -> Result<()> {
    run_fn(options, |gpu, world, rng| {
        let mut artist = A::setup(gpu, world, rng)?;
        Ok(move |ctx: Context, canvas: &mut Canvas| artist.paint(ctx, canvas))
    })
}
<|endoftext|>


<commit_before>#![feature(old_io)]

extern crate xml;

use xml::attribute::Attribute;
use xml::common::XmlVersion;
use xml::name::Name;
use xml::namespace::Namespace;
use xml::writer::EventWriter;
use xml::writer::events::XmlEvent;

trait Write {
    fn write<W: Writer>(&self, writer: W) -> Result<(), ()>;
}

trait ToXml<'a> {
    // todo: get rid of namespace parameter
    fn to_xml(&'a self, namespace: &'a Namespace) -> Vec<XmlEvent>;
}

/// RSS version 2.0
pub struct Rss(pub Vec<Channel>);

impl<'a> ToXml<'a> for Rss {
    fn to_xml(&'a self, namespace: &'a Namespace) -> Vec<XmlEvent> {
        let mut events = vec![];

        // <?xml version="1.0" encoding="UTF-8"?>
        events.push(XmlEvent::StartDocument{
            version: XmlVersion::Version10,
            encoding: Some("UTF-8"),
            standalone: None,
        });

        // <rss version="2.0">
        events.push(XmlEvent::StartElement {
            name: Name::local("rss"),
            attributes: vec![
                Attribute::new(Name::local("version"), "2.0"),
            ],
            namespace: namespace,
        });

        /*
        let &Rss(ref channels) = self;
        for channel in channels {
            for event in channel.to_xml(namespace) {
                events.push(event);
            }
        }
        */

        // </rss>
        events.push(XmlEvent::EndElement {
            name: Name::local("rss"),
        });

        events
    }
}

impl Write for Rss {
    fn write<W: Writer>(&self, writer: W) -> Result<(), ()> {
        let mut event_writer = EventWriter::new(writer);

        let namespace = Namespace::empty();
        let events = self.to_xml(&namespace);

        for event in events {
            event_writer.write(event);
        };

        Ok(())
    }
}

pub struct Channel {
    pub title: String,
    pub link: String,
    pub description: String,
    pub items: Vec<Item>,
}

/*
impl<'a> ToXml<'a> for Channel {
    fn to_xml(&self) -> Vec<XmlEvent> {
        vec![]
    }
}
*/

pub struct Item {
    pub title: Option<String>,
    pub link: Option<String>,
    pub description: Option<String>,
}

#[test]
fn test_consruct() {
    use std::old_io;
    let rss = Rss(vec![]);
    rss.write(old_io::stdout());
}
<commit_msg>Implement to_xml for Channel<commit_after>#![feature(old_io)]

extern crate xml;

use xml::attribute::Attribute;
use xml::common::XmlVersion;
use xml::name::Name;
use xml::namespace::Namespace;
use xml::writer::EventWriter;
use xml::writer::events::XmlEvent;

fn add_block<'a>(events: &mut Vec<XmlEvent<'a>>, namespace: &'a Namespace, tag_name: &'static str, chars: &'a String) {
    // <(tag_name)>
    events.push(XmlEvent::StartElement {
        name: Name::local(tag_name),
        attributes: vec![],
        namespace: namespace,
    });

    events.push(XmlEvent::Characters(chars));

    // </(tag_name)>
    events.push(XmlEvent::EndElement {
        name: Name::local(tag_name),
    });
}

trait Write {
    fn write<W: Writer>(&self, writer: W) -> Result<(), ()>;
}

trait ToXml<'a> {
    // todo: get rid of namespace parameter
    fn to_xml(&'a self, namespace: &'a Namespace) -> Vec<XmlEvent>;
}

/// RSS version 2.0
pub struct Rss(pub Vec<Channel>);

impl<'a> ToXml<'a> for Rss {
    fn to_xml(&'a self, namespace: &'a Namespace) -> Vec<XmlEvent> {
        let mut events = vec![];

        // <?xml version="1.0" encoding="UTF-8"?>
        events.push(XmlEvent::StartDocument{
            version: XmlVersion::Version10,
            encoding: Some("UTF-8"),
            standalone: None,
        });

        // <rss version="2.0">
        events.push(XmlEvent::StartElement {
            name: Name::local("rss"),
            attributes: vec![
                Attribute::new(Name::local("version"), "2.0"),
            ],
            namespace: namespace,
        });

        let &Rss(ref channels) = self;
        for channel in channels {
            for event in channel.to_xml(namespace) {
                events.push(event);
            }
        }

        // </rss>
        events.push(XmlEvent::EndElement {
            name: Name::local("rss"),
        });

        events
    }
}

impl Write for Rss {
    fn write<W: Writer>(&self, writer: W) -> Result<(), ()> {
        let mut event_writer = EventWriter::new(writer);

        let namespace = Namespace::empty();
        let events = self.to_xml(&namespace);

        for event in events {
            event_writer.write(event);
        };

        Ok(())
    }
}

pub struct Channel {
    pub title: String,
    pub link: String,
    pub description: String,
    pub items: Vec<Item>,
}

impl<'a> ToXml<'a> for Channel {
    fn to_xml(&'a self, namespace: &'a Namespace) -> Vec<XmlEvent> {
        let mut events = vec![];

        // <channel>
        events.push(XmlEvent::StartElement {
            name: Name::local("channel"),
            attributes: vec![],
            namespace: namespace,
        });

        add_block(&mut events, namespace, "title", &self.title);
        add_block(&mut events, namespace, "link", &self.link);
        add_block(&mut events, namespace, "description", &self.description);

        // </channel>
        events.push(XmlEvent::EndElement {
            name: Name::local("channel"),
        });

        events
    }
}

pub struct Item {
    pub title: Option<String>,
    pub link: Option<String>,
    pub description: Option<String>,
}

#[test]
fn test_consruct() {
    use std::old_io;

    let channel = Channel {
        title: String::from_str("My Blog"),
        link: String::from_str("http://myblog.com"),
        description: String::from_str("Where I write stuff"),
        items: vec![],
    };

    let rss = Rss(vec![channel]);
    rss.write(old_io::stdout());
}
<|endoftext|>


<commit_before>use std::fs;
use std::io;
use std::io::{Write,Read};
use std::path::PathBuf;
#[macro_use]
extern crate json;
extern crate git2;
use git2::Repository;

struct Config {
    class_name: String,
    master_repo: String,
    description: String
}

struct Student {
    name: String,
    repo: String
}

pub fn new(name: &str) {
    match fs::create_dir(name) {
        Ok(_) => init(name),
        Err(e) => println!("Couldn't create: {}",e)
    }
}

pub fn init(path: &str) {
    println!("initalizing at {}", path);
    let config: Config = get_init_options();
    let config_json = object!{
        "className" => config.class_name.trim(),
        "description" => config.description.trim(),
        "masterRepo" => config.master_repo.trim(),
        "students" => json::JsonValue::new_object()
    };
    write_config_json(json::stringify_pretty(config_json,4), path)
}

pub fn add() {
    let mut config_json = get_config_json().unwrap();
    let student = get_student_details();
    let student_json = object!(
        "name" => student.name.trim(),
        "repo" => student.repo.trim()
    );
    config_json["students"][student.name.trim()] = student_json;
    write_config_json(json::stringify_pretty(config_json,4), "./");
    clone_repo(student.repo.as_str(), student.name.as_str());
}

pub fn remove(name: &str) {
    let mut config_json = get_config_json().unwrap();
    if config_json["students"].has_key(name) {
        println!("Removing {}", name);
        config_json["students"].remove(name);
        fs::remove_dir_all(name);
        write_config_json(json::stringify_pretty(config_json,4), "./");
    } else {
        println!("Student {} not known.",name);
    }
}

pub fn update() {
    println!("Updating student repos");
    let config_json = get_config_json().unwrap();
    let students = config_json["students"].entries();
    for s in students {
        println!("Updating {}",s.0);
        update_repo(s.1.clone());
    }
}

fn write_config_json(data: String, path: &str) {
    let mut init_path: PathBuf = PathBuf::from(path);
    init_path.push("gitclass.json");
    let mut f = fs::File::create(init_path.as_path()).unwrap();
    // let out_str = json::stringify_pretty(obj, 4);
    println!("{}",data);
    f.write(data.as_bytes());
}

fn get_config_json() -> Result<json::JsonValue, json::Error> {
    let mut f = fs::File::open("gitclass.json").unwrap();
    let mut config_str = String::new();
    f.read_to_string(&mut config_str);
    json::parse(config_str.as_str())
}

fn get_init_options() -> Config {
    let mut class_name = String::new();
    println!("Enter your class's name: ");
    io::stdin().read_line(&mut class_name);
    let mut master_repo = String::new();
    println!("Enter the master repo: ");
    io::stdin().read_line(&mut master_repo);
    println!("Enter the description: ");
    let mut description = String::new();
    io::stdin().read_line(&mut description);
    return Config {
        class_name: class_name,
        master_repo: master_repo,
        description: description
    }
}

fn get_student_details() -> Student {
    let mut name = String::new();
    println!("Student name: ");
    io::stdin().read_line(&mut name);
    let mut repo = String::new();
    println!("Student repo: ");
    io::stdin().read_line(&mut repo);
    return Student {
        name: name,
        repo: repo
    }
}

fn clone_repo(url: &str, path: &str) -> git2::Repository {
    match Repository::clone(url.trim(), path.trim()) {
        Ok(repo) => repo,
        Err(e) => panic!("failed to clone: {}", e),
    }
}

fn update_repo(student: json::JsonValue) {
    let path = student["name"].as_str().unwrap();
    let url = student["repo"].as_str().unwrap();
    fs::remove_dir_all(path);
    clone_repo(url, path);
}
<commit_msg>Add error checking<commit_after>use std::fs;
use std::io;
use std::io::{Write,Read};
use std::path::PathBuf;
#[macro_use]
extern crate json;
extern crate git2;
use git2::Repository;

struct Config {
    class_name: String,
    master_repo: String,
    description: String
}

struct Student {
    name: String,
    repo: String
}

pub fn new(name: &str) {
    match fs::create_dir(name) {
        Ok(_) => init(name),
        Err(e) => println!("Couldn't create: {}",e)
    }
}

pub fn init(path: &str) {
    println!("initalizing at {}", path);
    let config: Config = get_init_options();
    let config_json = object!{
        "className" => config.class_name.trim(),
        "description" => config.description.trim(),
        "masterRepo" => config.master_repo.trim(),
        "students" => json::JsonValue::new_object()
    };
    write_config_json(json::stringify_pretty(config_json,4), path)
}

pub fn add() {
    let mut config_json = get_config_json().unwrap();
    let student = get_student_details();
    let student_json = object!(
        "name" => student.name.trim(),
        "repo" => student.repo.trim()
    );
    config_json["students"][student.name.trim()] = student_json;
    write_config_json(json::stringify_pretty(config_json,4), "./");
    clone_repo(student.repo.as_str(), student.name.as_str());
}

pub fn remove(name: &str) {
    let mut config_json = get_config_json().unwrap();
    if config_json["students"].has_key(name) {
        println!("Removing {}", name);
        config_json["students"].remove(name);
        match fs::remove_dir_all(name) {
            Ok(_) => println!("Removed {}",name),
            Err(e) => panic!("Couldn't remove!: {}",e)
        };
        write_config_json(json::stringify_pretty(config_json,4), "./");
    } else {
        println!("Student {} not known.",name);
    }
}

pub fn update() {
    println!("Updating student repos");
    let config_json = get_config_json().unwrap();
    let students = config_json["students"].entries();
    for s in students {
        println!("Updating {}",s.0);
        update_repo(s.1.clone());
    }
}

fn write_config_json(data: String, path: &str) {
    let mut init_path: PathBuf = PathBuf::from(path);
    init_path.push("gitclass.json");
    let mut f = fs::File::create(init_path.as_path()).unwrap();
    // let out_str = json::stringify_pretty(obj, 4);
    println!("{}",data);
    match f.write(data.as_bytes()) {
        Ok(_) => println!("Config updated"),
        Err(e) => panic!("Config not updated: {}",e)
    };
}

fn get_config_json() -> Result<json::JsonValue, json::Error> {
    let mut f = fs::File::open("gitclass.json").unwrap();
    let mut config_str = String::new();
    match f.read_to_string(&mut config_str) {
        Ok(_) => println!("Config loaded"),
        Err(e) => panic!("Couldn't load config: {}",e)
    };
    json::parse(config_str.as_str())
}

fn get_init_options() -> Config {
    let mut class_name = String::new();
    println!("Enter your class's name: ");
    match io::stdin().read_line(&mut class_name) {
        Ok(_) => {},
        Err(e) => panic!("Couldn't read name: {}",e)
    };
    let mut master_repo = String::new();
    println!("Enter the master repo: ");
    match io::stdin().read_line(&mut master_repo) {
        Ok(_) => {},
        Err(e) => panic!("Couldn't read repo: {}",e)
    };
    println!("Enter the description: ");
    let mut description = String::new();
    match io::stdin().read_line(&mut description) {
        Ok(_) => {},
        Err(e) => panic!("Couldn't read description: {}",e)
    };
    return Config {
        class_name: class_name,
        master_repo: master_repo,
        description: description
    }
}

fn get_student_details() -> Student {
    let mut name = String::new();
    println!("Student name: ");
    match io::stdin().read_line(&mut name) {
        Ok(_) => {},
        Err(e) => panic!("Couldn't read name: {}",e)
    };
    let mut repo = String::new();
    println!("Student repo: ");
    match io::stdin().read_line(&mut repo) {
        Ok(_) => {},
        Err(e) => panic!("Couldn't read repo: {}",e)
    };
    return Student {
        name: name,
        repo: repo
    }
}

fn clone_repo(url: &str, path: &str) -> git2::Repository {
    match Repository::clone(url.trim(), path.trim()) {
        Ok(repo) => repo,
        Err(e) => panic!("failed to clone: {}", e),
    }
}

fn update_repo(student: json::JsonValue) {
    let path = student["name"].as_str().unwrap();
    let url = student["repo"].as_str().unwrap();
    match fs::remove_dir_all(path) {
        Ok(_) => {},
        Err(e) => panic!("Couldn't remove: {}",e)
    };
    clone_repo(url, path);
}
<|endoftext|>


<commit_before>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// 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::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of crate published to the index
#[derive(RustcDecodable)]
pub struct Version {
    pub name: String,
    pub vers: String,
    pub deps: Vec<Dependency>,
    pub cksum: String,
    pub features: HashMap<String, Vec<String>>,
    pub yanked: bool,
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable)]
pub struct Dependency {
    pub name: String,
    pub req: String,
    pub features: Vec<String>,
    pub optional: bool,
    pub default_features: bool,
    pub target: Option<String>,
    pub kind: Option<String>
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self)  -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index{path: path}
    }

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

    /// Clones the index to the path specified from the constructor
    pub fn clone(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(|p| Crate::new(&p))
    }

    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone())  // TODO: remove this clone
    }

    /// Generates a map of dependencies where the keys are crate names and the values are vectors
    /// of crate names that are its dependencies
    pub fn dependency_map(&self) -> HashMap<String, Vec<String>> {
        let mut map = HashMap::new();
        for crate_ in self.crates() {
            let version = crate_.latest_version();
            let mut deps_names = version.deps.iter().map(|d| d.name.clone()).collect::<Vec<_>>();
            deps_names.sort_by(|a, b| a.cmp(b));
            deps_names.dedup();
            map.insert(version.name.clone(), deps_names);
        }

        map
    }
}

pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
}
<commit_msg>Extend the extremely lame test case to an extremely lamer test case<commit_after>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// 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::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of crate published to the index
#[derive(RustcDecodable)]
pub struct Version {
    pub name: String,
    pub vers: String,
    pub deps: Vec<Dependency>,
    pub cksum: String,
    pub features: HashMap<String, Vec<String>>,
    pub yanked: bool,
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable)]
pub struct Dependency {
    pub name: String,
    pub req: String,
    pub features: Vec<String>,
    pub optional: bool,
    pub default_features: bool,
    pub target: Option<String>,
    pub kind: Option<String>
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self)  -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index{path: path}
    }

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

    /// Clones the index to the path specified from the constructor
    pub fn clone(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(|p| Crate::new(&p))
    }

    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone())  // TODO: remove this clone
    }

    /// Generates a map of dependencies where the keys are crate names and the values are vectors
    /// of crate names that are its dependencies
    pub fn dependency_map(&self) -> HashMap<String, Vec<String>> {
        let mut map = HashMap::new();
        for crate_ in self.crates() {
            let version = crate_.latest_version();
            let mut deps_names = version.deps.iter().map(|d| d.name.clone()).collect::<Vec<_>>();
            deps_names.sort_by(|a, b| a.cmp(b));
            deps_names.dedup();
            map.insert(version.name.clone(), deps_names);
        }

        map
    }
}

pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
    let crate_ = index.crates().nth(0).unwrap();
    let version = crate_.latest_version();
    let _ = version.deps;
}
<|endoftext|>


<commit_before>#[macro_use] extern crate log;

extern crate byteorder;
extern crate dns_parser;
extern crate futures;
extern crate libc;
extern crate multimap;
extern crate net2;
extern crate nix;
extern crate rand;
extern crate tokio_core as tokio;

use dns_parser::Name;
use futures::{BoxFuture, Future};
use futures::sync::mpsc;
use std::io;
use std::thread;
use std::sync::{Arc, RwLock};
use std::cell::RefCell;
use tokio::reactor::{Handle, Core};

mod address_family;
mod fsm;
mod services;
mod net;

use address_family::{Inet, Inet6};
use services::{ServicesInner, Services, ServiceData};
use fsm::{Command, FSM};

const DEFAULT_TTL : u32 = 60;
const MDNS_PORT : u16 = 5353;

pub struct Responder {
    services: Services,
    commands: RefCell<CommandSender>,
    shutdown: Arc<Shutdown>,
}

pub struct Service {
    id: usize,
    services: Services,
    commands: CommandSender,
    _shutdown: Arc<Shutdown>,
}

impl Responder {
    fn setup_core() -> io::Result<(Core, BoxFuture<(), io::Error>, Responder)> {
        let core = Core::new()?;
        let (responder, task) = Self::with_handle(&core.handle())?;
        Ok((core, task, responder))
    }

    pub fn new() -> io::Result<Responder> {
        let (tx, rx) = std::sync::mpsc::sync_channel(0);
        thread::Builder::new()
            .name("mdns-responder".to_owned())
            .spawn(move || {
                match Self::setup_core() {
                    Ok((mut core, task, responder)) => {
                        tx.send(Ok(responder)).expect("Could not write Ok to sync_channel");
                        core.run(task).expect("Could not run task");
                    }
                    Err(err) => {
                        tx.send(Err(err)).expect("Could not write Error to sync_channel");
                    }
                }
            })?;

        rx.recv().expect("Could not receive from sync_channel")
    }

    pub fn spawn(handle: &Handle) -> io::Result<Responder> {
        let (responder, task) = Responder::with_handle(handle)?;
        handle.spawn(task.map_err(|e| {
            warn!("mdns error {:?}", e);
            ()
        }));
        Ok(responder)
    }

    pub fn with_handle(handle: &Handle) -> io::Result<(Responder, BoxFuture<(), io::Error>)> {
        let mut hostname = try!(net::gethostname());
        if !hostname.ends_with(".local") {
            hostname.push_str(".local");
        }

        let services = Arc::new(RwLock::new(ServicesInner::new(hostname)));

        let v4 = FSM::<Inet>::new(handle, &services);
        let v6 = FSM::<Inet6>::new(handle, &services);

        let (task, commands) = match (v4, v6) {
            (Ok((v4_task, v4_command)), Ok((v6_task, v6_command))) => {
                let task = v4_task.join(v6_task).map(|((),())| ()).boxed();
                let commands = vec![v4_command, v6_command];
                (task, commands)
            }

            (Ok((v4_task, v4_command)), Err(err)) => {
                warn!("Failed to register IPv6 receiver: {:?}", err);
                (v4_task.boxed(), vec![v4_command])
            }

            (Err(err), _) => return Err(err),
        };

        let commands = CommandSender(commands);
        let responder = Responder {
            services: services,
            commands: RefCell::new(commands.clone()),
            shutdown: Arc::new(Shutdown(commands)),
        };

        Ok((responder, task.boxed()))
    }
}

impl Responder {
    pub fn register(&self, svc_type: String, svc_name: String, port: u16, txt: &[&str]) -> Service {
        let txt = if txt.is_empty() {
            vec![0]
        } else {
            txt.into_iter().flat_map(|entry| {
                let entry = entry.as_bytes();
                if entry.len() > 255 {
                    panic!("{:?} is too long for a TXT record", entry);
                }
                std::iter::once(entry.len() as u8).chain(entry.into_iter().cloned())
            }).collect()
        };

        let svc = ServiceData {
            typ: Name::from_str(format!("{}.local", svc_type)).unwrap(),
            name: Name::from_str(format!("{}.{}.local", svc_name, svc_type)).unwrap(),
            port: port,
            txt: txt,
        };

        self.commands.borrow_mut()
            .send_unsolicited(svc.clone(), DEFAULT_TTL, true);

        let id = self.services
            .write().unwrap()
            .register(svc);

        Service {
            id: id,
            commands: self.commands.borrow().clone(),
            services: self.services.clone(),
            _shutdown: self.shutdown.clone(),
        }
    }

}

impl Drop for Service {
    fn drop(&mut self) {
        let svc = self.services
            .write().unwrap()
            .unregister(self.id);
        self.commands.send_unsolicited(svc, 0, false);
    }
}

struct Shutdown(CommandSender);
impl Drop for Shutdown {
    fn drop(&mut self) {
        self.0.send_shutdown();
        // TODO wait for tasks to shutdown
    }
}

#[derive(Clone)]
struct CommandSender(Vec<mpsc::UnboundedSender<Command>>);
impl CommandSender {
    fn send(&mut self, cmd: Command) {
        for tx in self.0.iter_mut() {
            tx.send(cmd.clone()).expect("responder died");
        }
    }

    fn send_unsolicited(&mut self, svc: ServiceData, ttl: u32, include_ip: bool) {
        self.send(Command::SendUnsolicited {
            svc: svc,
            ttl: ttl,
            include_ip: include_ip,
        });
    }

    fn send_shutdown(&mut self) {
        self.send(Command::Shutdown);
    }
}
<commit_msg>better wording of the error messages<commit_after>#[macro_use] extern crate log;

extern crate byteorder;
extern crate dns_parser;
extern crate futures;
extern crate libc;
extern crate multimap;
extern crate net2;
extern crate nix;
extern crate rand;
extern crate tokio_core as tokio;

use dns_parser::Name;
use futures::{BoxFuture, Future};
use futures::sync::mpsc;
use std::io;
use std::thread;
use std::sync::{Arc, RwLock};
use std::cell::RefCell;
use tokio::reactor::{Handle, Core};

mod address_family;
mod fsm;
mod services;
mod net;

use address_family::{Inet, Inet6};
use services::{ServicesInner, Services, ServiceData};
use fsm::{Command, FSM};

const DEFAULT_TTL : u32 = 60;
const MDNS_PORT : u16 = 5353;

pub struct Responder {
    services: Services,
    commands: RefCell<CommandSender>,
    shutdown: Arc<Shutdown>,
}

pub struct Service {
    id: usize,
    services: Services,
    commands: CommandSender,
    _shutdown: Arc<Shutdown>,
}

impl Responder {
    fn setup_core() -> io::Result<(Core, BoxFuture<(), io::Error>, Responder)> {
        let core = Core::new()?;
        let (responder, task) = Self::with_handle(&core.handle())?;
        Ok((core, task, responder))
    }

    pub fn new() -> io::Result<Responder> {
        let (tx, rx) = std::sync::mpsc::sync_channel(0);
        thread::Builder::new()
            .name("mdns-responder".to_owned())
            .spawn(move || {
                match Self::setup_core() {
                    Ok((mut core, task, responder)) => {
                        tx.send(Ok(responder)).expect("tx responder channel closed");
                        core.run(task).expect("mdsn thread failed");
                    }
                    Err(err) => {
                        tx.send(Err(err)).expect("tx responder channel closed");
                    }
                }
            })?;

        rx.recv().expect("rx responder channel closed")
    }

    pub fn spawn(handle: &Handle) -> io::Result<Responder> {
        let (responder, task) = Responder::with_handle(handle)?;
        handle.spawn(task.map_err(|e| {
            warn!("mdns error {:?}", e);
            ()
        }));
        Ok(responder)
    }

    pub fn with_handle(handle: &Handle) -> io::Result<(Responder, BoxFuture<(), io::Error>)> {
        let mut hostname = try!(net::gethostname());
        if !hostname.ends_with(".local") {
            hostname.push_str(".local");
        }

        let services = Arc::new(RwLock::new(ServicesInner::new(hostname)));

        let v4 = FSM::<Inet>::new(handle, &services);
        let v6 = FSM::<Inet6>::new(handle, &services);

        let (task, commands) = match (v4, v6) {
            (Ok((v4_task, v4_command)), Ok((v6_task, v6_command))) => {
                let task = v4_task.join(v6_task).map(|((),())| ()).boxed();
                let commands = vec![v4_command, v6_command];
                (task, commands)
            }

            (Ok((v4_task, v4_command)), Err(err)) => {
                warn!("Failed to register IPv6 receiver: {:?}", err);
                (v4_task.boxed(), vec![v4_command])
            }

            (Err(err), _) => return Err(err),
        };

        let commands = CommandSender(commands);
        let responder = Responder {
            services: services,
            commands: RefCell::new(commands.clone()),
            shutdown: Arc::new(Shutdown(commands)),
        };

        Ok((responder, task.boxed()))
    }
}

impl Responder {
    pub fn register(&self, svc_type: String, svc_name: String, port: u16, txt: &[&str]) -> Service {
        let txt = if txt.is_empty() {
            vec![0]
        } else {
            txt.into_iter().flat_map(|entry| {
                let entry = entry.as_bytes();
                if entry.len() > 255 {
                    panic!("{:?} is too long for a TXT record", entry);
                }
                std::iter::once(entry.len() as u8).chain(entry.into_iter().cloned())
            }).collect()
        };

        let svc = ServiceData {
            typ: Name::from_str(format!("{}.local", svc_type)).unwrap(),
            name: Name::from_str(format!("{}.{}.local", svc_name, svc_type)).unwrap(),
            port: port,
            txt: txt,
        };

        self.commands.borrow_mut()
            .send_unsolicited(svc.clone(), DEFAULT_TTL, true);

        let id = self.services
            .write().unwrap()
            .register(svc);

        Service {
            id: id,
            commands: self.commands.borrow().clone(),
            services: self.services.clone(),
            _shutdown: self.shutdown.clone(),
        }
    }

}

impl Drop for Service {
    fn drop(&mut self) {
        let svc = self.services
            .write().unwrap()
            .unregister(self.id);
        self.commands.send_unsolicited(svc, 0, false);
    }
}

struct Shutdown(CommandSender);
impl Drop for Shutdown {
    fn drop(&mut self) {
        self.0.send_shutdown();
        // TODO wait for tasks to shutdown
    }
}

#[derive(Clone)]
struct CommandSender(Vec<mpsc::UnboundedSender<Command>>);
impl CommandSender {
    fn send(&mut self, cmd: Command) {
        for tx in self.0.iter_mut() {
            tx.send(cmd.clone()).expect("responder died");
        }
    }

    fn send_unsolicited(&mut self, svc: ServiceData, ttl: u32, include_ip: bool) {
        self.send(Command::SendUnsolicited {
            svc: svc,
            ttl: ttl,
            include_ip: include_ip,
        });
    }

    fn send_shutdown(&mut self) {
        self.send(Command::Shutdown);
    }
}
<|endoftext|>


<commit_before>//! A C-style `for` loop in macro form.
//!
//! This takes the form `cfor!(initialiser; condition; step { body })`.
//!
//! - `initialiser` is a statement evaluated before any iterations of
//!   the loop. Any variables declared here are scoped to the `cfor!`
//!   invocation, that is, only usable inside `condition`, `step` and
//!   `body`.
//! - `condition` is an boolean expression evaluated at the start of
//!   each iteration. If it evaluates to `false` iteration will stop.
//! - `step` is an arbitrary expression which is executed at the end
//!   of each iteration (including if `continue` is called), before
//!   `condition` is checked.
//!
//!
//! The initialiser and condition can be empty like C, but the step
//! cannot unlike C. A `for` loop with no step is identical to a
//! `while` loop.
//!
//! [*Source & issue tracker*](https://github.com/huonw/cfor/)
//!
//! # When should I use it?
//!
//! *Only* when `cfor!` is clearer than the more declarative built-in
//! [iterators](http://doc.rust-lang.org/master/std/iter/), [their
//! adaptors](http://doc.rust-lang.org/master/std/iter/trait.Iterator.html)
//! and the `for` loop. For example, the built-in iterator
//! functionality is more self-contained so there is less risk of
//! accidentally writing `i` in a condition when `j` was meant (I
//! personally get bitten by this semiregularly when writing nested
//! "2D" loops in C).
//!
//! Furthermore, the adaptor methods linked above allow [one to
//! write](http://huonw.github.io/2014/06/10/knn-rust.html) concise,
//! performant, reusable "functional" code in a way that is not
//! possible to achieve using C-style iteration.
//!
//! # How to use it?
//!
//! Add the repository as a normal cargo dependency, and include into
//! your crate with `#[phase(plugin)]`. (See examples below.)
//!
//! ```toml
//! [dependencies.cfor]
//! cfor = "1.0"
//! ```
//!
//! # Examples
//!
//! ## Simple
//!
//! A non-additive condition is not handled extremely naturally by
//! `std::iter`, but is straight-forward to handle directly.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1; x < 0x1000; x *= 2; {
//!         println!("power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Intrabody condition
//!
//! If a condition requires some extra computation to be checked (or
//! if there is some code that should always be evaluated, even if the
//! condition will be `false` for a given iteration), the condition in
//! the `cfor` header can be omitted.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1; ; x *= 2; {
//!         // ... setup ...
//!         println!("handling power of 2: {}", x);
//!
//!         if x < 0x1000 { break }
//!
//!         // ... further handling ...
//!         println!("handling power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Out-of-loop initialisation
//!
//! Sometimes one may wish to have access to a variable outside the
//! loop after it finishes so it has to be declared outside the loop,
//! or one may be iterating over some presupplied/-computed value so
//! there is no meaningful additional initialisation possible. The
//! initialisation expression can be safely omitted in this case.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! extern crate rand;
//!
//! fn main() {
//!     let mut x = 1u16;
//!
//!     cfor!{; x < 0x1000; x *= 2; {
//!         println!("power of 2: {}", x);
//!
//!         // sometimes quit early
//!         if x > rand::random() { break }
//!     }}
//!
//!     println!("actually stopped at {}", x);
//! }
//! ```
//!
//! # Handling `continue`
//!
//! (Or, "why is the macro so complicated?")
//!
//! Special effort is made to ensure that `continue` acts correctly, a
//! naive macro defined as follows will cause `continue` to also skip
//! evaluating `step`, likely leading to undesirable behaviour like
//! infinite loops.
//!
//! ```rust
//! # // avoid our crate being inserted automatically, which gets in
//! # // the way of the feature above.
//! # #[macro_use] extern crate cfor;
//! // WARNING: this is broken.
//! macro_rules! bad_cfor {
//!     ($init: stmt; $cond: expr; $step: expr; $body: block) => {
//!         {
//!             $init;
//!             while $cond {
//!                 $body;
//!
//!                 $step;
//!             }
//!         }
//!     }
//! }
//!
//! fn main() {
//!     let mut true_counter = 0;
//!
//!     bad_cfor!{let mut i = 0; i < 10; i += 1; {
//!
//!         // manually avoid the infinite loop
//!         if true_counter >= 50 { break }
//!         true_counter += 1;
//!
//!         println!("i = {}", i);
//!         // try to skip just i == 4
//!         if i == 4 {
//!             // but this skips the i += 1 leaving us
//!             // on i == 4 forever.
//!             continue
//!         }
//!         // ...more code...
//!     }}
//! }
//! ```
//!
//! This is invoked in the same manner as `cfor!`, but, if `$body`
//! contains a `continue`, the `$step` at the end of the loop body
//! will never be evaluated.

/// A C-style `for` loop in macro form.
///
/// See crates docs for more information.
#[macro_export]
macro_rules! cfor {
    // for (; ...; ...) { ... }
    (; $($rest: tt)*) => {
        cfor!((); $($rest)*)
    };
    // for ($init; ; ...) { ... }
    ($init: stmt; ; $($rest: tt)*) => {
        // avoid the `while true` lint
        cfor!($init; !false; $($rest)*)
    };

    // for ($init; $cond; ) { ... }
    ($init: stmt; $cond: expr; ; $body: block) => {
        cfor!{$init; $cond; (); $body}
    };

    // for ($init; $cond; $step) { $body }
    ($init: stmt; $cond: expr; $step: expr; $body: block) => {
        {
            $init;
            while $cond {
                let mut _first = true;
                let mut _continue = false;
                // this loop runs once, allowing us to use `break` and
                // `continue` as `goto` to skip forward to the
                // condition.
                //
                // the booleans above are very transparent to the
                // optimiser, since they are modified exactly once,
                // with nice control flow, and this this optimises to
                // be similar to C for loop.
                loop {
                    // if we *don't* hit this, there was a `break` in
                    // the body (otherwise the loop fell-through or
                    // was `continue`d.)
                    if !_first { _continue = true; break }
                    _first = false;

                    $body
                }
                if !_continue {
                    // the `if` wasn't hit, so we should propagate the
                    // `break`.
                    break
                }

                $step
            }
        }
    };
}
<commit_msg>Added repetition for multiple declarations/steps<commit_after>//! A C-style `for` loop in macro form.
//!
//! This takes the form `cfor!(initialiser; condition; step { body })`.
//!
//! - `initialiser` is a statement evaluated before any iterations of
//!   the loop. Any variables declared here are scoped to the `cfor!`
//!   invocation, that is, only usable inside `condition`, `step` and
//!   `body`.
//! - `condition` is an boolean expression evaluated at the start of
//!   each iteration. If it evaluates to `false` iteration will stop.
//! - `step` is an arbitrary expression which is executed at the end
//!   of each iteration (including if `continue` is called), before
//!   `condition` is checked.
//!
//!
//! The initialiser and condition can be empty like C, but the step
//! cannot unlike C. A `for` loop with no step is identical to a
//! `while` loop.
//!
//! [*Source & issue tracker*](https://github.com/huonw/cfor/)
//!
//! # When should I use it?
//!
//! *Only* when `cfor!` is clearer than the more declarative built-in
//! [iterators](http://doc.rust-lang.org/master/std/iter/), [their
//! adaptors](http://doc.rust-lang.org/master/std/iter/trait.Iterator.html)
//! and the `for` loop. For example, the built-in iterator
//! functionality is more self-contained so there is less risk of
//! accidentally writing `i` in a condition when `j` was meant (I
//! personally get bitten by this semiregularly when writing nested
//! "2D" loops in C).
//!
//! Furthermore, the adaptor methods linked above allow [one to
//! write](http://huonw.github.io/2014/06/10/knn-rust.html) concise,
//! performant, reusable "functional" code in a way that is not
//! possible to achieve using C-style iteration.
//!
//! # How to use it?
//!
//! Add the repository as a normal cargo dependency, and include into
//! your crate with `#[phase(plugin)]`. (See examples below.)
//!
//! ```toml
//! [dependencies.cfor]
//! cfor = "1.0"
//! ```
//!
//! # Examples
//!
//! ## Simple
//!
//! A non-additive condition is not handled extremely naturally by
//! `std::iter`, but is straight-forward to handle directly.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1; x < 0x1000; x *= 2; {
//!         println!("power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Intrabody condition
//!
//! If a condition requires some extra computation to be checked (or
//! if there is some code that should always be evaluated, even if the
//! condition will be `false` for a given iteration), the condition in
//! the `cfor` header can be omitted.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1; ; x *= 2; {
//!         // ... setup ...
//!         println!("handling power of 2: {}", x);
//!
//!         if x < 0x1000 { break }
//!
//!         // ... further handling ...
//!         println!("handling power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Out-of-loop initialisation
//!
//! Sometimes one may wish to have access to a variable outside the
//! loop after it finishes so it has to be declared outside the loop,
//! or one may be iterating over some presupplied/-computed value so
//! there is no meaningful additional initialisation possible. The
//! initialisation expression can be safely omitted in this case.
//!
//! ```rust
//! #[macro_use] extern crate cfor;
//!
//! extern crate rand;
//!
//! fn main() {
//!     let mut x = 1u16;
//!
//!     cfor!{; x < 0x1000; x *= 2; {
//!         println!("power of 2: {}", x);
//!
//!         // sometimes quit early
//!         if x > rand::random() { break }
//!     }}
//!
//!     println!("actually stopped at {}", x);
//! }
//! ```
//!
//! # Handling `continue`
//!
//! (Or, "why is the macro so complicated?")
//!
//! Special effort is made to ensure that `continue` acts correctly, a
//! naive macro defined as follows will cause `continue` to also skip
//! evaluating `step`, likely leading to undesirable behaviour like
//! infinite loops.
//!
//! ```rust
//! # // avoid our crate being inserted automatically, which gets in
//! # // the way of the feature above.
//! # #[macro_use] extern crate cfor;
//! // WARNING: this is broken.
//! macro_rules! bad_cfor {
//!     ($init: stmt; $cond: expr; $step: expr; $body: block) => {
//!         {
//!             $init;
//!             while $cond {
//!                 $body;
//!
//!                 $step;
//!             }
//!         }
//!     }
//! }
//!
//! fn main() {
//!     let mut true_counter = 0;
//!
//!     bad_cfor!{let mut i = 0; i < 10; i += 1; {
//!
//!         // manually avoid the infinite loop
//!         if true_counter >= 50 { break }
//!         true_counter += 1;
//!
//!         println!("i = {}", i);
//!         // try to skip just i == 4
//!         if i == 4 {
//!             // but this skips the i += 1 leaving us
//!             // on i == 4 forever.
//!             continue
//!         }
//!         // ...more code...
//!     }}
//! }
//! ```
//!
//! This is invoked in the same manner as `cfor!`, but, if `$body`
//! contains a `continue`, the `$step` at the end of the loop body
//! will never be evaluated.
//!
//! # Handling multiple initializations and steps
//!
//! Like C loops, `cfor!` supports specfying multiple initializations and steps seperated by a comma.
//!
//! ```
//!cfor!(let mut x = 0, let mut y = x; x <= 10 && y <= 100; x+= 1, y += 10; {
//!    println!("{}:{}", x, y);
//!});

/// A C-style `for` loop in macro form.
///
/// See crates docs for more information.
#[macro_export]
macro_rules! cfor {
    // for (; ...; ...) { ... }
    (; $($rest: tt)*) => {
        cfor!((); $($rest)*)
    };
    // for ($init; ; ...) { ... }
    ($($init: stmt),+; ; $($rest: tt)*) => {
        // avoid the `while true` lint
        cfor!($($init),+; !false; $($rest)*)
    };

    // for ($init; $cond; ) { ... }
    ($($init: stmt),+; $cond: expr; ; $body: block) => {
        cfor!{$($init),+; $cond; (); $body}
    };

    // for ($init; $cond; $step) { $body }
    ($($init: stmt),+; $cond: expr; $($step: expr),+; $body: block) => {
        {
            $($init;)+
            while $cond {
                let mut _first = true;
                let mut _continue = false;
                // this loop runs once, allowing us to use `break` and
                // `continue` as `goto` to skip forward to the
                // condition.
                //
                // the booleans above are very transparent to the
                // optimiser, since they are modified exactly once,
                // with nice control flow, and this this optimises to
                // be similar to C for loop.
                loop {
                    // if we *don't* hit this, there was a `break` in
                    // the body (otherwise the loop fell-through or
                    // was `continue`d.)
                    if !_first { _continue = true; break }
                    _first = false;

                    $body
                }
                if !_continue {
                    // the `if` wasn't hit, so we should propagate the
                    // `break`.
                    break
                }

                $($step;)+
            }
        }
    };
}
<|endoftext|>


<commit_before>//! Elasticsearch Response Iterators
//!
//! A crate to handle parsing and handling Elasticsearch search results which provides
//! convenient iterators to step through the results returned. It is designed to work
//! with [`elastic-reqwest`](https://github.com/elastic-rs/elastic-reqwest/).
//!
//! This crate provides a generic `HttpResponse` that can be parsed into a concrete response
//! type, or an `ApiError`.
//!
//! ## Usage
//!
//! Query your Elasticsearch Cluster, then iterate through the results
//!
//! ```no_run
//! # extern crate elastic_responses;
//! # use elastic_responses::*;
//! # fn do_request() -> (u16, Vec<u8>) { unimplemented!() }
//! # fn main() {
//! // Send a document get request and read as a response
//! let (response_status, response_body) = do_request();
//!
//! // Parse body to JSON as an elastic_responses::SearchResponse object
//! // If the response is an API error then it'll be parsed into a friendly Rust error
//! let body_as_json: SearchResponse = parse().from_slice(response_status, response_body).unwrap();
//!
//! // Use hits() or aggs() iterators
//! // Hits
//! for i in body_as_json.hits() {
//!   println!("{:?}",i);
//! }
//!
//! // Agregations
//! for i in body_as_json.aggs() {
//!   println!("{:?}",i);
//! }
//! # }
//! ```
//!
/// Any type that implements `IsOk` can be parsed into a concrete response or an `ApiError`:
///
/// ```no_run
/// # extern crate serde_json;
/// # extern crate elastic_responses;
/// # use serde_json::*;
/// # use elastic_responses::*;
/// # use elastic_responses::error::*;
/// # fn do_request() -> (u16, Vec<u8>) { unimplemented!() }
/// # fn main() {
/// // Send a document get request and read as a response
/// let (response_status, response_body) = do_request();
///
/// let get_response = parse::<GetResponseOf<Value>>().from_slice(response_status, response_body);
///
/// match get_response {
///     Ok(res) => {
///         // Do something with the GetResponse
///     }
///     Err(ResponseError::Api(ApiError::IndexNotFound { index })) => {
///         // Do something with the missing index error
///     }
///     _ => {
///         // Some other error
///     }
/// }
/// # }
/// ```

#[macro_use]
extern crate log;

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate quick_error;

extern crate serde;
extern crate serde_json;

extern crate slog_stdlog;
extern crate slog_envlogger;

pub mod error;
pub mod parsing;

mod common;
mod command;
mod ping;
mod get;
mod search;
mod bulk;
mod index;

pub use self::common::*;
pub use self::command::*;
pub use self::ping::*;
pub use self::get::*;
pub use self::search::*;
pub use self::bulk::*;
pub use self::index::*;

pub use self::parsing::parse;
<commit_msg>fix root docs<commit_after>//! Elasticsearch Response Iterators
//!
//! A crate to handle parsing and handling Elasticsearch search results which provides
//! convenient iterators to step through the results returned. It is designed to work
//! with [`elastic-reqwest`](https://github.com/elastic-rs/elastic-reqwest/).
//!
//! This crate provides a generic `HttpResponse` that can be parsed into a concrete response
//! type, or an `ApiError`.
//!
//! ## Usage
//!
//! Query your Elasticsearch Cluster, then iterate through the results
//!
//! ```no_run
//! # extern crate elastic_responses;
//! # use elastic_responses::*;
//! # fn do_request() -> (u16, Vec<u8>) { unimplemented!() }
//! # fn main() {
//! // Send a document get request and read as a response
//! let (response_status, response_body) = do_request();
//!
//! // Parse body to JSON as an elastic_responses::SearchResponse object
//! // If the response is an API error then it'll be parsed into a friendly Rust error
//! let body_as_json: SearchResponse = parse().from_slice(response_status, response_body).unwrap();
//!
//! // Use hits() or aggs() iterators
//! // Hits
//! for i in body_as_json.hits() {
//!   println!("{:?}",i);
//! }
//!
//! // Agregations
//! for i in body_as_json.aggs() {
//!   println!("{:?}",i);
//! }
//! # }
//! ```
//!
//! Any type that implements `IsOk` can be parsed into a concrete response or an `ApiError`:
//!
//! ```no_run
//! # extern crate serde_json;
//! # extern crate elastic_responses;
//! # use serde_json::*;
//! # use elastic_responses::*;
//! # use elastic_responses::error::*;
//! # fn do_request() -> (u16, Vec<u8>) { unimplemented!() }
//! # fn main() {
//! // Send a document get request and read as a response
//! let (response_status, response_body) = do_request();
//!
//! let get_response = parse::<GetResponseOf<Value>>().from_slice(response_status, response_body);
//!
//! match get_response {
//!     Ok(res) => {
//!         // Do something with the GetResponse
//!     }
//!     Err(ResponseError::Api(ApiError::IndexNotFound { index })) => {
//!         // Do something with the missing index error
//!     }
//!     _ => {
//!         // Some other error
//!     }
//! }
//! # }
//! ```

#[macro_use]
extern crate log;

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate quick_error;

extern crate serde;
extern crate serde_json;

extern crate slog_stdlog;
extern crate slog_envlogger;

pub mod error;
pub mod parsing;

mod common;
mod command;
mod ping;
mod get;
mod search;
mod bulk;
mod index;

pub use self::common::*;
pub use self::command::*;
pub use self::ping::*;
pub use self::get::*;
pub use self::search::*;
pub use self::bulk::*;
pub use self::index::*;

pub use self::parsing::parse;
<|endoftext|>


<commit_before>#![crate_type = "rlib"]

//! Macro to create a "view box", a box containing data plus
//! a "view" struct that can have interior references into the data.
//! The view box be can moved around as an atomic unit.

#[macro_export]
macro_rules! viewbox {
    (struct $name:ident<$d:ty, $v:ident>;) => (
        pub struct $name {
            view: $v<'static>,
            #[allow(dead_code)]
            data: Box<$d>
        }

        #[allow(dead_code)]
        impl $name {
            pub fn new<F>(data: $d, f: F) -> $name
                          where F: for<'a> FnOnce(&'a mut $d) -> $v<'a> {
                let mut d = box data;
                let v = unsafe { ::std::mem::transmute(f(&mut *d)) };

                $name { data: d, view: v }
            }

            pub fn new_result<E,F>(data: $d,
                                   f: F)
                                   -> ::std::result::Result<$name,($d,E)>
                                   where F: for<'a> FnOnce(&'a mut $d) -> ::std::result::Result<$v<'a>,E> {
                let mut d = box data;
                match f(&mut *d).map(|v| unsafe { ::std::mem::transmute(v) }) {
                    Ok(v) => Ok($name { data: d, view: v }),
                    Err(e) => Err((*d,e))
                }
            }

            pub fn into_inner(self)-> $d {
                let $name { data: box data, .. } = self;
                data
            }

            pub fn view<'a>(&'a self) -> &'a $v<'a> {
                unsafe { ::std::mem::transmute(&self.view) }
            }

            pub fn view_mut<'a>(&'a mut self) -> &'a mut $v<'a> {
                unsafe { ::std::mem::transmute(&mut self.view) }
            }
        }
    );
    (#[derive(PartialEq $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::cmp::PartialEq for $name {
            fn eq(&self, other: &$name) -> bool { self.view() == other.view(); }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[derive(Debug $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::fmt::Debug for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                   -> ::std::result::Result<(), ::std::fmt::FormatError> {
                self.view().fmt(fmt)
            }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[derive()] struct $name:ident<$d:ty, $v:ident>;) => (
        viewbox!(struct $name<$d,$v>;)
    );
}

#[cfg(test)]
mod test {
    // Test data structure
    #[derive(PartialEq,Debug)]
    struct TestData {
        foo: i32,
        bar: String
    }

    // View structure that has references into the boxed data
    struct TestView<'a> {
        x: &'a i32,
        y: &'a str
    }

    // Create TestBox which combines TestData and TestView
    viewbox! {
        struct TestBox<TestData,TestView>;
    }

    // Mutable view into TestData
    struct MutView<'a> {
        x: &'a mut i32,
        y: &'a mut String
    }

    // MutBox combines TestData and MutView
    viewbox! {
        struct MutBox<TestData, MutView>;
    }

    #[test]
    fn basic() {
        // Create some data
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        // Move it into box, creating a view with interior references
        let v = TestBox::new(t, |d| TestView { x: &d.foo, y: d.bar.as_slice() });

        // We can access the boxed data via the view
        assert_eq!(v.view().x, &42i32);
        assert_eq!(v.view().y, "Hello");
        // We can unwrap the view to get the data back
        let t = v.into_inner();
        assert_eq!(t.foo, 42i32);
        assert_eq!(t.bar, "Hello".to_string());
    }

    #[test]
    fn mutation() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let mut v = MutBox::new(t, |d| MutView { x: &mut d.foo, y: &mut d.bar });

        *v.view_mut().x = 5;
        *v.view_mut().y = "Goodbye".to_string();
        let t = v.into_inner();
        assert_eq!(t, TestData { foo: 5, bar: "Goodbye".to_string() });
    }

    #[test]
    fn error() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let v = MutBox::new_result(t, |_| Err("Nope")).err().unwrap();
        assert_eq!(v, (TestData { foo: 42, bar: "Hello".to_string() }, "Nope"))
    }
}
<commit_msg>Fix warning<commit_after>#![crate_type = "rlib"]

//! Macro to create a "view box", a box containing data plus
//! a "view" struct that can have interior references into the data.
//! The view box be can moved around as an atomic unit.

#[macro_export]
macro_rules! viewbox {
    (struct $name:ident<$d:ty, $v:ident>;) => (
        pub struct $name {
            view: $v<'static>,
            #[allow(dead_code)]
            data: Box<$d>
        }

        #[allow(dead_code)]
        impl $name {
            pub fn new<F>(data: $d, f: F) -> $name
                          where F: for<'a> FnOnce(&'a mut $d) -> $v<'a> {
                let mut d = box data;
                let v = unsafe { ::std::mem::transmute(f(&mut *d)) };

                $name { data: d, view: v }
            }

            pub fn new_result<E,F>(data: $d,
                                   f: F)
                                   -> ::std::result::Result<$name,($d,E)>
                                   where F: for<'a> FnOnce(&'a mut $d) -> ::std::result::Result<$v<'a>,E> {
                let mut d = box data;
                match f(&mut *d).map(|v| unsafe { ::std::mem::transmute(v) }) {
                    Ok(v) => Ok($name { data: d, view: v }),
                    Err(e) => Err((*d,e))
                }
            }

            pub fn into_inner(self)-> $d {
                let $name { data: box data, .. } = self;
                data
            }

            pub fn view<'a>(&'a self) -> &'a $v<'a> {
                unsafe { ::std::mem::transmute(&self.view) }
            }

            pub fn view_mut<'a>(&'a mut self) -> &'a mut $v<'a> {
                unsafe { ::std::mem::transmute(&mut self.view) }
            }
        }
    );
    (#[derive(PartialEq $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::cmp::PartialEq for $name {
            fn eq(&self, other: &$name) -> bool { self.view() == other.view(); }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[derive(Debug $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::fmt::Debug for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                   -> ::std::result::Result<(), ::std::fmt::FormatError> {
                self.view().fmt(fmt)
            }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[derive()] struct $name:ident<$d:ty, $v:ident>;) => (
        viewbox!(struct $name<$d,$v>;)
    );
}

#[cfg(test)]
mod test {
    // Test data structure
    #[derive(PartialEq,Debug)]
    struct TestData {
        foo: i32,
        bar: String
    }

    // View structure that has references into the boxed data
    struct TestView<'a> {
        x: &'a i32,
        y: &'a str
    }

    // Create TestBox which combines TestData and TestView
    viewbox! {
        struct TestBox<TestData,TestView>;
    }

    // Mutable view into TestData
    struct MutView<'a> {
        x: &'a mut i32,
        y: &'a mut String
    }

    // MutBox combines TestData and MutView
    viewbox! {
        struct MutBox<TestData, MutView>;
    }

    #[test]
    fn basic() {
        // Create some data
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        // Move it into box, creating a view with interior references
        let v = TestBox::new(t, |d| TestView { x: &d.foo, y: &d.bar });

        // We can access the boxed data via the view
        assert_eq!(v.view().x, &42i32);
        assert_eq!(v.view().y, "Hello");
        // We can unwrap the view to get the data back
        let t = v.into_inner();
        assert_eq!(t.foo, 42i32);
        assert_eq!(t.bar, "Hello".to_string());
    }

    #[test]
    fn mutation() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let mut v = MutBox::new(t, |d| MutView { x: &mut d.foo, y: &mut d.bar });

        *v.view_mut().x = 5;
        *v.view_mut().y = "Goodbye".to_string();
        let t = v.into_inner();
        assert_eq!(t, TestData { foo: 5, bar: "Goodbye".to_string() });
    }

    #[test]
    fn error() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let v = MutBox::new_result(t, |_| Err("Nope")).err().unwrap();
        assert_eq!(v, (TestData { foo: 42, bar: "Hello".to_string() }, "Nope"))
    }
}
<|endoftext|>


<commit_before>mod evaluation;
pub use self::evaluation::*;

pub mod species;

mod types;
pub use self::types::*;
<commit_msg>Make PokeSpecies a top-level export<commit_after>mod evaluation;
pub use self::evaluation::*;

pub mod species;
pub use species::PokeSpecies;

mod types;
pub use self::types::*;
<|endoftext|>