<commit_before>//! An example of how to play with various graphics modes settings,
//! resize windows, etc.
//!
//! Prints instructions to the console.
use std::convert::TryFrom;

use ggez::event::{self, KeyCode, KeyMods};
use ggez::graphics::{self, Color, DrawMode, DrawParam};
use ggez::{conf, graphics::Rect};
use ggez::{Context, GameResult};

use argh::FromArgs;

use std::env;
use std::path;

type Point2 = glam::Vec2;

struct WindowSettings {
    toggle_fullscreen: bool,
    is_fullscreen: bool,
    resize_projection: bool,
}

struct MainState {
    angle: f32, // in radians
    zoom: f32,
    image: graphics::Image,
    window_settings: WindowSettings,
    screen_coords: Rect,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let s = MainState {
            angle: 0.0,
            zoom: 1.0,
            image: graphics::Image::from_path(&ctx.fs, &ctx.gfx, "/tile.png", true)?,
            window_settings: WindowSettings {
                toggle_fullscreen: false,
                is_fullscreen: false,
                resize_projection: false,
            },
            screen_coords: Rect {
                x: 0.,
                y: 0.,
                w: ctx.gfx.drawable_size().0,
                h: ctx.gfx.drawable_size().1,
            },
        };
        Ok(s)
    }
}

impl event::EventHandler<ggez::GameError> for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult {
        const DESIRED_FPS: u32 = 60;
        while ctx.time.check_update_time(DESIRED_FPS) {
            self.angle += 0.01;

            if self.window_settings.toggle_fullscreen {
                let fullscreen_type = if self.window_settings.is_fullscreen {
                    conf::FullscreenType::Desktop
                } else {
                    conf::FullscreenType::Windowed
                };
                ctx.gfx.set_fullscreen(fullscreen_type)?;
                self.window_settings.toggle_fullscreen = false;
            }
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        let mut canvas = graphics::Canvas::from_frame(&ctx.gfx, Color::BLACK);
        canvas.set_screen_coordinates(self.screen_coords);

        canvas.draw(
            self.image.clone(),
            DrawParam::new()
                .dest(Point2::new(400.0, 300.0))
                .color(Color::WHITE), //.offset([0.5, 0.5]),
        );

        let rotation = ctx.time.ticks() % 1000;
        let circle = graphics::Mesh::new_circle(
            &ctx.gfx,
            DrawMode::stroke(3.0),
            Point2::new(0.0, 0.0),
            100.0,
            4.0,
            Color::WHITE,
        )?;
        canvas.draw_mesh(
            circle,
            None,
            (Point2::new(400.0, 300.0), rotation as f32, Color::WHITE),
        );

        // Let's draw a grid so we can see where the window bounds are.
        const COUNT: i32 = 10;
        let mut mb = graphics::MeshBuilder::new();
        for x in -COUNT..COUNT {
            for y in -COUNT..COUNT {
                const SPACING: i32 = 100;
                let fx = (x * SPACING) as f32;
                let fy = (y * SPACING) as f32;
                // println!("POS: {},{}", fx, fy);
                let r = (x as f32) / (COUNT as f32);
                let b = (y as f32) / (COUNT as f32);
                // println!("R: {}", r);
                let color = graphics::Color::new(r, 0.0, b, 1.0);
                // graphics::rectangle(
                //     ctx,
                //     color,
                //     graphics::DrawMode::fill(),
                //     graphics::Rect::new(fx, fy, 5.0, 5.0),
                // )?
                mb.rectangle(
                    DrawMode::fill(),
                    graphics::Rect::new(fx, fy, 5.0, 5.0),
                    color,
                )?;
            }
        }
        let mesh = graphics::Mesh::from_data(&ctx.gfx, mb.build());
        canvas.draw_mesh(mesh, None, (ggez::mint::Point2 { x: 0.0, y: 0.0 },));

        canvas.finish(&mut ctx.gfx)?;

        Ok(())
    }

    fn mouse_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _btn: event::MouseButton,
        x: f32,
        y: f32,
    ) -> GameResult {
        println!("Button clicked at: {} {}", x, y);
        Ok(())
    }

    fn key_up_event(
        &mut self,
        ctx: &mut Context,
        keycode: KeyCode,
        _keymod: KeyMods,
    ) -> GameResult {
        match keycode {
            KeyCode::F => {
                self.window_settings.toggle_fullscreen = true;
                self.window_settings.is_fullscreen = !self.window_settings.is_fullscreen;
            }
            KeyCode::Up => {
                self.zoom += 0.1;
                println!("Zoom is now {}", self.zoom);
                let (w, h) = ctx.gfx.drawable_size();
                let new_rect =
                    graphics::Rect::new(0.0, 0.0, w as f32 * self.zoom, h as f32 * self.zoom);
                self.screen_coords = new_rect;
            }
            KeyCode::Down => {
                self.zoom -= 0.1;
                println!("Zoom is now {}", self.zoom);
                let (w, h) = ctx.gfx.drawable_size();
                let new_rect =
                    graphics::Rect::new(0.0, 0.0, w as f32 * self.zoom, h as f32 * self.zoom);
                self.screen_coords = new_rect;
            }
            KeyCode::Space => {
                self.window_settings.resize_projection = !self.window_settings.resize_projection;
                println!(
                    "Resizing the projection on window resize is now: {}",
                    self.window_settings.resize_projection
                );
            }
            _ => {}
        }
        Ok(())
    }

    fn resize_event(&mut self, _ctx: &mut Context, width: f32, height: f32) -> GameResult {
        println!("Resized screen to {}, {}", width, height);
        if self.window_settings.resize_projection {
            let new_rect = graphics::Rect::new(
                0.0,
                0.0,
                width as f32 * self.zoom,
                height as f32 * self.zoom,
            );
            self.screen_coords = new_rect;
        }
        Ok(())
    }
}

fn print_help() {
    println!("GRAPHICS SETTING EXAMPLE:");
    println!("    F: toggle fullscreen");
    println!("    Up/Down: Zoom in/out");
    println!(
        "    Spacebar: Toggle whether or not to resize the projection when the window is resized"
    );
    println!("    ");
    println!("    To see command-line options, run with `cargo run --example graphics_settings -- --help`");
    println!("    ");
}

/// Print out graphics settings.
#[derive(FromArgs, Debug)]
struct Opt {
    /// what level of MSAA to try to use (1, 2, 4, 8)
    #[argh(option, short = 'm', long = "msaa", default = "1")]
    msaa: u8,
}

pub fn main() -> GameResult {
    let opt: Opt = argh::from_env();

    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let backend = conf::Backend::default();

    let cb = ggez::ContextBuilder::new("graphics_settings", "ggez")
        .window_mode(
            conf::WindowMode::default()
                .fullscreen_type(conf::FullscreenType::Windowed)
                .resizable(true),
        )
        .window_setup(
            conf::WindowSetup::default().samples(
                conf::NumSamples::try_from(opt.msaa)
                    .expect("Option msaa needs to be 1, 2, 4, 8 or 16!"),
            ),
        )
        .backend(backend)
        .add_resource_path(resource_dir);

    let (mut ctx, events_loop) = cb.build()?;

    print_help();
    let state = MainState::new(&mut ctx)?;
    event::run(ctx, events_loop, state)
}
<commit_msg>update msaa comments in graphics_settings example<commit_after>//! An example of how to play with various graphics modes settings,
//! resize windows, etc.
//!
//! Prints instructions to the console.
use std::convert::TryFrom;

use ggez::event::{self, KeyCode, KeyMods};
use ggez::graphics::{self, Color, DrawMode, DrawParam};
use ggez::{conf, graphics::Rect};
use ggez::{Context, GameResult};

use argh::FromArgs;

use std::env;
use std::path;

type Point2 = glam::Vec2;

struct WindowSettings {
    toggle_fullscreen: bool,
    is_fullscreen: bool,
    resize_projection: bool,
}

struct MainState {
    angle: f32, // in radians
    zoom: f32,
    image: graphics::Image,
    window_settings: WindowSettings,
    screen_coords: Rect,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let s = MainState {
            angle: 0.0,
            zoom: 1.0,
            image: graphics::Image::from_path(&ctx.fs, &ctx.gfx, "/tile.png", true)?,
            window_settings: WindowSettings {
                toggle_fullscreen: false,
                is_fullscreen: false,
                resize_projection: false,
            },
            screen_coords: Rect {
                x: 0.,
                y: 0.,
                w: ctx.gfx.drawable_size().0,
                h: ctx.gfx.drawable_size().1,
            },
        };
        Ok(s)
    }
}

impl event::EventHandler<ggez::GameError> for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult {
        const DESIRED_FPS: u32 = 60;
        while ctx.time.check_update_time(DESIRED_FPS) {
            self.angle += 0.01;

            if self.window_settings.toggle_fullscreen {
                let fullscreen_type = if self.window_settings.is_fullscreen {
                    conf::FullscreenType::Desktop
                } else {
                    conf::FullscreenType::Windowed
                };
                ctx.gfx.set_fullscreen(fullscreen_type)?;
                self.window_settings.toggle_fullscreen = false;
            }
        }
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        let mut canvas = graphics::Canvas::from_frame(&ctx.gfx, Color::BLACK);
        canvas.set_screen_coordinates(self.screen_coords);

        canvas.draw(
            self.image.clone(),
            DrawParam::new()
                .dest(Point2::new(400.0, 300.0))
                .color(Color::WHITE), //.offset([0.5, 0.5]),
        );

        let rotation = ctx.time.ticks() % 1000;
        let circle = graphics::Mesh::new_circle(
            &ctx.gfx,
            DrawMode::stroke(3.0),
            Point2::new(0.0, 0.0),
            100.0,
            4.0,
            Color::WHITE,
        )?;
        canvas.draw_mesh(
            circle,
            None,
            (Point2::new(400.0, 300.0), rotation as f32, Color::WHITE),
        );

        // Let's draw a grid so we can see where the window bounds are.
        const COUNT: i32 = 10;
        let mut mb = graphics::MeshBuilder::new();
        for x in -COUNT..COUNT {
            for y in -COUNT..COUNT {
                const SPACING: i32 = 100;
                let fx = (x * SPACING) as f32;
                let fy = (y * SPACING) as f32;
                // println!("POS: {},{}", fx, fy);
                let r = (x as f32) / (COUNT as f32);
                let b = (y as f32) / (COUNT as f32);
                // println!("R: {}", r);
                let color = graphics::Color::new(r, 0.0, b, 1.0);
                // graphics::rectangle(
                //     ctx,
                //     color,
                //     graphics::DrawMode::fill(),
                //     graphics::Rect::new(fx, fy, 5.0, 5.0),
                // )?
                mb.rectangle(
                    DrawMode::fill(),
                    graphics::Rect::new(fx, fy, 5.0, 5.0),
                    color,
                )?;
            }
        }
        let mesh = graphics::Mesh::from_data(&ctx.gfx, mb.build());
        canvas.draw_mesh(mesh, None, (ggez::mint::Point2 { x: 0.0, y: 0.0 },));

        canvas.finish(&mut ctx.gfx)?;

        Ok(())
    }

    fn mouse_button_down_event(
        &mut self,
        _ctx: &mut Context,
        _btn: event::MouseButton,
        x: f32,
        y: f32,
    ) -> GameResult {
        println!("Button clicked at: {} {}", x, y);
        Ok(())
    }

    fn key_up_event(
        &mut self,
        ctx: &mut Context,
        keycode: KeyCode,
        _keymod: KeyMods,
    ) -> GameResult {
        match keycode {
            KeyCode::F => {
                self.window_settings.toggle_fullscreen = true;
                self.window_settings.is_fullscreen = !self.window_settings.is_fullscreen;
            }
            KeyCode::Up => {
                self.zoom += 0.1;
                println!("Zoom is now {}", self.zoom);
                let (w, h) = ctx.gfx.drawable_size();
                let new_rect =
                    graphics::Rect::new(0.0, 0.0, w as f32 * self.zoom, h as f32 * self.zoom);
                self.screen_coords = new_rect;
            }
            KeyCode::Down => {
                self.zoom -= 0.1;
                println!("Zoom is now {}", self.zoom);
                let (w, h) = ctx.gfx.drawable_size();
                let new_rect =
                    graphics::Rect::new(0.0, 0.0, w as f32 * self.zoom, h as f32 * self.zoom);
                self.screen_coords = new_rect;
            }
            KeyCode::Space => {
                self.window_settings.resize_projection = !self.window_settings.resize_projection;
                println!(
                    "Resizing the projection on window resize is now: {}",
                    self.window_settings.resize_projection
                );
            }
            _ => {}
        }
        Ok(())
    }

    fn resize_event(&mut self, _ctx: &mut Context, width: f32, height: f32) -> GameResult {
        println!("Resized screen to {}, {}", width, height);
        if self.window_settings.resize_projection {
            let new_rect = graphics::Rect::new(
                0.0,
                0.0,
                width as f32 * self.zoom,
                height as f32 * self.zoom,
            );
            self.screen_coords = new_rect;
        }
        Ok(())
    }
}

fn print_help() {
    println!("GRAPHICS SETTING EXAMPLE:");
    println!("    F: toggle fullscreen");
    println!("    Up/Down: Zoom in/out");
    println!(
        "    Spacebar: Toggle whether or not to resize the projection when the window is resized"
    );
    println!("    ");
    println!("    To see command-line options, run with `cargo run --example graphics_settings -- --help`");
    println!("    ");
}

/// Print out graphics settings.
#[derive(FromArgs, Debug)]
struct Opt {
    /// what level of MSAA to try to use (1 or 4)
    #[argh(option, short = 'm', long = "msaa", default = "1")]
    msaa: u8,
}

pub fn main() -> GameResult {
    let opt: Opt = argh::from_env();

    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let backend = conf::Backend::default();

    let cb = ggez::ContextBuilder::new("graphics_settings", "ggez")
        .window_mode(
            conf::WindowMode::default()
                .fullscreen_type(conf::FullscreenType::Windowed)
                .resizable(true),
        )
        .window_setup(conf::WindowSetup::default().samples(
            conf::NumSamples::try_from(opt.msaa).expect("Option msaa needs to be 1 or 4!"),
        ))
        .backend(backend)
        .add_resource_path(resource_dir);

    let (mut ctx, events_loop) = cb.build()?;

    print_help();
    let state = MainState::new(&mut ctx)?;
    event::run(ctx, events_loop, state)
}
<|endoftext|>


<commit_before>use semver;
use url::Url;
use std::hash::Hash;
use std::fmt;
use std::fmt::{Show,Formatter};
use collections::hash;
use serialize::{
    Encodable,
    Encoder,
    Decodable,
    Decoder
};

use util::{CargoResult, CargoError, short_hash};
use core::source::SourceId;

trait ToVersion {
    fn to_version(self) -> Result<semver::Version, String>;
}

impl ToVersion for semver::Version {
    fn to_version(self) -> Result<semver::Version, String> {
        Ok(self)
    }
}

impl<'a> ToVersion for &'a str {
    fn to_version(self) -> Result<semver::Version, String> {
        match semver::parse(self) {
            Some(v) => Ok(v),
            None => Err(format!("cannot parse '{}' as a semver", self)),
        }
    }
}

trait ToUrl {
    fn to_url(self) -> Result<Url, String>;
}

impl<'a> ToUrl for &'a str {
    fn to_url(self) -> Result<Url, String> {
        Url::parse(self)
    }
}

impl ToUrl for Url {
    fn to_url(self) -> Result<Url, String> {
        Ok(self)
    }
}

impl<'a> ToUrl for &'a Url {
    fn to_url(self) -> Result<Url, String> {
        Ok(self.clone())
    }
}

#[deriving(Clone, PartialEq)]
pub struct PackageId {
    name: String,
    version: semver::Version,
    source_id: SourceId,
}

impl<S: hash::Writer> Hash<S> for PackageId {
    fn hash(&self, state: &mut S) {
        self.name.hash(state);
        self.version.to_string().hash(state);
        self.source_id.hash(state);
    }
}

impl Eq for PackageId {}

#[deriving(Clone, Show, PartialEq)]
pub enum PackageIdError {
    InvalidVersion(String),
    InvalidNamespace(String)
}

impl CargoError for PackageIdError {
    fn description(&self) -> String {
        match *self {
            InvalidVersion(ref v) => format!("invalid version: {}", *v),
            InvalidNamespace(ref ns) => format!("invalid namespace: {}", *ns),
        }
    }
    fn is_human(&self) -> bool { true }
}

#[deriving(PartialEq, Hash, Clone, Encodable)]
pub struct Metadata {
    pub metadata: String,
    pub extra_filename: String
}

impl PackageId {
    pub fn new<T: ToVersion>(name: &str, version: T,
                             sid: &SourceId) -> CargoResult<PackageId> {
        let v = try!(version.to_version().map_err(InvalidVersion));
        Ok(PackageId {
            name: name.to_string(),
            version: v,
            source_id: sid.clone()
        })
    }

    pub fn get_name<'a>(&'a self) -> &'a str {
        self.name.as_slice()
    }

    pub fn get_version<'a>(&'a self) -> &'a semver::Version {
        &self.version
    }

    pub fn get_source_id<'a>(&'a self) -> &'a SourceId {
        &self.source_id
    }

    pub fn generate_metadata(&self) -> Metadata {
        let metadata = format!("{}:-:{}:-:{}", self.name, self.version, self.source_id);
        let extra_filename = short_hash(
            &(self.name.as_slice(), self.version.to_string(), &self.source_id));

        Metadata { metadata: metadata, extra_filename: format!("-{}", extra_filename) }
    }
}

static central_repo: &'static str = "http://rust-lang.org/central-repo";

impl Show for PackageId {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        try!(write!(f, "{} v{}", self.name, self.version));

        if self.source_id.to_string().as_slice() != central_repo {
            try!(write!(f, " ({})", self.source_id));
        }

        Ok(())
    }
}

impl<D: Decoder<Box<CargoError + Send>>>
    Decodable<D,Box<CargoError + Send>> for PackageId {
    fn decode(d: &mut D) -> CargoResult<PackageId> {
        let (name, version, source_id): (String, String, SourceId) = try!(Decodable::decode(d));

        PackageId::new(name.as_slice(), version.as_slice(), &source_id)
    }
}

impl<E, S: Encoder<E>> Encodable<S,E> for PackageId {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        (self.name.clone(), self.version.to_string(), self.source_id.clone()).encode(e)
    }
}

#[cfg(test)]
mod tests {
    use super::{PackageId, central_repo};
    use core::source::{Location, RegistryKind, SourceId};

    #[test]
    fn invalid_version_handled_nicely() {
        let loc = Location::parse(central_repo).unwrap();
        let repo = SourceId::new(RegistryKind, loc);

        assert!(PackageId::new("foo", "1.0", &repo).is_err());
        assert!(PackageId::new("foo", "1", &repo).is_err());
        assert!(PackageId::new("foo", "bar", &repo).is_err());
        assert!(PackageId::new("foo", "", &repo).is_err());
    }
}
<commit_msg>undo inline for better readability<commit_after>use semver;
use url::Url;
use std::hash::Hash;
use std::fmt;
use std::fmt::{Show,Formatter};
use collections::hash;
use serialize::{
    Encodable,
    Encoder,
    Decodable,
    Decoder
};

use util::{CargoResult, CargoError, short_hash};
use core::source::SourceId;

trait ToVersion {
    fn to_version(self) -> Result<semver::Version, String>;
}

impl ToVersion for semver::Version {
    fn to_version(self) -> Result<semver::Version, String> {
        Ok(self)
    }
}

impl<'a> ToVersion for &'a str {
    fn to_version(self) -> Result<semver::Version, String> {
        match semver::parse(self) {
            Some(v) => Ok(v),
            None => Err(format!("cannot parse '{}' as a semver", self)),
        }
    }
}

trait ToUrl {
    fn to_url(self) -> Result<Url, String>;
}

impl<'a> ToUrl for &'a str {
    fn to_url(self) -> Result<Url, String> {
        Url::parse(self)
    }
}

impl ToUrl for Url {
    fn to_url(self) -> Result<Url, String> {
        Ok(self)
    }
}

impl<'a> ToUrl for &'a Url {
    fn to_url(self) -> Result<Url, String> {
        Ok(self.clone())
    }
}

#[deriving(Clone, PartialEq)]
pub struct PackageId {
    name: String,
    version: semver::Version,
    source_id: SourceId,
}

impl<S: hash::Writer> Hash<S> for PackageId {
    fn hash(&self, state: &mut S) {
        self.name.hash(state);
        self.version.to_string().hash(state);
        self.source_id.hash(state);
    }
}

impl Eq for PackageId {}

#[deriving(Clone, Show, PartialEq)]
pub enum PackageIdError {
    InvalidVersion(String),
    InvalidNamespace(String)
}

impl CargoError for PackageIdError {
    fn description(&self) -> String {
        match *self {
            InvalidVersion(ref v) => format!("invalid version: {}", *v),
            InvalidNamespace(ref ns) => format!("invalid namespace: {}", *ns),
        }
    }
    fn is_human(&self) -> bool { true }
}

#[deriving(PartialEq, Hash, Clone, Encodable)]
pub struct Metadata {
    pub metadata: String,
    pub extra_filename: String
}

impl PackageId {
    pub fn new<T: ToVersion>(name: &str, version: T,
                             sid: &SourceId) -> CargoResult<PackageId> {
        let v = try!(version.to_version().map_err(InvalidVersion));
        Ok(PackageId {
            name: name.to_string(),
            version: v,
            source_id: sid.clone()
        })
    }

    pub fn get_name<'a>(&'a self) -> &'a str {
        self.name.as_slice()
    }

    pub fn get_version<'a>(&'a self) -> &'a semver::Version {
        &self.version
    }

    pub fn get_source_id<'a>(&'a self) -> &'a SourceId {
        &self.source_id
    }

    pub fn generate_metadata(&self) -> Metadata {
        let metadata = format!("{}:-:{}:-:{}", self.name, self.version, self.source_id);
        let extra_filename = short_hash(
            &(self.name.as_slice(), self.version.to_string(), &self.source_id));

        Metadata { metadata: metadata, extra_filename: format!("-{}", extra_filename) }
    }
}

static central_repo: &'static str = "http://rust-lang.org/central-repo";

impl Show for PackageId {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        try!(write!(f, "{} v{}", self.name, self.version));

        if self.source_id.to_string().as_slice() != central_repo {
            try!(write!(f, " ({})", self.source_id));
        }

        Ok(())
    }
}

impl<D: Decoder<Box<CargoError + Send>>>
    Decodable<D,Box<CargoError + Send>>
    for PackageId
{
    fn decode(d: &mut D) -> CargoResult<PackageId> {
        let (name, version, source_id): (String, String, SourceId) = try!(Decodable::decode(d));

        PackageId::new(name.as_slice(), version.as_slice(), &source_id)
    }
}

impl<E, S: Encoder<E>> Encodable<S,E> for PackageId {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        (self.name.clone(), self.version.to_string(), self.source_id.clone()).encode(e)
    }
}

#[cfg(test)]
mod tests {
    use super::{PackageId, central_repo};
    use core::source::{Location, RegistryKind, SourceId};

    #[test]
    fn invalid_version_handled_nicely() {
        let loc = Location::parse(central_repo).unwrap();
        let repo = SourceId::new(RegistryKind, loc);

        assert!(PackageId::new("foo", "1.0", &repo).is_err());
        assert!(PackageId::new("foo", "1", &repo).is_err());
        assert!(PackageId::new("foo", "bar", &repo).is_err());
        assert!(PackageId::new("foo", "", &repo).is_err());
    }
}
<|endoftext|>


<commit_before>use bytes::{Bytes, BytesMut};
use futures_core::stream::Stream;
use pin_project_lite::pin_project;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::AsyncRead;

const CAPACITY: usize = 4096;

pin_project! {
    /// Convert an [`AsyncRead`] into a [`Stream`] of byte chunks.
    ///
    /// This stream is fused. It performs the inverse operation of
    /// [`StreamReader`].
    ///
    /// # Example
    ///
    /// ```
    /// # #[tokio::main]
    /// # async fn main() -> std::io::Result<()> {
    /// use tokio_stream::StreamExt;
    /// use tokio_util::io::ReaderStream;
    ///
    /// // Create a stream of data.
    /// let data = b"hello, world!";
    /// let mut stream = ReaderStream::new(&data[..]);
    ///
    /// // Read all of the chunks into a vector.
    /// let mut stream_contents = Vec::new();
    /// while let Some(chunk) = stream.next().await {
    ///    stream_contents.extend_from_slice(&chunk?);
    /// }
    ///
    /// // Once the chunks are concatenated, we should have the
    /// // original data.
    /// assert_eq!(stream_contents, data);
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// [`AsyncRead`]: tokio::io::AsyncRead
    /// [`StreamReader`]: crate::io::StreamReader
    /// [`Stream`]: futures_core::Stream
    #[derive(Debug)]
    pub struct ReaderStream<R> {
        // Reader itself.
        //
        // This value is `None` if the stream has terminated.
        #[pin]
        reader: Option<R>,
        // Working buffer, used to optimize allocations.
        buf: BytesMut,
    }
}

impl<R: AsyncRead> ReaderStream<R> {
    /// Convert an [`AsyncRead`] into a [`Stream`] with item type
    /// `Result<Bytes, std::io::Error>`.
    ///
    /// [`AsyncRead`]: tokio::io::AsyncRead
    /// [`Stream`]: futures_core::Stream
    pub fn new(reader: R) -> Self {
        ReaderStream {
            reader: Some(reader),
            buf: BytesMut::new(),
        }
    }
}

impl<R: AsyncRead> Stream for ReaderStream<R> {
    type Item = std::io::Result<Bytes>;
    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        use crate::util::poll_read_buf;

        let mut this = self.as_mut().project();

        let reader = match this.reader.as_pin_mut() {
            Some(r) => r,
            None => return Poll::Ready(None),
        };

        if this.buf.capacity() == 0 {
            this.buf.reserve(CAPACITY);
        }

        match poll_read_buf(reader, cx, &mut this.buf) {
            Poll::Pending => Poll::Pending,
            Poll::Ready(Err(err)) => {
                self.project().reader.set(None);
                Poll::Ready(Some(Err(err)))
            }
            Poll::Ready(Ok(0)) => {
                self.project().reader.set(None);
                Poll::Ready(None)
            }
            Poll::Ready(Ok(_)) => {
                let chunk = this.buf.split();
                Poll::Ready(Some(Ok(chunk.freeze())))
            }
        }
    }
}
<commit_msg>io: add with_capacity for ReaderStream (#4086)<commit_after>use bytes::{Bytes, BytesMut};
use futures_core::stream::Stream;
use pin_project_lite::pin_project;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::AsyncRead;

const DEFAULT_CAPACITY: usize = 4096;

pin_project! {
    /// Convert an [`AsyncRead`] into a [`Stream`] of byte chunks.
    ///
    /// This stream is fused. It performs the inverse operation of
    /// [`StreamReader`].
    ///
    /// # Example
    ///
    /// ```
    /// # #[tokio::main]
    /// # async fn main() -> std::io::Result<()> {
    /// use tokio_stream::StreamExt;
    /// use tokio_util::io::ReaderStream;
    ///
    /// // Create a stream of data.
    /// let data = b"hello, world!";
    /// let mut stream = ReaderStream::new(&data[..]);
    ///
    /// // Read all of the chunks into a vector.
    /// let mut stream_contents = Vec::new();
    /// while let Some(chunk) = stream.next().await {
    ///    stream_contents.extend_from_slice(&chunk?);
    /// }
    ///
    /// // Once the chunks are concatenated, we should have the
    /// // original data.
    /// assert_eq!(stream_contents, data);
    /// # Ok(())
    /// # }
    /// ```
    ///
    /// [`AsyncRead`]: tokio::io::AsyncRead
    /// [`StreamReader`]: crate::io::StreamReader
    /// [`Stream`]: futures_core::Stream
    #[derive(Debug)]
    pub struct ReaderStream<R> {
        // Reader itself.
        //
        // This value is `None` if the stream has terminated.
        #[pin]
        reader: Option<R>,
        // Working buffer, used to optimize allocations.
        buf: BytesMut,
        capacity: usize,
    }
}

impl<R: AsyncRead> ReaderStream<R> {
    /// Convert an [`AsyncRead`] into a [`Stream`] with item type
    /// `Result<Bytes, std::io::Error>`.
    ///
    /// [`AsyncRead`]: tokio::io::AsyncRead
    /// [`Stream`]: futures_core::Stream
    pub fn new(reader: R) -> Self {
        ReaderStream {
            reader: Some(reader),
            buf: BytesMut::new(),
            capacity: DEFAULT_CAPACITY,
        }
    }

    /// Convert an [`AsyncRead`] into a [`Stream`] with item type
    /// `Result<Bytes, std::io::Error>`,
    /// with a specific read buffer initial capacity.
    ///
    /// [`AsyncRead`]: tokio::io::AsyncRead
    /// [`Stream`]: futures_core::Stream
    pub fn with_capacity(reader: R, capacity: usize) -> Self {
        ReaderStream {
            reader: Some(reader),
            buf: BytesMut::with_capacity(capacity),
            capacity,
        }
    }
}

impl<R: AsyncRead> Stream for ReaderStream<R> {
    type Item = std::io::Result<Bytes>;
    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        use crate::util::poll_read_buf;

        let mut this = self.as_mut().project();

        let reader = match this.reader.as_pin_mut() {
            Some(r) => r,
            None => return Poll::Ready(None),
        };

        if this.buf.capacity() == 0 {
            this.buf.reserve(*this.capacity);
        }

        match poll_read_buf(reader, cx, &mut this.buf) {
            Poll::Pending => Poll::Pending,
            Poll::Ready(Err(err)) => {
                self.project().reader.set(None);
                Poll::Ready(Some(Err(err)))
            }
            Poll::Ready(Ok(0)) => {
                self.project().reader.set(None);
                Poll::Ready(None)
            }
            Poll::Ready(Ok(_)) => {
                let chunk = this.buf.split();
                Poll::Ready(Some(Ok(chunk.freeze())))
            }
        }
    }
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]

use std::mem;
use std::os::raw::c_void;
use std::ffi::CStr;

extern crate glfw;
use self::glfw::Context;

extern crate gl;

use cgmath::{Matrix4, Deg, Vector2, vec3, Point3, perspective};

use num::range_step;

use common::{process_events, processInput};
use shader::Shader;
use camera::Camera;

// settings
const SCR_WIDTH: u32 = 1280;
const SCR_HEIGHT: u32 = 720;

// TODO: copied from 4.10.1
pub fn main_4_10_1() {
    let mut camera = Camera {
        Position: Point3::new(0.0, 0.0, 3.0),
        ..Camera::default()
    };

    let mut firstMouse = true;
    let mut lastX: f32 = SCR_WIDTH as f32 / 2.0;
    let mut lastY: f32 = SCR_HEIGHT as f32 / 2.0;

    // timing
    let mut deltaTime: f32; // time between current frame and last frame
    let mut lastFrame: f32 = 0.0;

    // glfw: initialize and configure
    // ------------------------------
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    #[cfg(target_os = "macos")]
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));

    // glfw window creation
    // --------------------
    let (mut window, events) = glfw.create_window(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window");

    window.make_current();
    window.set_framebuffer_size_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_scroll_polling(true);

    // tell GLFW to capture our mouse
    window.set_cursor_mode(glfw::CursorMode::Disabled);

    // gl: load all OpenGL function pointers
    // ---------------------------------------
    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    let (shader, ) = unsafe {
        // configure global opengl state
        // -----------------------------
        gl::Enable(gl::DEPTH_TEST);

        // build and compile shaders
        // -------------------------
        let shader = Shader::new(
            "src/_4_advanced_opengl/shaders/10.1.instancing.vs",
            "src/_4_advanced_opengl/shaders/10.1.instancing.fs",
        );

        // generate a list of 100 quad locations/translation-vectors
        // ---------------------------------------------------------
        let mut translations = vec![];
        let offset = 0.1;
        for y in range_step(-10, 10, 2) {
            for x in range_step(-10, 10, 2) {
                translations.push(
                    Vector2 {
                        x: x as i32 as f32 / 10.0 + offset,
                        y: y as i32 as f32 / 10.0 + offset
                    }
                )
            }
        }

        let mut instanceVBO = 0;
        gl::GenBuffers(1, &mut instanceVBO);
        gl::BindBuffer(gl::ARRAY_BUFFER, instanceVBO);
        gl::BufferData(
            gl::ARRAY_BUFFER,
            mem::size_of::<Vector2<f32>>() as isize * 100 ,
            &translations[0] as *const Vector2<f32> as *const c_void,
            gl::STATIC_DRAW);
        gl::BindBuffer(gl::ARRAY_BUFFER, 0);

        // TODO!!!

        (shader, )
    };

    // render loop
    // -----------
    while !window.should_close() {
        // per-frame time logic
        // --------------------
        let currentFrame = glfw.get_time() as f32;
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // events
        // -----
        process_events(&events, &mut firstMouse, &mut lastX, &mut lastY, &mut camera);

        // input
        // -----
        processInput(&mut window, deltaTime, &mut camera);

        // render
        // ------
        unsafe {
            gl::ClearColor(0.1, 0.1, 0.1, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            // configure transformation matrices
            let projection: Matrix4<f32> = perspective(Deg(45.0), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 100.0);
            let view = camera.GetViewMatrix();
            let mut model = Matrix4::<f32>::from_translation(vec3(0.0, -1.75, 0.0)); // translate it down so it's at the center of the scene
            model = model * Matrix4::from_scale(0.2);  // it's a bit too big for our scene, so scale it down
            shader.useProgram();
            shader.setMat4(c_str!("projection"), &projection);
            shader.setMat4(c_str!("view"), &view);
            shader.setMat4(c_str!("model"), &model);

        }

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        window.swap_buffers();
        glfw.poll_events();
    }
}
<commit_msg>"finish" 4.10.1, but not working<commit_after>#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]

use std::ptr;
use std::mem;
use std::os::raw::c_void;

extern crate glfw;
use self::glfw::Context;

extern crate gl;
use self::gl::types::*;

use cgmath::{Vector2};

use num::range_step;

use shader::Shader;

// settings
const SCR_WIDTH: u32 = 1280;
const SCR_HEIGHT: u32 = 720;

pub fn main_4_10_1() {
    // glfw: initialize and configure
    // ------------------------------
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    #[cfg(target_os = "macos")]
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));

    // glfw window creation
    // --------------------
    let (mut window, _events) = glfw.create_window(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window");

    window.make_current();
    window.set_framebuffer_size_polling(true);

    // gl: load all OpenGL function pointers
    // ---------------------------------------
    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    let (shader, quadVAO, quadVBO) = unsafe {
        // configure global opengl state
        // -----------------------------
        gl::Enable(gl::DEPTH_TEST);

        // build and compile shaders
        // -------------------------
        let shader = Shader::new(
            "src/_4_advanced_opengl/shaders/10.1.instancing.vs",
            "src/_4_advanced_opengl/shaders/10.1.instancing.fs",
        );

        // generate a list of 100 quad locations/translation-vectors
        // ---------------------------------------------------------
        let mut translations = vec![];
        let offset = 0.1;
        for y in range_step(-10, 10, 2) {
            for x in range_step(-10, 10, 2) {
                translations.push(
                    Vector2 {
                        x: x as i32 as f32 / 10.0 + offset,
                        y: y as i32 as f32 / 10.0 + offset
                    }
                )
            }
        }

        let mut instanceVBO = 0;
        gl::GenBuffers(1, &mut instanceVBO);
        gl::BindBuffer(gl::ARRAY_BUFFER, instanceVBO);
        gl::BufferData(
            gl::ARRAY_BUFFER,
            mem::size_of::<Vector2<f32>>() as isize * 100 ,
            &translations[0] as *const Vector2<f32> as *const c_void,
            gl::STATIC_DRAW);
        gl::BindBuffer(gl::ARRAY_BUFFER, 0);

        // set up vertex data (and buffer(s)) and configure vertex attributes
        // ------------------------------------------------------------------
        let quadVertices: [f32; 30] = [
            // positions   // colors
            -0.05,  0.05,  1.0, 0.0, 0.0,
             0.05, -0.05,  0.0, 1.0, 0.0,
            -0.05, -0.05,  0.0, 0.0, 1.0,

            -0.05,  0.05,  1.0, 0.0, 0.0,
             0.05, -0.05,  0.0, 1.0, 0.0,
             0.05,  0.05,  0.0, 1.0, 1.0
        ];
        let (mut quadVAO, mut quadVBO) = (0, 0);
        gl::GenVertexArrays(1, &mut quadVAO);
        gl::GenBuffers(1, &mut quadVBO);
        gl::BindVertexArray(quadVBO);
        gl::BindBuffer(gl::ARRAY_BUFFER, quadVBO);
        gl::BufferData(gl::ARRAY_BUFFER,
                       (quadVertices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
                       &quadVertices[0] as *const f32 as *const c_void,
                       gl::STATIC_DRAW);
        gl::EnableVertexAttribArray(0);
        let stride = 5 * mem::size_of::<GLfloat>() as GLsizei;
        gl::VertexAttribPointer(0, 2, gl::FLOAT, gl::FALSE, stride, ptr::null());
        gl::EnableVertexAttribArray(1);
        gl::VertexAttribPointer(1, 3, gl::FLOAT, gl::FALSE, stride, (2 * mem::size_of::<GLfloat>()) as *const c_void);
        // also set instance data
        gl::EnableVertexAttribArray(2);
        gl::BindBuffer(gl::ARRAY_BUFFER, instanceVBO); // this attribute comes from a different vertex buffer
        gl::VertexAttribPointer(2, 2, gl::FLOAT, gl::FALSE, (2 * mem::size_of::<GLfloat>()) as i32, ptr::null());
        gl::BindBuffer(gl::ARRAY_BUFFER, 0);
        gl::VertexAttribDivisor(2, 1); // tell OpenGL this is an instanced vertex attribute.

        (shader, quadVAO, quadVBO)
    };

    // render loop
    // -----------
    while !window.should_close() {
        // render
        // ------
        unsafe {
            gl::ClearColor(0.1, 0.1, 0.1, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            // draw 100 instanced quads
            shader.useProgram();
            gl::BindVertexArray(quadVAO);
            gl::DrawArraysInstanced(gl::TRIANGLES, 0, 6, 100); // 100 triangles of 6 vertices each
            gl::BindVertexArray(0);
        }

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        window.swap_buffers();
        glfw.poll_events();
    }

        // optional: de-allocate all resources once they've outlived their purpose:
    // ------------------------------------------------------------------------
    unsafe {
        gl::DeleteVertexArrays(1, &quadVAO);
        gl::DeleteBuffers(1, &quadVBO);
    }
}
<|endoftext|>


<commit_before>
extern crate cdrs;
#[macro_use]
extern crate log;
extern crate env_logger;

use cdrs::client::CDRS;
use cdrs::query::QueryBuilder;
use cdrs::authenticators::NoneAuthenticator;
use cdrs::compression::Compression;
use cdrs::consistency::Consistency;
use cdrs::transport::TransportPlain;
use cdrs::query::QueryParamsBuilder;
use cdrs::types::value::Value;

// default credentials
const _ADDR: &'static str = "127.0.0.1:9042";

pub struct TestContext {
    pub client: cdrs::client::CDRS<NoneAuthenticator, TransportPlain>,
}

impl TestContext {
    fn new() -> TestContext {
        const _ADDR: &'static str = "127.0.0.1:9042";
        let authenticator = NoneAuthenticator;
        let tcp_transport = TransportPlain::new(_ADDR);
        let client = CDRS::new(tcp_transport.unwrap(), authenticator);
        TestContext { client: client }
    }
}

#[test]
fn create_keyspace() {
    let ctx = TestContext::new();
    let mut session = ctx.client.start(Compression::None).unwrap();
    let create_ks_cql = "CREATE KEYSPACE user_keyspace WITH REPLICATION = { 'class' : \
                         'SimpleStrategy', 'replication_factor' : 1 } ;";

    let create_ks_query = QueryBuilder::new(create_ks_cql)
        .consistency(Consistency::One)
        .finalize();

    let create_ks_query_result = session.query(create_ks_query, false, false);

    assert_eq!(create_ks_query_result.is_ok(), true);

}

#[test]
fn create_table() {
    let ctx = TestContext::new();
    let mut session = ctx.client.start(Compression::None).unwrap();
    let create_table_cql = "CREATE TABLE user_keyspace.users (
        user_name varchar PRIMARY KEY,
        password varchar,
        gender varchar,
        session_token varchar,
        state varchar,
        birth_year bigint
    );";

    let create_table_query = QueryBuilder::new(create_table_cql)
        .consistency(Consistency::One)
        .finalize();

    let create_table_query_result = session.query(create_table_query, false, false);

    assert_eq!(create_table_query_result.is_ok(), true);

    match create_table_query_result {
        Ok(ref res) => println!("table created: {:?}", res.get_body()),
        Err(ref err) => println!("Error occured: {:?}", err),
    }

}

#[test]
fn insert_data_users() {

    let ctx = TestContext::new();
    let mut session = ctx.client.start(Compression::None).unwrap();
    let insert_table_cql = " insert into user_keyspace.users
            (user_name ,password,gender,session_token, state)
    values  (?         ,  ?     ,     ?,            ?,     ?)";

    let prepared = session.prepare(insert_table_cql.to_string(), true, true)
        .unwrap()
        .get_body()
        .into_prepared()
        .unwrap();

    println!("prepared:\n{:?}", prepared);

    let v: Vec<Value> = vec![Value::new_normal(String::from("harry").into_bytes()),
                             Value::new_normal(String::from("pwd").into_bytes()),
                             Value::new_normal(String::from("male").into_bytes()),
                             Value::new_normal(String::from("09000").into_bytes()),
                             Value::new_normal(String::from("FL").into_bytes())];
    let execution_params = QueryParamsBuilder::new(Consistency::One).values(v).finalize();

    let query_id = prepared.id;
    //    let executed = session.execute(query_id, execution_params, true, true)
    //        .unwrap()
    //        .get_body()
    //        .into_set_keyspace()
    //        .unwrap();

    let executed = session.execute(query_id, execution_params, true, true);

    info!("executed:\n{:?}", executed);

}

#[test]
fn drop_keyspace() {
    let ctx = TestContext::new();
    let mut session = ctx.client.start(Compression::None).unwrap();
    let drop_ks = "DROP KEYSPACE user_keyspace;";
    let with_tracing = false;
    let with_warnings = false;
    let drop_ks_query = QueryBuilder::new(drop_ks).consistency(Consistency::One).finalize();
    let drop_ks_query_result = session.query(drop_ks_query, with_tracing, with_warnings);

    assert_eq!(drop_ks_query_result.is_ok(), true);

    match drop_ks_query_result {
        Ok(ref res) => println!("keyspace dropped: {:?}", res.get_body()),
        Err(ref err) => println!("Error occured: {:?}", err),
    }
}
<commit_msg>added more test<commit_after>extern crate cdrs;
#[macro_use]
extern crate log;
extern crate env_logger;

use cdrs::client::CDRS;
use cdrs::query::QueryBuilder;
use cdrs::authenticators::NoneAuthenticator;
use cdrs::compression::Compression;
use cdrs::consistency::Consistency;
use cdrs::transport::TransportPlain;
use cdrs::query::QueryParamsBuilder;
use cdrs::types::value::Value;
use std::panic;

// default credentials
const _ADDR: &'static str = "127.0.0.1:9042";

pub struct TestContext {
    pub client: cdrs::client::CDRS<NoneAuthenticator, TransportPlain>,
}

impl TestContext {
    fn new() -> TestContext {
        const _ADDR: &'static str = "127.0.0.1:9042";
        let authenticator = NoneAuthenticator;
        let tcp_transport = TransportPlain::new(_ADDR);
        let client = CDRS::new(tcp_transport.unwrap(), authenticator);
        TestContext { client: client }
    }
}

fn create_keyspace() {
    let ctx = TestContext::new();
    let mut session = ctx.client.start(Compression::None).unwrap();
    let create_ks_cql = "CREATE KEYSPACE user_keyspace WITH REPLICATION = { 'class' : \
                         'SimpleStrategy', 'replication_factor' : 1 } ;";

    let create_ks_query = QueryBuilder::new(create_ks_cql)
        .consistency(Consistency::One)
        .finalize();

    let create_ks_query_result = session.query(create_ks_query, false, false);

    assert_eq!(create_ks_query_result.is_ok(), true);
}

fn create_table() {
    let ctx = TestContext::new();
    let mut session = ctx.client.start(Compression::None).unwrap();
    let create_table_cql = "CREATE TABLE user_keyspace.users (
        user_name varchar PRIMARY KEY,
        password varchar,
        gender varchar,
        session_token varchar,
        state varchar,
        birth_year bigint
    );";

    let create_table_query = QueryBuilder::new(create_table_cql)
        .consistency(Consistency::One)
        .finalize();

    let create_table_query_result = session.query(create_table_query, false, false);

    assert_eq!(create_table_query_result.is_ok(), true);

    match create_table_query_result {
        Ok(ref res) => println!("table created: {:?}", res.get_body()),
        Err(ref err) => println!("Error occured: {:?}", err),
    }
}

#[test]
fn test_something_interesting() {
    run_test(|| insert_data_users())
}

fn run_test<T>(test: T) -> ()
    where T: FnOnce() -> () + panic::UnwindSafe
{
    setup();

    let result = panic::catch_unwind(|| test());

    teardown();

    assert!(result.is_ok())
}

fn setup() {
    create_keyspace();
    create_table();
}

fn teardown() {
    drop_keyspace();
}

fn insert_data_users() {
    let ctx = TestContext::new();
    let mut session = ctx.client.start(Compression::None).unwrap();
    let insert_table_cql = " insert into user_keyspace.users
            (user_name ,password,gender,session_token, state)
    values  (?         ,  ?     ,     ?,            ?,     ?)";

    let prepared = session.prepare(insert_table_cql.to_string(), true, true)
        .unwrap()
        .get_body()
        .into_prepared()
        .unwrap();

    println!("prepared:\n{:?}", prepared);

    let v: Vec<Value> = vec![Value::new_normal(String::from("harry").into_bytes()),
                             Value::new_normal(String::from("pwd").into_bytes()),
                             Value::new_normal(String::from("male").into_bytes()),
                             Value::new_normal(String::from("09000").into_bytes()),
                             Value::new_normal(String::from("FL").into_bytes())];
    let execution_params = QueryParamsBuilder::new(Consistency::One).values(v).finalize();

    let query_id = prepared.id;
    //    let executed = session.execute(query_id, execution_params, true, true)
    //        .unwrap()
    //        .get_body()
    //        .into_set_keyspace()
    //        .unwrap();

    let executed = session.execute(query_id, execution_params, true, true);

    info!("executed:\n{:?}", executed);
}

fn drop_keyspace() {
    let ctx = TestContext::new();
    let mut session = ctx.client.start(Compression::None).unwrap();
    let drop_ks = "DROP KEYSPACE user_keyspace;";
    let with_tracing = false;
    let with_warnings = false;
    let drop_ks_query = QueryBuilder::new(drop_ks).consistency(Consistency::One).finalize();
    let drop_ks_query_result = session.query(drop_ks_query, with_tracing, with_warnings);

    assert_eq!(drop_ks_query_result.is_ok(), true);

    match drop_ks_query_result {
        Ok(ref res) => println!("keyspace dropped: {:?}", res.get_body()),
        Err(ref err) => println!("Error occured: {:?}", err),
    }
}
<|endoftext|>


<commit_before>extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use structopt::StructOpt;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

type Position = usize;
type Name = char;

enum Operation {
    Spin(Position),
    Exchange(Position, Position),
    Partner(Name, Name),
}

impl std::str::FromStr for Operation {
    type Err = String;
    fn from_str(input: &str) -> Result<Self, Self::Err> {
        let mut chars = input.trim().chars();
        match chars.next() {
            Some('s') => chars.as_str().parse().map(Operation::Spin).map_err(
                |_| format!("Could not parse position from {}", chars.as_str()),
            ),
            Some('x') => {
                let mut split = chars.as_str().split('/');
                match (split.next(), split.next()) {
                    (Some(a), Some(b)) => Ok(Operation::Exchange(
                        a.parse().map_err(|_| {
                            format!("Could not parse {} as position", a)
                        })?,
                        b.parse().map_err(|_| {
                            format!("Could not parse {} as position", b)
                        })?,
                    )),
                    _ => Err(format!("Could not parse {} as Operation", input)),
                }
            },
            Some('p') => {
                let mut split = chars.as_str().split('/');
                match (split.next(), split.next()) {
                    (Some(a), Some(b)) => Ok(Operation::Partner(
                        a.parse().map_err(|_| {
                            format!("Could not parse {} as name", a)
                        })?,
                        b.parse().map_err(|_| {
                            format!("Could not parse {} as name", b)
                        })?,
                    )),
                    _ => Err(format!("Could not parse {} as Operation", input)),
                }
            }
            _ => Err(format!("Could not parse {} as Operation", input)),
        }
    }
}

fn cycle_len(initial: &str, input: &str) -> usize {
    let mut cycle_len = 1;
    let mut changed = part1(initial, input);
    while changed != initial {
        changed = part1(&changed, input);
        cycle_len += 1;
    }
    cycle_len
}

fn part1(initial: &str, input: &str) -> String {
    let mut result = initial.to_owned();
    let instructions: Vec<Operation> =
        input.split(',').map(|s| s.parse().unwrap()).collect();
    for instr in instructions {
        match instr {
            Operation::Spin(p) => {
                result = {
                    let split = result.split_at(result.len() - p);
                    let mut swapped = split.1.to_owned();
                    swapped.push_str(split.0);
                    swapped
                }
            }
            Operation::Exchange(a, b) => {
                unsafe { result.as_bytes_mut() }.swap(a, b);
            }
            Operation::Partner(a, b) => {
                let loc_a =
                    result.find(a).expect(&format!("Could not find {}", a));
                let loc_b =
                    result.find(b).expect(&format!("Could not find {}", b));
                unsafe { result.as_bytes_mut() }.swap(loc_a, loc_b);
            }
        }
    }
    result
}

fn part2(initial: &str, input: &str, count: usize) -> String {
    let cycle = cycle_len(initial, input);
    let mut result = initial.to_owned();
    for _ in 0..(count % cycle) {
        result = part1(&result, input);
    }
    result
}

fn main() {
    let opt = Opt::from_args();
    let mut contents = String::new();
    if opt.input.to_str() == Some("-") {
        std::io::stdin()
            .read_to_string(&mut contents)
            .expect("could not read stdin");
    } else {
        let mut file = File::open(&opt.input)
            .expect(&format!("file {} not found", opt.input.display()));
        file.read_to_string(&mut contents)
            .expect(&format!("could not read file {}", opt.input.display()));
    }
    println!("Part 1: {}", part1("abcdefghijklmnop", &contents));
    println!("Part 2: {}", part2("abcdefghijklmnop", &contents, 1_000_000_000));
}

#[derive(StructOpt, Debug)]
#[structopt(name = "day13", about = "Advent of code 2017 day 13")]
struct Opt {
    #[structopt(help = "Input file", parse(from_os_str))] input: PathBuf,
}

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

    #[test]
    fn part1_test() {
        assert_eq!(part1("abcde", "s1,x3/4,pe/b"), "baedc");
    }

    #[test]
    fn part4_test() {
        assert_eq!(part2("abcde", "s1,x3/4,pe/b", 2), "ceadb");
    }
}
<commit_msg>Make minor improvements to 2017 day 16<commit_after>extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use structopt::StructOpt;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

type Position = usize;
type Name = char;

enum Operation {
    Spin(Position),
    Exchange(Position, Position),
    Partner(Name, Name),
}

impl std::str::FromStr for Operation {
    type Err = String;
    fn from_str(input: &str) -> Result<Self, Self::Err> {
        let mut chars = input.trim().chars();
        match chars.next() {
            Some('s') => chars.as_str().parse().map(Operation::Spin).map_err(
                |_| format!("Could not parse position from {}", chars.as_str()),
            ),
            Some('x') => {
                let mut split = chars.as_str().split('/');
                match (split.next(), split.next()) {
                    (Some(a), Some(b)) => Ok(Operation::Exchange(
                        a.parse().map_err(|_| {
                            format!("Could not parse {} as position", a)
                        })?,
                        b.parse().map_err(|_| {
                            format!("Could not parse {} as position", b)
                        })?,
                    )),
                    _ => Err(format!("Could not parse {} as Operation", input)),
                }
            }
            Some('p') => {
                let mut split = chars.as_str().split('/');
                match (split.next(), split.next()) {
                    (Some(a), Some(b)) => Ok(Operation::Partner(
                        a.parse().map_err(|_| {
                            format!("Could not parse {} as name", a)
                        })?,
                        b.parse().map_err(|_| {
                            format!("Could not parse {} as name", b)
                        })?,
                    )),
                    _ => Err(format!("Could not parse {} as Operation", input)),
                }
            }
            _ => Err(format!("Could not parse {} as Operation", input)),
        }
    }
}

fn parse(input: &str) -> Vec<Operation> {
    input
        .split(',')
        .map(|s| s.parse().expect("Could not parse instructions"))
        .collect()
}

fn part1(initial: &str, input: &[Operation]) -> String {
    let mut result = initial.to_owned();
    for instr in input {
        match *instr {
            Operation::Spin(p) => {
                result = {
                    let split = result.split_at(result.len() - p);
                    let mut swapped = split.1.to_owned();
                    swapped.push_str(split.0);
                    swapped
                }
            }
            Operation::Exchange(a, b) => {
                unsafe { result.as_bytes_mut() }.swap(a, b);
            }
            Operation::Partner(a, b) => {
                let loc_a =
                    result.find(a).expect(&format!("Could not find {}", a));
                let loc_b =
                    result.find(b).expect(&format!("Could not find {}", b));
                unsafe { result.as_bytes_mut() }.swap(loc_a, loc_b);
            }
        }
    }
    result
}

fn cycle_len(initial: &str, input: &[Operation]) -> usize {
    let mut cycle_len = 1;
    let mut changed = part1(initial, input);
    while changed != initial {
        changed = part1(&changed, input);
        cycle_len += 1;
    }
    cycle_len
}

fn part2(initial: &str, input: &[Operation], count: usize) -> String {
    let cycle = cycle_len(initial, input);
    let mut result = initial.to_owned();
    for _ in 0..(count % cycle) {
        result = part1(&result, input);
    }
    result
}

fn main() {
    let opt = Opt::from_args();
    let mut contents = String::new();
    if opt.input.to_str() == Some("-") {
        std::io::stdin()
            .read_to_string(&mut contents)
            .expect("could not read stdin");
    } else {
        let mut file = File::open(&opt.input)
            .expect(&format!("file {} not found", opt.input.display()));
        file.read_to_string(&mut contents)
            .expect(&format!("could not read file {}", opt.input.display()));
    }
    let instructions = parse(&contents);
    println!("Part 1: {}", part1("abcdefghijklmnop", &instructions));
    println!(
        "Part 2: {}",
        part2("abcdefghijklmnop", &instructions, 1_000_000_000)
    );
}

#[derive(StructOpt, Debug)]
#[structopt(name = "day13", about = "Advent of code 2017 day 13")]
struct Opt {
    #[structopt(help = "Input file", parse(from_os_str))] input: PathBuf,
}

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

    #[test]
    fn part1_test() {
        assert_eq!(part1("abcde", &parse("s1,x3/4,pe/b")), "baedc");
    }

    #[test]
    fn part4_test() {
        assert_eq!(part2("abcde", &parse("s1,x3/4,pe/b"), 2), "ceadb");
    }
}
<|endoftext|>


<commit_before>extern crate itertools;

extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use structopt::StructOpt;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum GridBuildError {
    Unsquare,
    // ^ Trying to build grid from non-square number of elements
    BadSideLen,
    // ^ Side length not divisible by 2 or 3
}

impl std::fmt::Display for GridBuildError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        use GridBuildError::*;
        match *self {
            Unsquare => write!(f, "Unsquare"),
            BadSideLen => write!(f, "Bad Side Length"),
        }
    }
}

impl std::error::Error for GridBuildError {
    fn description(&self) -> &str {
        use GridBuildError::*;
        match *self {
            Unsquare => "Non-square number of elements",
            BadSideLen => "Side length not divisible by 2 or 3",
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Rule {
    before: Grid,
    after: Grid,
}

type RuleSet = std::collections::HashMap<Grid, Grid>;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Grid {
    side_len: usize,     // this shall always be divisible by 2 or 3
    contents: Vec<bool>, // this shall always have side_len * side_len rows
}

impl Grid {
    fn empty() -> Grid {
        Grid {
            side_len: 0,
            contents: Vec::new(),
        }
    }

    fn from_components(
        side_len: usize,
        contents: Vec<bool>,
    ) -> Result<Grid, GridBuildError> {
        if side_len * side_len != contents.len() {
            return Err(GridBuildError::Unsquare);
        }
        if side_len % 2 != 0 && side_len % 3 != 0 {
            return Err(GridBuildError::BadSideLen);
        }
        Ok(Grid {
            side_len: side_len,
            contents: contents,
        })
    }

    fn from_subgrids<T>(container: T) -> Result<Grid, GridBuildError>
    where
        T: IntoIterator<Item = Grid>,
        T::IntoIter: ExactSizeIterator,
    {
        // "sg" = "subgrid"
        let mut iter = container.into_iter().peekable();
        let sg_side_len = match iter.peek() {
            Some(sg) => sg.side_len,
            None => return Ok(Grid::empty()),
        };
        let side_len = ((iter.len() as f64).sqrt() as usize) * sg_side_len;
        let mut contents = vec![false; side_len * side_len];
        for (b, sg) in iter.enumerate() {
            for r in 0..sg_side_len {
                for c in 0..sg_side_len {
                    let src_row =
                        b / (side_len / sg_side_len) * sg_side_len + r;
                    let src_col =
                        b % (side_len / sg_side_len) * sg_side_len + c;
                    contents[src_row * side_len + src_col] =
                        sg.contents[r * sg_side_len + c];
                }
            }
        }
        Grid::from_components(side_len, contents)
    }

    fn from_bools<T>(container: T) -> Result<Grid, GridBuildError>
    where
        T: IntoIterator<Item = bool>,
        T::IntoIter: ExactSizeIterator,
    {
        let iter = container.into_iter();
        let side_len = (iter.len() as f64).sqrt() as usize;
        Grid::from_components(side_len, iter.collect())
    }

    fn split(&self) -> Vec<Grid> {
        // in this function, "sg" = "subgrid"
        let sg_side_len = if self.contents.len() % 4 == 0 { 2 } else { 3 };
        let mut grids = Vec::new();
        for b in 0..self.contents.len() / (sg_side_len * sg_side_len) {
            let mut sg_contents = vec![false; sg_side_len * sg_side_len];
            for r in 0..sg_side_len {
                for c in 0..sg_side_len {
                    let src_row =
                        b / (self.side_len / sg_side_len) * sg_side_len + r;
                    let src_col =
                        b % (self.side_len / sg_side_len) * sg_side_len + c;
                    sg_contents[r * sg_side_len + c] =
                        self.contents[src_row * self.side_len + src_col];
                }
            }
            grids.push(Grid {
                side_len: sg_side_len,
                contents: sg_contents,
            });
        }
        grids
    }

    fn enhance(&self, rules: &RuleSet) -> Option<Grid> {
        rules.get(self).cloned().map(|g| {
            Self::from_bools(g.contents).expect("Error enhancing grid")
        })
    }

    fn iterate(&self, rules: &RuleSet) -> Grid {
        Grid::from_subgrids(self.split().iter().map(|grid| {
            grid.enhance(rules)
                .expect(&format!("Rule not found: \n{}", grid))
        })).expect("Grid Iteration: Invalid subgrid produced")
    }

    fn count(&self) -> usize {
        self.contents.iter().filter(|b| **b).count()
    }

    fn rotate_ccw(&self) -> Grid {
        let mut contents = vec![false; self.contents.len()];
        for r in 0..self.side_len {
            for c in 0..self.side_len {
                let dst_row = self.side_len - c - 1;
                let dst_col = r;
                contents[dst_row * self.side_len + dst_col] =
                    self.contents[r * self.side_len + c];
            }
        }
        Grid::from_components(self.side_len, contents).expect("Error rotating")
    }

    fn flip_lr(&self) -> Grid {
        let mut contents = vec![false; self.contents.len()];
        for r in 0..self.side_len {
            for c in 0..self.side_len {
                contents[r * self.side_len + (self.side_len - c - 1)] =
                    self.contents[r * self.side_len + c];
            }
        }
        Grid::from_components(self.side_len, contents).expect("Error flipping")
    }
}

impl std::str::FromStr for Grid {
    type Err = GridBuildError;
    fn from_str(s: &str) -> Result<Grid, Self::Err> {
        let contents: Vec<_> = s.bytes()
            .filter_map(|b| match b {
                b'#' => Some(true),
                b'.' => Some(false),
                _ => None,
            })
            .collect();
        Self::from_bools(contents)
    }
}

impl std::fmt::Display for Grid {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        for (pos, val) in self.contents.iter().enumerate() {
            if pos != 0 && pos % self.side_len == 0 {
                write!(f, "\n")?
            }
            write!(f, "{}", if *val { '#' } else { '.' })?
        }
        Ok(())
    }
}

fn parse(input: &str) -> Vec<Rule> {
    use std::str::FromStr;
    input
        .lines()
        .map(|line| {
            let (before, after) = line.split_at(
                line.find("=>").expect(&format!("Invalid line: {}", line)),
            );
            Rule {
                before: Grid::from_str(before)
                    .expect(&format!("Could not parse grid from {}", before)),
                after: Grid::from_str(after)
                    .expect(&format!("Could not parse grid from {}", after)),
            }
        })
        .collect()
}

fn make_ruleset(rule_list: &[Rule]) -> RuleSet {
    let mut rule_set = std::collections::HashMap::new();
    for rule in rule_list {
        let mut new_rule = rule.before.clone();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.flip_lr();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
    }
    rule_set
}

fn start() -> Grid {
    Grid {
        side_len: 3,
        contents: vec![
            false, true, false, false, false, true, true, true, true
        ],
    }
}

fn part1(rules: &RuleSet) -> usize {
    itertools::iterate(start(), |g| g.iterate(rules))
        .nth(5)
        .unwrap()
        .count()
}

fn main() {
    let opt = Opt::from_args();
    let mut contents = String::new();
    if opt.input.to_str() == Some("-") {
        std::io::stdin()
            .read_to_string(&mut contents)
            .expect("could not read stdin");
    } else {
        let mut file = File::open(&opt.input)
            .expect(&format!("file {} not found", opt.input.display()));
        file.read_to_string(&mut contents)
            .expect(&format!("could not read file {}", opt.input.display()));
    }
    let rule_list = parse(&contents);
    let rules = make_ruleset(&rule_list);
    println!("Part 1: {}", part1(&rules));
}

#[derive(StructOpt, Debug)]
#[structopt(name = "day20", about = "Advent of code 2017 day 20")]
struct Opt {
    #[structopt(help = "Input file", parse(from_os_str))]
    input: PathBuf,
}

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

    #[test]
    fn rotate_ccw_test() {
        assert_eq!(
            Grid::from_str("#...##...").unwrap().rotate_ccw(),
            Grid::from_str(".#..#.#..").unwrap(),
        );
        assert_eq!(
            Grid::from_str("#.#.").unwrap().rotate_ccw(),
            Grid::from_str("..##").unwrap(),
        );
        assert_eq!(
            Grid::from_str("#...##...")
                .unwrap()
                .rotate_ccw()
                .rotate_ccw()
                .rotate_ccw()
                .rotate_ccw(),
            Grid::from_str("#...##...").unwrap()
        );
    }

    #[test]
    fn flip_lr_test() {
        assert_eq!(
            Grid::from_str("#...##...").unwrap().flip_lr(),
            Grid::from_str("..###....").unwrap(),
        );
        assert_eq!(
            Grid::from_str("#.#.").unwrap().flip_lr(),
            Grid::from_str(".#.#").unwrap(),
        );
        assert_eq!(
            Grid::from_str("#...##...").unwrap().flip_lr().flip_lr(),
            Grid::from_str("#...##...").unwrap(),
        );
    }

    #[test]
    fn split_2_test() {
        assert_eq!(
            Grid::from_str("#.##.#|#.#.##|......|.##.##|###...|#.##.#")
                .unwrap()
                .split(),
            vec![
                Grid::from_str("#.#.").unwrap(),
                Grid::from_str("###.").unwrap(),
                Grid::from_str(".###").unwrap(),
                Grid::from_str("...#").unwrap(),
                Grid::from_str("..#.").unwrap(),
                Grid::from_str("..##").unwrap(),
                Grid::from_str("###.").unwrap(),
                Grid::from_str("#.##").unwrap(),
                Grid::from_str("...#").unwrap(),
            ],
        )
    }

    #[test]
    fn from_subgrids_test() {
        assert_eq!(
            Grid::from_subgrids(vec![
                Grid::from_str("#.#.").unwrap(),
                Grid::from_str("###.").unwrap(),
                Grid::from_str(".###").unwrap(),
                Grid::from_str("...#").unwrap(),
                Grid::from_str("..#.").unwrap(),
                Grid::from_str("..##").unwrap(),
                Grid::from_str("###.").unwrap(),
                Grid::from_str("#.##").unwrap(),
                Grid::from_str("...#").unwrap(),
            ]).unwrap(),
            Grid::from_str("#.##.#|#.#.##|......|.##.##|###...|#.##.#")
                .unwrap(),
        )
    }

    #[test]
    fn enhance_test() {
        let rules: RuleSet = std::iter::once((
            Grid::from_str("#.#.").unwrap(),
            Grid::from_str(".##.##.##").unwrap(),
        )).collect();
        assert_eq!(
            Grid::from_str("#.#.").unwrap().enhance(&rules),
            Some(Grid::from_str(".##.##.##").unwrap())
        );
        assert_eq!(Grid::from_str(".#.#").unwrap().enhance(&rules), None);
    }

    #[test]
    fn iterate_test() {
        let input: Vec<Rule> = vec![
            Rule {
                before: Grid::from_str("../.#").unwrap(),
                after: Grid::from_str("##./#../...").unwrap(),
            },
            Rule {
                before: Grid::from_str(".#./..#/###").unwrap(),
                after: Grid::from_str("#..#/..../..../#..#").unwrap(),
            },
        ];
        let ruleset = make_ruleset(&input);
        let res = start().iterate(&ruleset).iterate(&ruleset).count();
        assert_eq!(res, 12);
    }
}
<commit_msg>2017 day 21 part 02<commit_after>extern crate itertools;

extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use structopt::StructOpt;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum GridBuildError {
    Unsquare,
    // ^ Trying to build grid from non-square number of elements
    BadSideLen,
    // ^ Side length not divisible by 2 or 3
}

impl std::fmt::Display for GridBuildError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        use GridBuildError::*;
        match *self {
            Unsquare => write!(f, "Unsquare"),
            BadSideLen => write!(f, "Bad Side Length"),
        }
    }
}

impl std::error::Error for GridBuildError {
    fn description(&self) -> &str {
        use GridBuildError::*;
        match *self {
            Unsquare => "Non-square number of elements",
            BadSideLen => "Side length not divisible by 2 or 3",
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Rule {
    before: Grid,
    after: Grid,
}

type RuleSet = std::collections::HashMap<Grid, Grid>;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Grid {
    side_len: usize,     // this shall always be divisible by 2 or 3
    contents: Vec<bool>, // this shall always have side_len * side_len rows
}

impl Grid {
    fn empty() -> Grid {
        Grid {
            side_len: 0,
            contents: Vec::new(),
        }
    }

    fn from_components(
        side_len: usize,
        contents: Vec<bool>,
    ) -> Result<Grid, GridBuildError> {
        if side_len * side_len != contents.len() {
            return Err(GridBuildError::Unsquare);
        }
        if side_len % 2 != 0 && side_len % 3 != 0 {
            return Err(GridBuildError::BadSideLen);
        }
        Ok(Grid {
            side_len: side_len,
            contents: contents,
        })
    }

    fn from_subgrids<T>(container: T) -> Result<Grid, GridBuildError>
    where
        T: IntoIterator<Item = Grid>,
        T::IntoIter: ExactSizeIterator,
    {
        // "sg" = "subgrid"
        let mut iter = container.into_iter().peekable();
        let sg_side_len = match iter.peek() {
            Some(sg) => sg.side_len,
            None => return Ok(Grid::empty()),
        };
        let side_len = ((iter.len() as f64).sqrt() as usize) * sg_side_len;
        let mut contents = vec![false; side_len * side_len];
        for (b, sg) in iter.enumerate() {
            for r in 0..sg_side_len {
                for c in 0..sg_side_len {
                    let src_row =
                        b / (side_len / sg_side_len) * sg_side_len + r;
                    let src_col =
                        b % (side_len / sg_side_len) * sg_side_len + c;
                    contents[src_row * side_len + src_col] =
                        sg.contents[r * sg_side_len + c];
                }
            }
        }
        Grid::from_components(side_len, contents)
    }

    fn from_bools<T>(container: T) -> Result<Grid, GridBuildError>
    where
        T: IntoIterator<Item = bool>,
        T::IntoIter: ExactSizeIterator,
    {
        let iter = container.into_iter();
        let side_len = (iter.len() as f64).sqrt() as usize;
        Grid::from_components(side_len, iter.collect())
    }

    fn split(&self) -> Vec<Grid> {
        // in this function, "sg" = "subgrid"
        let sg_side_len = if self.contents.len() % 4 == 0 { 2 } else { 3 };
        let mut grids = Vec::new();
        for b in 0..self.contents.len() / (sg_side_len * sg_side_len) {
            let mut sg_contents = vec![false; sg_side_len * sg_side_len];
            for r in 0..sg_side_len {
                for c in 0..sg_side_len {
                    let src_row =
                        b / (self.side_len / sg_side_len) * sg_side_len + r;
                    let src_col =
                        b % (self.side_len / sg_side_len) * sg_side_len + c;
                    sg_contents[r * sg_side_len + c] =
                        self.contents[src_row * self.side_len + src_col];
                }
            }
            grids.push(Grid {
                side_len: sg_side_len,
                contents: sg_contents,
            });
        }
        grids
    }

    fn enhance(&self, rules: &RuleSet) -> Option<Grid> {
        rules.get(self).cloned().map(|g| {
            Self::from_bools(g.contents).expect("Error enhancing grid")
        })
    }

    fn iterate(&self, rules: &RuleSet) -> Grid {
        Grid::from_subgrids(self.split().iter().map(|grid| {
            grid.enhance(rules)
                .expect(&format!("Rule not found: \n{}", grid))
        })).expect("Grid Iteration: Invalid subgrid produced")
    }

    fn count(&self) -> usize {
        self.contents.iter().filter(|b| **b).count()
    }

    fn rotate_ccw(&self) -> Grid {
        let mut contents = vec![false; self.contents.len()];
        for r in 0..self.side_len {
            for c in 0..self.side_len {
                let dst_row = self.side_len - c - 1;
                let dst_col = r;
                contents[dst_row * self.side_len + dst_col] =
                    self.contents[r * self.side_len + c];
            }
        }
        Grid::from_components(self.side_len, contents).expect("Error rotating")
    }

    fn flip_lr(&self) -> Grid {
        let mut contents = vec![false; self.contents.len()];
        for r in 0..self.side_len {
            for c in 0..self.side_len {
                contents[r * self.side_len + (self.side_len - c - 1)] =
                    self.contents[r * self.side_len + c];
            }
        }
        Grid::from_components(self.side_len, contents).expect("Error flipping")
    }
}

impl std::str::FromStr for Grid {
    type Err = GridBuildError;
    fn from_str(s: &str) -> Result<Grid, Self::Err> {
        let contents: Vec<_> = s.bytes()
            .filter_map(|b| match b {
                b'#' => Some(true),
                b'.' => Some(false),
                _ => None,
            })
            .collect();
        Self::from_bools(contents)
    }
}

impl std::fmt::Display for Grid {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        for (pos, val) in self.contents.iter().enumerate() {
            if pos != 0 && pos % self.side_len == 0 {
                write!(f, "\n")?
            }
            write!(f, "{}", if *val { '#' } else { '.' })?
        }
        Ok(())
    }
}

fn parse(input: &str) -> Vec<Rule> {
    use std::str::FromStr;
    input
        .lines()
        .map(|line| {
            let (before, after) = line.split_at(
                line.find("=>").expect(&format!("Invalid line: {}", line)),
            );
            Rule {
                before: Grid::from_str(before)
                    .expect(&format!("Could not parse grid from {}", before)),
                after: Grid::from_str(after)
                    .expect(&format!("Could not parse grid from {}", after)),
            }
        })
        .collect()
}

fn make_ruleset(rule_list: &[Rule]) -> RuleSet {
    let mut rule_set = std::collections::HashMap::new();
    for rule in rule_list {
        let mut new_rule = rule.before.clone();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.flip_lr();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
        new_rule = new_rule.rotate_ccw();
        rule_set.insert(new_rule.clone(), rule.after.clone());
    }
    rule_set
}

fn start() -> Grid {
    Grid {
        side_len: 3,
        contents: vec![
            false, true, false, false, false, true, true, true, true
        ],
    }
}

fn part1(rules: &RuleSet) -> usize {
    itertools::iterate(start(), |g| g.iterate(rules))
        .nth(5)
        .unwrap()
        .count()
}

fn part2(rules: &RuleSet) -> usize {
    itertools::iterate(start(), |g| g.iterate(rules))
        .nth(18)
        .unwrap()
        .count()
}

fn main() {
    let opt = Opt::from_args();
    let mut contents = String::new();
    if opt.input.to_str() == Some("-") {
        std::io::stdin()
            .read_to_string(&mut contents)
            .expect("could not read stdin");
    } else {
        let mut file = File::open(&opt.input)
            .expect(&format!("file {} not found", opt.input.display()));
        file.read_to_string(&mut contents)
            .expect(&format!("could not read file {}", opt.input.display()));
    }
    let rule_list = parse(&contents);
    let rules = make_ruleset(&rule_list);
    println!("Part 1: {}", part1(&rules));
    println!("Part 2: {}", part2(&rules));
}

#[derive(StructOpt, Debug)]
#[structopt(name = "day20", about = "Advent of code 2017 day 20")]
struct Opt {
    #[structopt(help = "Input file", parse(from_os_str))]
    input: PathBuf,
}

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

    #[test]
    fn rotate_ccw_test() {
        assert_eq!(
            Grid::from_str("#...##...").unwrap().rotate_ccw(),
            Grid::from_str(".#..#.#..").unwrap(),
        );
        assert_eq!(
            Grid::from_str("#.#.").unwrap().rotate_ccw(),
            Grid::from_str("..##").unwrap(),
        );
        assert_eq!(
            Grid::from_str("#...##...")
                .unwrap()
                .rotate_ccw()
                .rotate_ccw()
                .rotate_ccw()
                .rotate_ccw(),
            Grid::from_str("#...##...").unwrap()
        );
    }

    #[test]
    fn flip_lr_test() {
        assert_eq!(
            Grid::from_str("#...##...").unwrap().flip_lr(),
            Grid::from_str("..###....").unwrap(),
        );
        assert_eq!(
            Grid::from_str("#.#.").unwrap().flip_lr(),
            Grid::from_str(".#.#").unwrap(),
        );
        assert_eq!(
            Grid::from_str("#...##...").unwrap().flip_lr().flip_lr(),
            Grid::from_str("#...##...").unwrap(),
        );
    }

    #[test]
    fn split_2_test() {
        assert_eq!(
            Grid::from_str("#.##.#|#.#.##|......|.##.##|###...|#.##.#")
                .unwrap()
                .split(),
            vec![
                Grid::from_str("#.#.").unwrap(),
                Grid::from_str("###.").unwrap(),
                Grid::from_str(".###").unwrap(),
                Grid::from_str("...#").unwrap(),
                Grid::from_str("..#.").unwrap(),
                Grid::from_str("..##").unwrap(),
                Grid::from_str("###.").unwrap(),
                Grid::from_str("#.##").unwrap(),
                Grid::from_str("...#").unwrap(),
            ],
        )
    }

    #[test]
    fn from_subgrids_test() {
        assert_eq!(
            Grid::from_subgrids(vec![
                Grid::from_str("#.#.").unwrap(),
                Grid::from_str("###.").unwrap(),
                Grid::from_str(".###").unwrap(),
                Grid::from_str("...#").unwrap(),
                Grid::from_str("..#.").unwrap(),
                Grid::from_str("..##").unwrap(),
                Grid::from_str("###.").unwrap(),
                Grid::from_str("#.##").unwrap(),
                Grid::from_str("...#").unwrap(),
            ]).unwrap(),
            Grid::from_str("#.##.#|#.#.##|......|.##.##|###...|#.##.#")
                .unwrap(),
        )
    }

    #[test]
    fn enhance_test() {
        let rules: RuleSet = std::iter::once((
            Grid::from_str("#.#.").unwrap(),
            Grid::from_str(".##.##.##").unwrap(),
        )).collect();
        assert_eq!(
            Grid::from_str("#.#.").unwrap().enhance(&rules),
            Some(Grid::from_str(".##.##.##").unwrap())
        );
        assert_eq!(Grid::from_str(".#.#").unwrap().enhance(&rules), None);
    }

    #[test]
    fn iterate_test() {
        let input: Vec<Rule> = vec![
            Rule {
                before: Grid::from_str("../.#").unwrap(),
                after: Grid::from_str("##./#../...").unwrap(),
            },
            Rule {
                before: Grid::from_str(".#./..#/###").unwrap(),
                after: Grid::from_str("#..#/..../..../#..#").unwrap(),
            },
        ];
        let ruleset = make_ruleset(&input);
        let res = start().iterate(&ruleset).iterate(&ruleset).count();
        assert_eq!(res, 12);
    }
}
<|endoftext|>


<commit_before>extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use std::collections::BTreeSet;
use structopt::StructOpt;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
struct Position(isize, isize);

impl Position {
    fn go(&self, dir: Direction) -> Position {
        use Direction::*;
        match dir {
            Up => Position(self.0 + 1, self.1),
            Right => Position(self.0, self.1 + 1),
            Down => Position(self.0 - 1, self.1),
            Left => Position(self.0, self.1 - 1),
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Direction {
    Up,
    Right,
    Down,
    Left,
}

impl Direction {
    fn turn_left(self) -> Direction {
        use Direction::*;
        match self {
            Up => Left,
            Right => Up,
            Down => Right,
            Left => Down,
        }
    }
    fn turn_right(self) -> Direction {
        use Direction::*;
        match self {
            Up => Right,
            Right => Down,
            Down => Left,
            Left => Up,
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Virus {
    loc: Position,
    facing: Direction,
}

impl Virus {
    /// Have virus act. Returns true if virus infects a new cell
    fn act(&mut self, infected: &mut Board) -> bool {
        if infected.contains(&self.loc) {
            self.facing = self.facing.turn_right();
            infected.remove(&self.loc);
            self.loc = self.loc.go(self.facing);
            false
        } else {
            self.facing = self.facing.turn_left();
            infected.insert(self.loc);
            self.loc = self.loc.go(self.facing);
            true
        }
    }
}

type Board = BTreeSet<Position>; // set of infected nodes

fn parse(input: &str) -> (Virus, Board) {
    let bools: Vec<bool> = input
        .bytes()
        .filter_map(|b| match b {
            b'#' => Some(true),
            b'.' => Some(false),
            _ => None,
        })
        .collect();
    let side_len = (bools.len() as f64).sqrt() as usize;
    if side_len * side_len != bools.len() {
        panic!("unsquare grid");
    }
    if side_len % 2 == 0 {
        panic!("center undefined");
    }
    let offset = (side_len / 2) as isize;
    let mut board = BTreeSet::new();
    for idx in bools.into_iter().enumerate().filter_map(|(idx, b)| {
        if b {
            Some(idx)
        } else {
            None
        }
    }) {
        let r = offset as isize - (idx / side_len) as isize;
        let c = (idx % side_len) as isize - offset;
        board.insert(Position(r, c));
    }
    (
        Virus {
            loc: Position(0, 0),
            facing: Direction::Up,
        },
        board,
    )
}

fn part1(mut virus: Virus, mut board: Board) -> usize {
    let mut count = 0;
    for _ in 0..10_000 {
        if virus.act(&mut board) {
            count += 1;
        }
    }
    count
}

fn main() {
    let opt = Opt::from_args();
    let mut contents = String::new();
    if opt.input.to_str() == Some("-") {
        std::io::stdin()
            .read_to_string(&mut contents)
            .expect("could not read stdin");
    } else {
        let mut file = File::open(&opt.input)
            .expect(&format!("file {} not found", opt.input.display()));
        file.read_to_string(&mut contents)
            .expect(&format!("could not read file {}", opt.input.display()));
    }
    let (virus, board) = parse(&contents);
    println!("Part 1: {}", part1(virus, board));
}

#[derive(StructOpt, Debug)]
#[structopt(name = "day22", about = "Advent of code 2017 day 22")]
struct Opt {
    #[structopt(help = "Input file", parse(from_os_str))]
    input: PathBuf,
}

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

    static INPUT: &str = concat!("..#\n", "#..\n", "...\n");

    #[test]
    fn parse_test() {
        assert_eq!(
            parse(INPUT),
            (
                Virus {
                    loc: Position(0, 0),
                    facing: Direction::Up,
                },
                [Position(1, 1), Position(0, -1),][..]
                    .iter()
                    .cloned()
                    .collect()
            )
        );
    }

    #[test]
    fn act_test() {
        let (mut virus, mut board) = parse(INPUT);
        assert_eq!(virus.act(&mut board), true);
        assert_eq!(
            virus,
            Virus {
                loc: Position(0, -1),
                facing: Direction::Left,
            }
        );
        assert_eq!(
            board,
            vec![Position(0, -1), Position(0, 0), Position(1, 1)]
                .into_iter()
                .collect()
        );
    }

    #[test]
    fn part1_test() {
        let (virus, board) = parse(INPUT);
        assert_eq!(part1(virus, board), 5587);
    }
}
<commit_msg>2017 day 22 prep part 02<commit_after>extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use std::collections::BTreeMap;
use std::default::Default;
use structopt::StructOpt;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
struct Position(isize, isize);

impl Position {
    fn go(&self, dir: Direction) -> Position {
        use Direction::*;
        match dir {
            Up => Position(self.0 + 1, self.1),
            Right => Position(self.0, self.1 + 1),
            Down => Position(self.0 - 1, self.1),
            Left => Position(self.0, self.1 - 1),
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum Direction {
    Up,
    Right,
    Down,
    Left,
}

impl Direction {
    fn turn_left(self) -> Direction {
        use Direction::*;
        match self {
            Up => Left,
            Right => Up,
            Down => Right,
            Left => Down,
        }
    }
    fn turn_right(self) -> Direction {
        use Direction::*;
        match self {
            Up => Right,
            Right => Down,
            Down => Left,
            Left => Up,
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum NodeState {
    Clean,
    Weakened,
    Infected,
    Flagged,
}

impl NodeState {
    fn progress(&mut self) {
        use NodeState::*;
        *self = match *self {
            Clean => Weakened,
            Weakened => Infected,
            Infected => Flagged,
            Flagged => Clean,
        };
    }
    fn toggle(&mut self) {
        use NodeState::*;
        *self = match *self {
            Clean => Infected,
            Weakened => panic!("Cannot toggle weakened state"),
            Infected => Clean,
            Flagged => panic!("Cannot toggle flagged state"),
        };
    }
}

impl Default for NodeState {
    fn default() -> Self {
        NodeState::Clean
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct Virus {
    loc: Position,
    facing: Direction,
}

impl Virus {
    /// Have virus act as in part 1. Returns true if virus infects a new cell
    fn act1(&mut self, infected: &mut Board) -> bool {
        use NodeState::*;
        let loc = self.loc;
        let state = infected.get(&loc).cloned().unwrap_or_default();
        // turn
        match state {
            Clean => {
                self.facing = self.facing.turn_left();
            }
            Infected => {
                self.facing = self.facing.turn_right();
            }
            _ => panic!("Invalid state for part 1"),
        }
        // infect
        infected.entry(loc).or_insert(Clean).toggle();
        if infected[&loc] == Clean {
            infected.remove(&loc);
        }
        // move
        self.loc = loc.go(self.facing);
        state != Infected
            && infected.get(&loc).cloned().unwrap_or_default() == Infected
    }
}

type Board = BTreeMap<Position, NodeState>; // set of infected nodes

fn parse(input: &str) -> (Virus, Board) {
    let bools: Vec<bool> = input
        .bytes()
        .filter_map(|b| match b {
            b'#' => Some(true),
            b'.' => Some(false),
            _ => None,
        })
        .collect();
    let side_len = (bools.len() as f64).sqrt() as usize;
    if side_len * side_len != bools.len() {
        panic!("unsquare grid");
    }
    if side_len % 2 == 0 {
        panic!("center undefined");
    }
    let offset = (side_len / 2) as isize;
    let mut board = BTreeMap::new();
    for idx in bools.into_iter().enumerate().filter_map(|(idx, b)| {
        if b {
            Some(idx)
        } else {
            None
        }
    }) {
        let r = offset as isize - (idx / side_len) as isize;
        let c = (idx % side_len) as isize - offset;
        board.insert(Position(r, c), NodeState::Infected);
    }
    (
        Virus {
            loc: Position(0, 0),
            facing: Direction::Up,
        },
        board,
    )
}

fn part1(mut virus: Virus, mut board: Board) -> usize {
    let mut count = 0;
    for _ in 0..10_000 {
        if virus.act1(&mut board) {
            count += 1;
        }
    }
    count
}

fn main() {
    let opt = Opt::from_args();
    let mut contents = String::new();
    if opt.input.to_str() == Some("-") {
        std::io::stdin()
            .read_to_string(&mut contents)
            .expect("could not read stdin");
    } else {
        let mut file = File::open(&opt.input)
            .expect(&format!("file {} not found", opt.input.display()));
        file.read_to_string(&mut contents)
            .expect(&format!("could not read file {}", opt.input.display()));
    }
    let (virus, board) = parse(&contents);
    println!("Part 1: {}", part1(virus, board));
}

#[derive(StructOpt, Debug)]
#[structopt(name = "day22", about = "Advent of code 2017 day 22")]
struct Opt {
    #[structopt(help = "Input file", parse(from_os_str))]
    input: PathBuf,
}

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

    static INPUT: &str = concat!("..#\n", "#..\n", "...\n");

    #[test]
    fn parse_test() {
        use NodeState::Infected;
        assert_eq!(
            parse(INPUT),
            (
                Virus {
                    loc: Position(0, 0),
                    facing: Direction::Up,
                },
                vec![(Position(1, 1), Infected), (Position(0, -1), Infected)]
                    .into_iter()
                    .collect()
            )
        );
    }

    #[test]
    fn act_test() {
        let (mut virus, mut board) = parse(INPUT);
        assert_eq!(virus.act1(&mut board), true);
        assert_eq!(
            virus,
            Virus {
                loc: Position(0, -1),
                facing: Direction::Left,
            }
        );
        assert_eq!(board, parse(concat!("..#\n", "##.\n", "...\n")).1);
    }

    #[test]
    fn part1_test() {
        let (virus, board) = parse(INPUT);
        assert_eq!(part1(virus, board), 5587);
    }
}
<|endoftext|>