<commit_before>use field::PuyoPlainField;
use frame;
use rensa_result::RensaResult;

#[cfg(all(target_feature = "avx2", target_feature = "bmi2"))]
use field::BitField;

fn run_plainfield_test(mut pf: PuyoPlainField, expected_result: &RensaResult) {
    let actual_result = pf.simulate();

    assert_eq!(actual_result.chain, expected_result.chain);
    assert_eq!(actual_result.score, expected_result.score);
    // Check only frames is not zero.
    if expected_result.frame > 0 {
        assert_eq!(actual_result.frame, expected_result.frame);
    }
    assert_eq!(actual_result.quick, expected_result.quick);
}

#[cfg(all(target_feature = "avx2", target_feature = "bmi2"))]
fn run_bitfield_test(mut bf: BitField, expected_result: &RensaResult) {
    let actual_result = bf.simulate();

    assert_eq!(actual_result.chain, expected_result.chain);
    assert_eq!(actual_result.score, expected_result.score);
    // Check only frames is not zero.
    if expected_result.frame > 0 {
        assert_eq!(actual_result.frame, expected_result.frame);
    }
    assert_eq!(actual_result.quick, expected_result.quick);
}

#[cfg(all(target_feature = "avx2", target_feature = "bmi2"))]
fn run_test(original: PuyoPlainField, expected_result: RensaResult) {
    run_plainfield_test(original.clone(), &expected_result);
    run_bitfield_test(BitField::from_plain_field(original), &expected_result);
}

#[cfg(not(all(target_feature = "avx2", target_feature = "bmi2")))]
fn run_test(original: PuyoPlainField, expected_result: RensaResult) {
    run_plainfield_test(original.clone(), &expected_result);
}

#[test]
fn test_simulate_1rensa_quick() {
    let pf = PuyoPlainField::from_str("..RRRR");

    let expected_result = RensaResult {
        chain: 1,
        score: 40,
        frame: frame::FRAMES_VANISH_ANIMATION,
        quick: true,
    };

    run_test(pf, expected_result);
}

#[test]
fn test_simulate_1rensa_nonquick_case1() {
    let pf = PuyoPlainField::from_str(concat!(
        ".....Y",
        "..RRRR",
    ));

    let expected_result = RensaResult {
        chain: 1,
        score: 40,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[1] + frame::FRAMES_GROUNDING,
        quick: false,
    };

    run_test(pf, expected_result);
}

#[test]
fn test_simulate_1rensa_nonquick_case2() {
    let pf = PuyoPlainField::from_str(concat!(
        ".....Y",
        ".....R",
        "...RRR",
    ));

    let expected_result = RensaResult {
        chain: 1,
        score: 40,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[2] + frame::FRAMES_GROUNDING,
        quick: false,
    };

    run_test(pf, expected_result);
}

#[test]
fn test_simulate_1rensa_nonquick_case3() {
    let pf = PuyoPlainField::from_str(concat!(
        ".....Y",
        "....YR",
        "...RRR",
    ));

    let expected_result = RensaResult {
        chain: 1,
        score: 40,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[2] + frame::FRAMES_GROUNDING,
        quick: false,
    };

    run_test(pf, expected_result);
}

#[test]
fn test_simulate_2rensa_quick() {
    let pf = PuyoPlainField::from_str(concat!(
        "Y.....",
        "RYY...",
        "RRRY..",
    ));

    let expected_result = RensaResult {
        chain: 2,
        score: 40 + 40 * 8,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[2] + frame::FRAMES_GROUNDING +
            frame::FRAMES_VANISH_ANIMATION,
        quick: true,
    };

    run_test(pf, expected_result);
}

#[test]
fn test_simulate_2rensa_nonquick_case1() {
    let pf = PuyoPlainField::from_str(concat!(
        "YB....",
        "RYY...",
        "RRRY..",
    ));

    let expected_result = RensaResult {
        chain: 2,
        score: 40 + 40 * 8,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[2] + frame::FRAMES_GROUNDING +
            frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[1] + frame::FRAMES_GROUNDING,
        quick: false,
    };

    run_test(pf, expected_result);
}

#[test]
fn test_simulate_2rensa_nonquick_case2() {
    let pf = PuyoPlainField::from_str(concat!(
        "..B...",
        "..BBYB",
        "RRRRBB"));

    let expected_result = RensaResult {
        chain: 2,
        score: 700,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[1] + frame::FRAMES_GROUNDING +
            frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[1] + frame::FRAMES_GROUNDING,
        quick: false
    };

    run_test(pf, expected_result);
}

#[test]
fn test_simulate_19rensa_case1() {
    let pf = PuyoPlainField::from_str(concat!(
        ".G.BRG",
        "GBRRYR",
        "RRYYBY",
        "RGYRBR",
        "YGYRBY",
        "YGBGYR",
        "GRBGYR",
        "BRBYBY",
        "RYYBYY",
        "BRBYBR",
        "BGBYRR",
        "YGBGBG",
        "RBGBGG"));

    let expected_result = RensaResult {
        chain: 19,
        score: 175080,
        frame: 0,
        quick: true,
    };

    run_test(pf, expected_result);
}

#[test]
fn test_simulate() {
    run_test(PuyoPlainField::from_str(".B.GRBBGRRYRRRYYGYRBYRGRYBYRGYYBGBYRBRGBYRGRGYGYRYYGYYGRGYGRGBGYRRYBGBGBRGBGBB"),
             RensaResult::new(19, 175080, 0, true));
    run_test(PuyoPlainField::from_str("B..RYGGYGYGBGRRRBRGBRYBGRRGGYGYYGYRRYGRBRBRBBGYGRGGYRRRBGRGRYBYRBBRRYGGBRBBYRY"),
             RensaResult::new(19, 175080, 0, true));
    run_test(PuyoPlainField::from_str("...BB..B.RBB.RBRBO.RBGRB.GRGRB.GRYRB.YGYGR.YGYGR.BYBYG.BYBYGBOBOYGRRRROYBBBOBB"),
             RensaResult::new(2, 38540, 0, true));
    run_test(PuyoPlainField::from_str(".B.BB..R.RBB.GBRBO.GBGRB.YRGRB.YRYRB.YGYGR.BGYGRGRGBGRGGYBYGYGBOBYYRRROBBBBOBB"),
             RensaResult::new(3, 43260, 0, true));
    run_test(PuyoPlainField::from_str("...BB..R.RBB.GBRBOGGBGRBRYRGRBRYRYRBRYGYGRRBGYGRORGBGRGGYBYGYGBOBYYRRROBBBBOBB"),
             RensaResult::new(4, 50140, 0, true));
    run_test(PuyoPlainField::from_str("GRBBB.BGYRBBYYYRBOOGBGRBBYRGRBBYRGRBBYGYGROBGYGRGRGBGRGGYBYYYOBOBYYRRROBBBBOBB"),
             RensaResult::new(5, 68700, 0, true));
    run_test(PuyoPlainField::from_str("RRRROOOOROROROROOROOROOORORORRROOOORROROOOOORRORROOOORRROOOROOOORORRROROOOOORO"),
             RensaResult::new(4, 4840, 0, true));
    run_test(PuyoPlainField::from_str("BRBBRRBRRRBRRBRBRBRBRBRBRBRBRBBRBRBRRRBBRRBBRRBBRBRBRBBRBRBRBBRBRRRRBRBBRBBRRB"),
             RensaResult::new(9, 49950, 0, true));
    run_test(PuyoPlainField::from_str("RRRRRYBRRYOORRYOYRBYRRROBRYOYYBYBYOBRBRBBORRORRROOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"),
             RensaResult::new(9, 32760, 0, true));
    run_test(PuyoPlainField::from_str("YYGBRGRYYBBBYYOYGGRGORGBRBORRGRYOYYYYYOBRGRBGRGGBBYRRYGGYBBBGRRYRYRGYRYYGRRBBB"),
             RensaResult::new(18, 155980, 0, true));
    run_test(PuyoPlainField::from_str("RRR.RRORRROROORORRROOROORORORRORORORRORORORROROROORROORROORRROROROORORORORRORR"),
             RensaResult::new(11, 47080, 0, true));
    run_test(PuyoPlainField::from_str("......RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"),
             RensaResult::new(1, 7200, 0, true));
}
<commit_msg>:recycle: Refactoring: Pass &str instead of PuyoPlainField in simulation_test<commit_after>use field::PuyoPlainField;
use frame;
use rensa_result::RensaResult;

#[cfg(all(target_feature = "avx2", target_feature = "bmi2"))]
use field::BitField;

fn run_plainfield_test(mut pf: PuyoPlainField, expected_result: &RensaResult) {
    let actual_result = pf.simulate();

    assert_eq!(actual_result.chain, expected_result.chain);
    assert_eq!(actual_result.score, expected_result.score);
    // Check only frames is not zero.
    if expected_result.frame > 0 {
        assert_eq!(actual_result.frame, expected_result.frame);
    }
    assert_eq!(actual_result.quick, expected_result.quick);
}

#[cfg(all(target_feature = "avx2", target_feature = "bmi2"))]
fn run_bitfield_test(mut bf: BitField, expected_result: &RensaResult) {
    let actual_result = bf.simulate();

    assert_eq!(actual_result.chain, expected_result.chain);
    assert_eq!(actual_result.score, expected_result.score);
    // Check only frames is not zero.
    if expected_result.frame > 0 {
        assert_eq!(actual_result.frame, expected_result.frame);
    }
    assert_eq!(actual_result.quick, expected_result.quick);
}

#[cfg(all(target_feature = "avx2", target_feature = "bmi2"))]
fn run_test(src: &str, expected_result: RensaResult) {
    run_plainfield_test(PuyoPlainField::from_str(src), &expected_result);
    run_bitfield_test(BitField::from_str(src), &expected_result);
}

#[cfg(not(all(target_feature = "avx2", target_feature = "bmi2")))]
fn run_test(src: &str, expected_result: RensaResult) {
    run_plainfield_test(PuyoPlainField::from_str(src), &expected_result);
}

#[test]
fn test_simulate_1rensa_quick() {
    let src = "..RRRR";

    let expected_result = RensaResult {
        chain: 1,
        score: 40,
        frame: frame::FRAMES_VANISH_ANIMATION,
        quick: true,
    };

    run_test(src, expected_result);
}

#[test]
fn test_simulate_1rensa_nonquick_case1() {
    let src = concat!(
        ".....Y",
        "..RRRR");

    let expected_result = RensaResult {
        chain: 1,
        score: 40,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[1] + frame::FRAMES_GROUNDING,
        quick: false,
    };

    run_test(src, expected_result);
}

#[test]
fn test_simulate_1rensa_nonquick_case2() {
    let src = concat!(
        ".....Y",
        ".....R",
        "...RRR");

    let expected_result = RensaResult {
        chain: 1,
        score: 40,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[2] + frame::FRAMES_GROUNDING,
        quick: false,
    };

    run_test(src, expected_result);
}

#[test]
fn test_simulate_1rensa_nonquick_case3() {
    let src = concat!(
        ".....Y",
        "....YR",
        "...RRR");

    let expected_result = RensaResult {
        chain: 1,
        score: 40,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[2] + frame::FRAMES_GROUNDING,
        quick: false,
    };

    run_test(src, expected_result);
}

#[test]
fn test_simulate_2rensa_quick() {
    let src = concat!(
        "Y.....",
        "RYY...",
        "RRRY..");

    let expected_result = RensaResult {
        chain: 2,
        score: 40 + 40 * 8,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[2] + frame::FRAMES_GROUNDING +
            frame::FRAMES_VANISH_ANIMATION,
        quick: true,
    };

    run_test(src, expected_result);
}

#[test]
fn test_simulate_2rensa_nonquick_case1() {
    let src = concat!(
        "YB....",
        "RYY...",
        "RRRY..");

    let expected_result = RensaResult {
        chain: 2,
        score: 40 + 40 * 8,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[2] + frame::FRAMES_GROUNDING +
            frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[1] + frame::FRAMES_GROUNDING,
        quick: false,
    };

    run_test(src, expected_result);
}

#[test]
fn test_simulate_2rensa_nonquick_case2() {
    let src = concat!(
        "..B...",
        "..BBYB",
        "RRRRBB");

    let expected_result = RensaResult {
        chain: 2,
        score: 700,
        frame: frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[1] + frame::FRAMES_GROUNDING +
            frame::FRAMES_VANISH_ANIMATION + frame::FRAMES_TO_DROP_FAST[1] + frame::FRAMES_GROUNDING,
        quick: false
    };

    run_test(src, expected_result);
}

#[test]
fn test_simulate_19rensa_case1() {
    let src = concat!(
        ".G.BRG",
        "GBRRYR",
        "RRYYBY",
        "RGYRBR",
        "YGYRBY",
        "YGBGYR",
        "GRBGYR",
        "BRBYBY",
        "RYYBYY",
        "BRBYBR",
        "BGBYRR",
        "YGBGBG",
        "RBGBGG");

    let expected_result = RensaResult {
        chain: 19,
        score: 175080,
        frame: 0,
        quick: true,
    };

    run_test(src, expected_result);
}

#[test]
fn test_simulate() {
    run_test(".B.GRBBGRRYRRRYYGYRBYRGRYBYRGYYBGBYRBRGBYRGRGYGYRYYGYYGRGYGRGBGYRRYBGBGBRGBGBB",
             RensaResult::new(19, 175080, 0, true));
    run_test("B..RYGGYGYGBGRRRBRGBRYBGRRGGYGYYGYRRYGRBRBRBBGYGRGGYRRRBGRGRYBYRBBRRYGGBRBBYRY",
             RensaResult::new(19, 175080, 0, true));
    run_test("...BB..B.RBB.RBRBO.RBGRB.GRGRB.GRYRB.YGYGR.YGYGR.BYBYG.BYBYGBOBOYGRRRROYBBBOBB",
             RensaResult::new(2, 38540, 0, true));
    run_test(".B.BB..R.RBB.GBRBO.GBGRB.YRGRB.YRYRB.YGYGR.BGYGRGRGBGRGGYBYGYGBOBYYRRROBBBBOBB",
             RensaResult::new(3, 43260, 0, true));
    run_test("...BB..R.RBB.GBRBOGGBGRBRYRGRBRYRYRBRYGYGRRBGYGRORGBGRGGYBYGYGBOBYYRRROBBBBOBB",
             RensaResult::new(4, 50140, 0, true));
    run_test("GRBBB.BGYRBBYYYRBOOGBGRBBYRGRBBYRGRBBYGYGROBGYGRGRGBGRGGYBYYYOBOBYYRRROBBBBOBB",
             RensaResult::new(5, 68700, 0, true));
    run_test("RRRROOOOROROROROOROOROOORORORRROOOORROROOOOORRORROOOORRROOOROOOORORRROROOOOORO",
             RensaResult::new(4, 4840, 0, true));
    run_test("BRBBRRBRRRBRRBRBRBRBRBRBRBRBRBBRBRBRRRBBRRBBRRBBRBRBRBBRBRBRBBRBRRRRBRBBRBBRRB",
             RensaResult::new(9, 49950, 0, true));
    run_test("RRRRRYBRRYOORRYOYRBYRRROBRYOYYBYBYOBRBRBBORRORRROOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
             RensaResult::new(9, 32760, 0, true));
    run_test("YYGBRGRYYBBBYYOYGGRGORGBRBORRGRYOYYYYYOBRGRBGRGGBBYRRYGGYBBBGRRYRYRGYRYYGRRBBB",
             RensaResult::new(18, 155980, 0, true));
    run_test("RRR.RRORRROROORORRROOROORORORRORORORRORORORROROROORROORROORRROROROORORORORRORR",
             RensaResult::new(11, 47080, 0, true));
    run_test("......RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR",
             RensaResult::new(1, 7200, 0, true));
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::io::{Read, Write, Result};

// use data::SideData;

bitflags! {
    flags PacketFlags: u32 {
        const KEY     = 0b0001,
        const CORRUPT = 0b0010,
        const NONE    = 0,
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Packet {
    data : Vec<u8>,
    pts : Option<i64>,
    dts : Option<i64>,
    pos : Option<i64>,
    stream_index : isize,

    // side_data : SideData;

    flags : PacketFlags,
}

impl Packet {
    pub fn with_capacity(capacity: usize) -> Self {
        Packet {
            data : Vec::with_capacity(capacity),
            pts : None,
            dts : None,
            pos : None,
            stream_index : -1,
            flags : NONE
        }
    }

    pub fn new() -> Self {
        Self::with_capacity(0)
    }
}

pub trait ReadPacket: Read {
    fn get_packet(&mut self, len: usize) -> Result<Packet> {
        let mut pkt = Packet::with_capacity(len);
        unsafe {
            pkt.data.set_len(len);
            try!(self.read(pkt.data.as_mut_slice()));
        }
        Ok(pkt)
    }
}

pub trait WritePacket: Write {
    fn put_packet(&mut self, pkt: Packet) -> Result<()> {
        self.write_all(pkt.data.as_slice())
    }
}

impl<R: Read + ?Sized> ReadPacket for R {}
impl<W: Write + ?Sized> WritePacket for W {}

#[cfg(test)]
mod test {
    use std::io::Cursor;
    use super::*;

    #[test]
    fn read_packet() {
        let mut buf = Cursor::new(vec![0; 1024]);

        match buf.get_packet(1024) {
            Ok(pkt) => assert!(pkt.data[0] == 0),
            _ => assert!(false)
        }
    }

    #[test]
    fn write_packet() {
        let size = 1024;
        let mut buf = Cursor::new(Vec::with_capacity(size));

        let mut pkt = Packet::with_capacity(size);

        for i in 0..size {
            pkt.data.push(i as u8);
        }

        buf.put_packet(pkt).unwrap();

        let vec = buf.into_inner();

        for i in 0..size {
            println!("{}", vec[i]);
            assert!(vec[i] == i as u8);
        }
    }
}
<commit_msg>packet: drop bitflags and make it accessible<commit_after>#![allow(dead_code)]

use std::io::{Read, Write, Result};

// use data::SideData;

#[derive(Debug, Clone, PartialEq)]
pub struct Packet {
    pub data : Vec<u8>,
    pub pts : Option<i64>,
    pub dts : Option<i64>,
    pub pos : Option<i64>,
    pub stream_index : isize,

    // side_data : SideData;

    pub is_key: bool,
    pub is_corrupted: bool,
}

impl Packet {
    pub fn with_capacity(capacity: usize) -> Self {
        Packet {
            data : Vec::with_capacity(capacity),
            pts : None,
            dts : None,
            pos : None,
            stream_index : -1,
            is_key: false,
            is_corrupted: false,
        }
    }

    pub fn new() -> Self {
        Self::with_capacity(0)
    }
}

pub trait ReadPacket: Read {
    fn get_packet(&mut self, len: usize) -> Result<Packet> {
        let mut pkt = Packet::with_capacity(len);
        unsafe {
            pkt.data.set_len(len);
            try!(self.read(pkt.data.as_mut_slice()));
        }
        Ok(pkt)
    }
}

pub trait WritePacket: Write {
    fn put_packet(&mut self, pkt: Packet) -> Result<()> {
        self.write_all(pkt.data.as_slice())
    }
}

impl<R: Read + ?Sized> ReadPacket for R {}
impl<W: Write + ?Sized> WritePacket for W {}

#[cfg(test)]
mod test {
    use std::io::Cursor;
    use super::*;

    #[test]
    fn read_packet() {
        let mut buf = Cursor::new(vec![0; 1024]);

        match buf.get_packet(1024) {
            Ok(pkt) => assert!(pkt.data[0] == 0),
            _ => assert!(false)
        }
    }

    #[test]
    fn write_packet() {
        let size = 1024;
        let mut buf = Cursor::new(Vec::with_capacity(size));

        let mut pkt = Packet::with_capacity(size);

        for i in 0..size {
            pkt.data.push(i as u8);
        }

        buf.put_packet(pkt).unwrap();

        let vec = buf.into_inner();

        for i in 0..size {
            println!("{}", vec[i]);
            assert!(vec[i] == i as u8);
        }
    }
}
<|endoftext|>


<commit_before>#[cfg(not(feature = "sdl_renderer"))]
pub mod renderer {
    pub mod glium_sdl2;

    use px8;
    use gfx::{Scale};

    use sdl2::video::gl_attr::GLAttr;
    use sdl2::VideoSubsystem;

    use glium;
    use glium::{DrawError, DrawParameters, IndexBuffer, Program, VertexBuffer, Surface};
    use glium::index::PrimitiveType;
    use glium::program::ProgramChooserCreationError;
    use glium::{Api, GliumCreationError, SwapBuffersError, Version};
    use glium::backend::Facade;
    use glium::texture::{ClientFormat, MipmapsOption, PixelValue, TextureCreationError, UncompressedFloatFormat};
    use glium::texture::pixel_buffer::PixelBuffer;
    use glium::texture::texture2d::Texture2d;

    use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter};
    use nalgebra::{Diagonal, Matrix4, Vector4};

    use self::glium_sdl2::{Display, DisplayBuild, GliumSdl2Error};

    #[derive(Clone, Debug)]
    pub enum RendererError {
        Sdl(String),
        Renderer(String),
        Other(String),
    }

    pub type RendererResult<T> = Result<T, RendererError>;

    impl From<DrawError> for RendererError {
        fn from(e: DrawError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<TextureCreationError> for RendererError {
        fn from(e: TextureCreationError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<glium::vertex::BufferCreationError> for RendererError {
        fn from(e: glium::vertex::BufferCreationError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<glium::index::BufferCreationError> for RendererError {
        fn from(e: glium::index::BufferCreationError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<ProgramChooserCreationError> for RendererError {
        fn from(e: ProgramChooserCreationError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<GliumCreationError<GliumSdl2Error>> for RendererError {
        fn from(e: GliumCreationError<GliumSdl2Error>) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<SwapBuffersError> for RendererError {
        fn from(e: SwapBuffersError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    unsafe impl PixelValue for px8::Color {
        fn get_format() -> ClientFormat {
            ClientFormat::U8
        }
    }

    type Texture = Texture2d;

    #[derive(Copy, Clone)]
    pub struct Vertex {
        position: [f32; 2],
        tex_coords: [f32; 2],
    }

    implement_vertex!(Vertex, position, tex_coords);

    pub struct Renderer {
        vertex_buffer: VertexBuffer<Vertex>,
        index_buffer: IndexBuffer<u16>,
        pixel_buffer: PixelBuffer<px8::Color>,
        program: Program,
        texture: Texture,
        matrix: Matrix4<f32>,
        display: Display,
    }

    const TEXTURE_WIDTH: u32 = 256;
    const TEXTURE_HEIGHT: u32 = 256;
    const TEX_OFFSET_X: f32 = px8::SCREEN_WIDTH as f32 / TEXTURE_WIDTH as f32;
    const TEX_OFFSET_Y: f32 = px8::SCREEN_HEIGHT as f32 / TEXTURE_HEIGHT as f32;

    const ASPECT_RATIO: f32 = px8::SCREEN_WIDTH as f32 / px8::SCREEN_HEIGHT as f32;

    fn aspect_ratio_correction(width: u32, height: u32) -> (f32, f32) {
        let fb_aspect_ratio = width as f32 / height as f32;
        let scale = ASPECT_RATIO / fb_aspect_ratio;
        if fb_aspect_ratio >= ASPECT_RATIO {
            (scale, 1.0)
        } else {
            (1.0, 1.0 / scale)
        }
    }

    impl Renderer {

        pub fn new(sdl_video: VideoSubsystem, fullscreen: bool, scale: Scale) -> RendererResult<Renderer> {
            let display;

            info!("SDL2 Video with opengl [glium]");

            configure_gl_attr(&mut sdl_video.gl_attr());

            if fullscreen {
                info!("SDL2 window fullscreen");

                display = try!(sdl_video.window("PX8",
                                                (px8::SCREEN_WIDTH * scale.factor()) as u32,
                                                (px8::SCREEN_HEIGHT * scale.factor()) as u32)
                    .resizable()
                    .fullscreen()
                    .position_centered()
                    .build_glium());
            } else {
                info!("SDL2 window");

                display = try!(sdl_video.window("PX8",
                                                (px8::SCREEN_WIDTH * scale.factor()) as u32,
                                                (px8::SCREEN_HEIGHT * scale.factor()) as u32)
                    .resizable()
                    .position_centered()
                    .build_glium());
            }

            info!("Init Renderer with GLIUM");

            let vertexes = [
                Vertex {
                    position: [-1.0, -1.0],
                    tex_coords: [0.0, TEX_OFFSET_Y],
                },
                Vertex {
                    position: [-1.0, 1.0],
                    tex_coords: [0.0, 0.0],
                },
                Vertex {
                    position: [1.0, 1.0],
                    tex_coords: [TEX_OFFSET_X, 0.0],
                },
                Vertex {
                    position: [1.0, -1.0],
                    tex_coords: [TEX_OFFSET_X, TEX_OFFSET_Y],
                }
            ];

            info!("Creating VertexBuffer");

            let vertex_buffer = try!(VertexBuffer::immutable(&display, &vertexes));

            info!("Creating IndexBuffer");

            let index_buffer =
            try!(IndexBuffer::immutable(&display, PrimitiveType::TriangleStrip, &[1u16, 2, 0, 3]));

            info!("Compiling shader");

            let program = try!(program!(
              &display,
              140 => {
                vertex: include_str!("shader/vert_140.glsl"),
                fragment: include_str!("shader/frag_140.glsl"),
                outputs_srgb: true
              },
              110 => {
                vertex: include_str!("shader/vert_110.glsl"),
                fragment: include_str!("shader/frag_110.glsl"),
                outputs_srgb: true
              }
            ));

            info!("Creating PixelBuffer");

            let pixel_buffer = PixelBuffer::new_empty(&display, px8::SCREEN_WIDTH * px8::SCREEN_HEIGHT);
            pixel_buffer.write(&vec![px8::Color::Black; pixel_buffer.get_size()]);

            info!("Creating Texture");
            let mut texture = try!(Texture::empty_with_format(&display,
                                                              UncompressedFloatFormat::U8U8U8,
                                                              MipmapsOption::NoMipmap,
                                                              TEXTURE_WIDTH,
                                                              TEXTURE_HEIGHT));

            info!("Uploading Pixels");
            texture.main_level().raw_upload_from_pixel_buffer(pixel_buffer.as_slice(),
                                                              0..px8::SCREEN_WIDTH as u32,
                                                              0..px8::SCREEN_HEIGHT as u32,
                                                              0..1);

            let (width, height) = display.get_context().get_framebuffer_dimensions();
            let (x_scale, y_scale) = aspect_ratio_correction(width, height);
            let matrix = Matrix4::from_diagonal(&Vector4::new(x_scale, y_scale, 1.0, 1.0));

            Ok(Renderer {
                vertex_buffer: vertex_buffer,
                index_buffer: index_buffer,
                pixel_buffer: pixel_buffer,
                program: program,
                texture: texture,
                matrix: matrix,
                display: display,
            })

        }
        pub fn draw<S: Surface>(&self, frame: &mut S) -> RendererResult<()> {
            let uniforms = uniform! {
                matrix: self.matrix.as_ref().clone(),
                tex: self.texture.sampled()
                    .minify_filter(MinifySamplerFilter::Nearest)
                    .magnify_filter(MagnifySamplerFilter::Nearest)
            };

            let params = DrawParameters { ..Default::default() };
            try!(frame.draw(&self.vertex_buffer,
                            &self.index_buffer,
                            &self.program,
                            &uniforms,
                            &params));
            Ok(())
        }

        pub fn blit(&mut self, back_buffer: &px8::ScreenBuffer) {
            self.update_pixels(back_buffer);

            let mut target = self.display.draw();
            target.clear_color(0.0, 0.0, 0.0, 0.0);
            self.draw(&mut target);
            target.finish();
        }

        pub fn update_pixels(&mut self, pixels: &px8::ScreenBuffer) {
            self.pixel_buffer.write(pixels);

            self.texture.main_level().raw_upload_from_pixel_buffer(self.pixel_buffer.as_slice(),
                                                                   0..px8::SCREEN_WIDTH as u32,
                                                                   0..px8::SCREEN_HEIGHT as u32,
                                                                   0..1);
        }

        pub fn update_dimensions(&mut self) {
            let (width, height) = self.display.get_context().get_framebuffer_dimensions();
            let (x_scale, y_scale) = aspect_ratio_correction(width, height);
            self.matrix.m11 = x_scale;
            self.matrix.m22 = y_scale;
        }

        pub fn get_dimensions(&mut self) -> (u32, u32) {
            return self.display.get_context().get_framebuffer_dimensions();
        }
    }

    #[cfg(target_os = "linux")]
    fn configure_gl_attr(gl_attr: &mut GLAttr) {
        info!("Init OPENGL for Linux");
    }

    #[cfg(target_os = "windows")]
    fn configure_gl_attr(gl_attr: &mut GLAttr) {
        info!("Init OPENGL for Windows");
    }

    #[cfg(target_os = "macos")]
    fn configure_gl_attr(gl_attr: &mut GLAttr) {
        info!("Init OPENGL for OSX");

        use sdl2::video::GLProfile;
        gl_attr.set_context_profile(GLProfile::Core);
        gl_attr.set_context_flags().forward_compatible().set();
    }

    #[cfg(target_os = "emscripten")]
    fn configure_gl_attr(gl_attr: &mut GLAttr) {
        info!("Init OPENGL for Emscripten");
    }
}

#[cfg(feature = "sdl_renderer")]
pub mod renderer {
    use px8;
    use gfx::{Scale};

    use sdl2::VideoSubsystem;
    use sdl2::render;
    use sdl2::pixels::PixelFormatEnum;

    #[derive(Clone, Debug)]
    pub enum RendererError {
        Sdl(String),
        Renderer(String),
        Other(String),
    }

    pub type RendererResult<T> = Result<T, RendererError>;

    pub struct Renderer {
        pub renderer: render::Renderer<'static>,
        pub texture: render::Texture,
    }

    impl Renderer {
        pub fn new(sdl_video: VideoSubsystem, fullscreen: bool, scale: Scale) -> RendererResult<Renderer> {
            info!("[SDL] Creating window");

            let mut window_builder = sdl_video.window("PX8",
                                                      (px8::SCREEN_WIDTH as usize * scale.factor()) as u32,
                                                      (px8::SCREEN_HEIGHT as usize * scale.factor()) as u32);
            let window = window_builder.position_centered().build().unwrap();

            info!("[SDL] Creating renderer");
            let mut renderer = window.renderer().accelerated().present_vsync().build().unwrap();

            info!("[SDL] Creating texture");
            let texture = renderer.create_texture(PixelFormatEnum::BGR24,
                                                  render::TextureAccess::Streaming,
                                                  px8::SCREEN_WIDTH as u32,
                                                  px8::SCREEN_HEIGHT as u32).unwrap();

            Ok(Renderer {
                renderer: renderer,
                texture: texture,
            })
        }

        pub fn blit(&mut self, back_buffer: &px8::ScreenBuffer) {
            let mut data = Box::new([0; px8::SCREEN_HEIGHT*px8::SCREEN_WIDTH*3]);

            for x in 0..px8::SCREEN_WIDTH {
                for y in 0..px8::SCREEN_HEIGHT {
                    let col_rgb = px8::Color::to_rgb(back_buffer[x + y * px8::SCREEN_WIDTH]);

                    data[(x+y*px8::SCREEN_WIDTH)*3] = col_rgb.b;
                    data[(x+y*px8::SCREEN_WIDTH)*3+1] = col_rgb.g;
                    data[(x+y*px8::SCREEN_WIDTH)*3+2] = col_rgb.r;
                }
            }

            self.texture.update(None,
                                &mut *data,
                                px8::SCREEN_WIDTH * 3).unwrap();

            self.renderer.clear();
            self.renderer.copy(&self.texture, None, None);
            self.renderer.present();
        }

        pub fn update_dimensions(&mut self) {
        }

        pub fn get_dimensions(&mut self) -> (u32, u32) {
            let size = self.renderer.window().unwrap().size();

            return (size.0, size.1)
        }
    }
}<commit_msg>Add fullscreen for SDL renderer<commit_after>#[cfg(not(feature = "sdl_renderer"))]
pub mod renderer {
    pub mod glium_sdl2;

    use px8;
    use gfx::{Scale};

    use sdl2::video::gl_attr::GLAttr;
    use sdl2::VideoSubsystem;

    use glium;
    use glium::{DrawError, DrawParameters, IndexBuffer, Program, VertexBuffer, Surface};
    use glium::index::PrimitiveType;
    use glium::program::ProgramChooserCreationError;
    use glium::{Api, GliumCreationError, SwapBuffersError, Version};
    use glium::backend::Facade;
    use glium::texture::{ClientFormat, MipmapsOption, PixelValue, TextureCreationError, UncompressedFloatFormat};
    use glium::texture::pixel_buffer::PixelBuffer;
    use glium::texture::texture2d::Texture2d;

    use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter};
    use nalgebra::{Diagonal, Matrix4, Vector4};

    use self::glium_sdl2::{Display, DisplayBuild, GliumSdl2Error};

    #[derive(Clone, Debug)]
    pub enum RendererError {
        Sdl(String),
        Renderer(String),
        Other(String),
    }

    pub type RendererResult<T> = Result<T, RendererError>;

    impl From<DrawError> for RendererError {
        fn from(e: DrawError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<TextureCreationError> for RendererError {
        fn from(e: TextureCreationError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<glium::vertex::BufferCreationError> for RendererError {
        fn from(e: glium::vertex::BufferCreationError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<glium::index::BufferCreationError> for RendererError {
        fn from(e: glium::index::BufferCreationError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<ProgramChooserCreationError> for RendererError {
        fn from(e: ProgramChooserCreationError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<GliumCreationError<GliumSdl2Error>> for RendererError {
        fn from(e: GliumCreationError<GliumSdl2Error>) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    impl From<SwapBuffersError> for RendererError {
        fn from(e: SwapBuffersError) -> RendererError {
            RendererError::Renderer(format!("{:?}", e))
        }
    }

    unsafe impl PixelValue for px8::Color {
        fn get_format() -> ClientFormat {
            ClientFormat::U8
        }
    }

    type Texture = Texture2d;

    #[derive(Copy, Clone)]
    pub struct Vertex {
        position: [f32; 2],
        tex_coords: [f32; 2],
    }

    implement_vertex!(Vertex, position, tex_coords);

    pub struct Renderer {
        vertex_buffer: VertexBuffer<Vertex>,
        index_buffer: IndexBuffer<u16>,
        pixel_buffer: PixelBuffer<px8::Color>,
        program: Program,
        texture: Texture,
        matrix: Matrix4<f32>,
        display: Display,
    }

    const TEXTURE_WIDTH: u32 = 256;
    const TEXTURE_HEIGHT: u32 = 256;
    const TEX_OFFSET_X: f32 = px8::SCREEN_WIDTH as f32 / TEXTURE_WIDTH as f32;
    const TEX_OFFSET_Y: f32 = px8::SCREEN_HEIGHT as f32 / TEXTURE_HEIGHT as f32;

    const ASPECT_RATIO: f32 = px8::SCREEN_WIDTH as f32 / px8::SCREEN_HEIGHT as f32;

    fn aspect_ratio_correction(width: u32, height: u32) -> (f32, f32) {
        let fb_aspect_ratio = width as f32 / height as f32;
        let scale = ASPECT_RATIO / fb_aspect_ratio;
        if fb_aspect_ratio >= ASPECT_RATIO {
            (scale, 1.0)
        } else {
            (1.0, 1.0 / scale)
        }
    }

    impl Renderer {

        pub fn new(sdl_video: VideoSubsystem, fullscreen: bool, scale: Scale) -> RendererResult<Renderer> {
            let display;

            info!("SDL2 Video with opengl [glium]");

            configure_gl_attr(&mut sdl_video.gl_attr());

            if fullscreen {
                info!("SDL2 window fullscreen");

                display = try!(sdl_video.window("PX8",
                                                (px8::SCREEN_WIDTH * scale.factor()) as u32,
                                                (px8::SCREEN_HEIGHT * scale.factor()) as u32)
                    .resizable()
                    .fullscreen()
                    .position_centered()
                    .build_glium());
            } else {
                info!("SDL2 window");

                display = try!(sdl_video.window("PX8",
                                                (px8::SCREEN_WIDTH * scale.factor()) as u32,
                                                (px8::SCREEN_HEIGHT * scale.factor()) as u32)
                    .resizable()
                    .position_centered()
                    .build_glium());
            }

            info!("Init Renderer with GLIUM");

            let vertexes = [
                Vertex {
                    position: [-1.0, -1.0],
                    tex_coords: [0.0, TEX_OFFSET_Y],
                },
                Vertex {
                    position: [-1.0, 1.0],
                    tex_coords: [0.0, 0.0],
                },
                Vertex {
                    position: [1.0, 1.0],
                    tex_coords: [TEX_OFFSET_X, 0.0],
                },
                Vertex {
                    position: [1.0, -1.0],
                    tex_coords: [TEX_OFFSET_X, TEX_OFFSET_Y],
                }
            ];

            info!("Creating VertexBuffer");

            let vertex_buffer = try!(VertexBuffer::immutable(&display, &vertexes));

            info!("Creating IndexBuffer");

            let index_buffer =
            try!(IndexBuffer::immutable(&display, PrimitiveType::TriangleStrip, &[1u16, 2, 0, 3]));

            info!("Compiling shader");

            let program = try!(program!(
              &display,
              140 => {
                vertex: include_str!("shader/vert_140.glsl"),
                fragment: include_str!("shader/frag_140.glsl"),
                outputs_srgb: true
              },
              110 => {
                vertex: include_str!("shader/vert_110.glsl"),
                fragment: include_str!("shader/frag_110.glsl"),
                outputs_srgb: true
              }
            ));

            info!("Creating PixelBuffer");

            let pixel_buffer = PixelBuffer::new_empty(&display, px8::SCREEN_WIDTH * px8::SCREEN_HEIGHT);
            pixel_buffer.write(&vec![px8::Color::Black; pixel_buffer.get_size()]);

            info!("Creating Texture");
            let mut texture = try!(Texture::empty_with_format(&display,
                                                              UncompressedFloatFormat::U8U8U8,
                                                              MipmapsOption::NoMipmap,
                                                              TEXTURE_WIDTH,
                                                              TEXTURE_HEIGHT));

            info!("Uploading Pixels");
            texture.main_level().raw_upload_from_pixel_buffer(pixel_buffer.as_slice(),
                                                              0..px8::SCREEN_WIDTH as u32,
                                                              0..px8::SCREEN_HEIGHT as u32,
                                                              0..1);

            let (width, height) = display.get_context().get_framebuffer_dimensions();
            let (x_scale, y_scale) = aspect_ratio_correction(width, height);
            let matrix = Matrix4::from_diagonal(&Vector4::new(x_scale, y_scale, 1.0, 1.0));

            Ok(Renderer {
                vertex_buffer: vertex_buffer,
                index_buffer: index_buffer,
                pixel_buffer: pixel_buffer,
                program: program,
                texture: texture,
                matrix: matrix,
                display: display,
            })

        }
        pub fn draw<S: Surface>(&self, frame: &mut S) -> RendererResult<()> {
            let uniforms = uniform! {
                matrix: self.matrix.as_ref().clone(),
                tex: self.texture.sampled()
                    .minify_filter(MinifySamplerFilter::Nearest)
                    .magnify_filter(MagnifySamplerFilter::Nearest)
            };

            let params = DrawParameters { ..Default::default() };
            try!(frame.draw(&self.vertex_buffer,
                            &self.index_buffer,
                            &self.program,
                            &uniforms,
                            &params));
            Ok(())
        }

        pub fn blit(&mut self, back_buffer: &px8::ScreenBuffer) {
            self.update_pixels(back_buffer);

            let mut target = self.display.draw();
            target.clear_color(0.0, 0.0, 0.0, 0.0);
            self.draw(&mut target);
            target.finish();
        }

        pub fn update_pixels(&mut self, pixels: &px8::ScreenBuffer) {
            self.pixel_buffer.write(pixels);

            self.texture.main_level().raw_upload_from_pixel_buffer(self.pixel_buffer.as_slice(),
                                                                   0..px8::SCREEN_WIDTH as u32,
                                                                   0..px8::SCREEN_HEIGHT as u32,
                                                                   0..1);
        }

        pub fn update_dimensions(&mut self) {
            let (width, height) = self.display.get_context().get_framebuffer_dimensions();
            let (x_scale, y_scale) = aspect_ratio_correction(width, height);
            self.matrix.m11 = x_scale;
            self.matrix.m22 = y_scale;
        }

        pub fn get_dimensions(&mut self) -> (u32, u32) {
            return self.display.get_context().get_framebuffer_dimensions();
        }
    }

    #[cfg(target_os = "linux")]
    fn configure_gl_attr(gl_attr: &mut GLAttr) {
        info!("Init OPENGL for Linux");
    }

    #[cfg(target_os = "windows")]
    fn configure_gl_attr(gl_attr: &mut GLAttr) {
        info!("Init OPENGL for Windows");
    }

    #[cfg(target_os = "macos")]
    fn configure_gl_attr(gl_attr: &mut GLAttr) {
        info!("Init OPENGL for OSX");

        use sdl2::video::GLProfile;
        gl_attr.set_context_profile(GLProfile::Core);
        gl_attr.set_context_flags().forward_compatible().set();
    }

    #[cfg(target_os = "emscripten")]
    fn configure_gl_attr(gl_attr: &mut GLAttr) {
        info!("Init OPENGL for Emscripten");
    }
}

#[cfg(feature = "sdl_renderer")]
pub mod renderer {
    use px8;
    use gfx::{Scale};

    use sdl2::VideoSubsystem;
    use sdl2::render;
    use sdl2::pixels::PixelFormatEnum;

    #[derive(Clone, Debug)]
    pub enum RendererError {
        Sdl(String),
        Renderer(String),
        Other(String),
    }

    pub type RendererResult<T> = Result<T, RendererError>;

    pub struct Renderer {
        pub renderer: render::Renderer<'static>,
        pub texture: render::Texture,
    }

    impl Renderer {
        pub fn new(sdl_video: VideoSubsystem, fullscreen: bool, scale: Scale) -> RendererResult<Renderer> {
            info!("[SDL] Creating window");

            let mut window_builder = sdl_video.window("PX8",
                                                      (px8::SCREEN_WIDTH as usize * scale.factor()) as u32,
                                                      (px8::SCREEN_HEIGHT as usize * scale.factor()) as u32);

            let window;
            if fullscreen {
                window = window_builder.fullscreen().build().unwrap();
            } else {
                window = window_builder.position_centered().build().unwrap();
            }

            info!("[SDL] Creating renderer");
            let mut renderer = window.renderer().accelerated().present_vsync().build().unwrap();

            info!("[SDL] Creating texture");
            let texture = renderer.create_texture(PixelFormatEnum::BGR24,
                                                  render::TextureAccess::Streaming,
                                                  px8::SCREEN_WIDTH as u32,
                                                  px8::SCREEN_HEIGHT as u32).unwrap();

            Ok(Renderer {
                renderer: renderer,
                texture: texture,
            })
        }

        pub fn blit(&mut self, back_buffer: &px8::ScreenBuffer) {
            let mut data = Box::new([0; px8::SCREEN_HEIGHT*px8::SCREEN_WIDTH*3]);

            for x in 0..px8::SCREEN_WIDTH {
                for y in 0..px8::SCREEN_HEIGHT {
                    let col_rgb = px8::Color::to_rgb(back_buffer[x + y * px8::SCREEN_WIDTH]);

                    data[(x+y*px8::SCREEN_WIDTH)*3] = col_rgb.b;
                    data[(x+y*px8::SCREEN_WIDTH)*3+1] = col_rgb.g;
                    data[(x+y*px8::SCREEN_WIDTH)*3+2] = col_rgb.r;
                }
            }

            self.texture.update(None,
                                &mut *data,
                                px8::SCREEN_WIDTH * 3).unwrap();

            self.renderer.clear();
            self.renderer.copy(&self.texture, None, None);
            self.renderer.present();
        }

        pub fn update_dimensions(&mut self) {
        }

        pub fn get_dimensions(&mut self) -> (u32, u32) {
            let size = self.renderer.window().unwrap().size();

            return (size.0, size.1)
        }
    }
}<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate sputnikvm;
extern crate bigint;
extern crate serde_json;
extern crate gethrpc;

use serde_json::{Value};
use std::process;
use std::fs::File;
use std::path::Path;
use std::io::{BufReader};
use std::str::FromStr;

use sputnikvm::{Gas, Address};
use bigint::{U256, M256, read_hex};
use sputnikvm::vm::{BlockHeader, Context, SeqVM, Patch, AccountCommitment};
use sputnikvm::vm::errors::RequireError;
use gethrpc::{regression, GethRPCClient, RPCCall, RPCBlock, RPCTransaction};

fn from_rpc_block(block: &RPCBlock) -> BlockHeader {
    BlockHeader {
        coinbase: Address::from_str(&block.miner).unwrap(),
        timestamp: M256::from_str(&block.timestamp).unwrap(),
        number: M256::from_str(&block.number).unwrap(),
        difficulty: M256::from_str(&block.difficulty).unwrap(),
        gas_limit: Gas::from_str(&block.gasLimit).unwrap(),
    }
}

fn from_rpc_transaction_and_code(transaction: &RPCTransaction, code: &str) -> Context {
    Context {
        caller: Address::from_str(&transaction.from).unwrap(),
        address: Address::from_str(&transaction.to).unwrap(),
        origin: Address::from_str(&transaction.to).unwrap(),
        value: U256::from_str(&transaction.value).unwrap(),
        code: read_hex(code).unwrap(),
        data: read_hex(&transaction.input).unwrap(),
        gas_limit: Gas::from_str(&transaction.gas).unwrap(),
        gas_price: Gas::from_str(&transaction.gasPrice).unwrap(),
    }
}

fn main() {
    let mut client = GethRPCClient::new("http://127.0.0.1:8545");

    println!("net version: {}", client.net_version());

    let block = client.get_block_by_number(format!("0x{:x}", 49439).as_str());
    println!("block {}, transaction count: {}", block.number, block.transactions.len());

    let block_header = from_rpc_block(&block);

    for transaction_hash in block.transactions {
        println!("\nworking on transaction {}", transaction_hash);
        let transaction = client.get_transaction_by_hash(&transaction_hash);
        println!("transaction: {:?}", transaction);
        let receipt = client.get_transaction_receipt(&transaction_hash);
        println!("receipt: {:?}", receipt);
        let code = client.get_code(&transaction.to, &block.number);
        println!("code: {:?}", code);

        let context = from_rpc_transaction_and_code(&transaction, &code);

        let mut vm = SeqVM::new(context, block_header.clone(), Patch::empty());
        loop {
            match vm.fire() {
                Ok(()) => {
                    println!("VM exited successfully, checking results ...");
                    break;
                },
                Err(RequireError::Account(address)) => {
                    println!("Feeding VM account at 0x{:x} ...", address);
                    let nonce = M256::from_str(&client.get_transaction_count(&format!("0x{:x}", address),
                                                                             &block.number)).unwrap();
                    let balance = U256::from_str(&client.get_balance(&format!("0x{:x}", address),
                                                                    &block.number)).unwrap();
                    let code = read_hex(&client.get_code(&format!("0x{:x}", address),
                                                         &block.number)).unwrap();
                    vm.commit_account(AccountCommitment::Full {
                        nonce: nonce,
                        address: address,
                        balance: balance,
                        code: code,
                    });
                },
                Err(RequireError::AccountStorage(address, index)) => {
                    println!("Feeding VM account storage at 0x{:x} with index 0x{:x} ...", address, index);
                    let value = M256::from_str(&client.get_storage_at(&format!("0x{:x}", address),
                                                                      &format!("0x{:x}", index),
                                                                      &block.number)).unwrap();
                    vm.commit_account(AccountCommitment::Storage {
                        address: address,
                        index: index,
                        value: value,
                    });
                }
                Err(err) => {
                    println!("Unhandled require: {:?}", err);
                    unimplemented!()
                },
            }
        }

        println!("\ntests after the vm has run:");
        println!("2. test gasUsed == {:?}", receipt.gasUsed);
        println!("3. logs and order is {:?}", receipt.logs);
    }

    println!("\nwhen the block is finished, test:");
    println!("1. balances of all used accounts.");
    println!("2. storage values touched.");

    // let matches = clap_app!(regression_test =>
    //     (version: "0.1")
    //     (author: "Ethereum Classic Contributors")
    //     (about: "Gaslighter - Tests the Ethereum Classic Virtual Machine in 5 different ways.")
    //     (@arg KEEP_GOING: -k --keep_going "Don't exit the program even if a test fails.")
    //     (@subcommand reg =>
    //         (about: "Performs an regression test on the entire Ethereum Classic blockchain.\n\nSteps to reproduce:\n* Install Ethereum Classic Geth: `$ go install github.com/ethereumproject/go-ethereum/cmd/geth`.\n* Run Geth with this command: `$ ~/go/bin/geth`.\n* Wait for the chain to sync.\n* <ctrl-c>\n* Change directory into the gaslighter directory `$ cd gaslighter`\n* Run this command: `$ RUST_BACKTRACE=1 RUST_LOG=gaslighter cargo run --bin gaslighter -- -k reg -c ~/.ethereum/chaindata/`")
    //         (@arg RPC: -r --rpc +takes_value +required "Domain of Ethereum Classic Geth's RPC endpoint. e.g. `-r localhost:8888`.")
    //     )
    // ).get_matches();
    // let mut has_regression_test_passed = true;
    // let keep_going = if matches.is_present("KEEP_GOING") { true } else { false };
    // if let Some(ref matches) = matches.subcommand_matches("reg") {
    //     let path = matches.value_of("RPC").unwrap();
    //     has_regression_test_passed = regression(path);
    // }
    // if has_regression_test_passed {
    //     process::exit(0);
    // } else {
    //     process::exit(1);
    // }
}
<commit_msg>Problem: when transaction.to == null it's a contract creation<commit_after>#[macro_use]
extern crate clap;
extern crate sputnikvm;
extern crate bigint;
extern crate serde_json;
extern crate gethrpc;

use serde_json::{Value};
use std::process;
use std::fs::File;
use std::path::Path;
use std::io::{BufReader};
use std::str::FromStr;

use sputnikvm::{Gas, Address};
use bigint::{U256, M256, read_hex};
use sputnikvm::vm::{BlockHeader, Context, SeqVM, Patch, AccountCommitment};
use sputnikvm::vm::errors::RequireError;
use gethrpc::{regression, GethRPCClient, RPCCall, RPCBlock, RPCTransaction};

fn from_rpc_block(block: &RPCBlock) -> BlockHeader {
    BlockHeader {
        coinbase: Address::from_str(&block.miner).unwrap(),
        timestamp: M256::from_str(&block.timestamp).unwrap(),
        number: M256::from_str(&block.number).unwrap(),
        difficulty: M256::from_str(&block.difficulty).unwrap(),
        gas_limit: Gas::from_str(&block.gasLimit).unwrap(),
    }
}

fn from_rpc_transaction_and_code(transaction: &RPCTransaction, code: &str) -> Context {
    Context {
        caller: Address::from_str(&transaction.from).unwrap(),
        address: Address::from_str(&transaction.to).unwrap(),
        origin: Address::from_str(&transaction.to).unwrap(),
        value: U256::from_str(&transaction.value).unwrap(),
        code: read_hex(code).unwrap(),
        data: read_hex(&transaction.input).unwrap(),
        gas_limit: Gas::from_str(&transaction.gas).unwrap(),
        gas_price: Gas::from_str(&transaction.gasPrice).unwrap(),
    }
}

fn main() {
    let mut client = GethRPCClient::new("http://127.0.0.1:8545");

    println!("net version: {}", client.net_version());

    let block = client.get_block_by_number(format!("0x{:x}", 49439).as_str());
    println!("block {}, transaction count: {}", block.number, block.transactions.len());

    let block_header = from_rpc_block(&block);

    for transaction_hash in block.transactions {
        println!("\nworking on transaction {}", transaction_hash);
        let transaction = client.get_transaction_by_hash(&transaction_hash);
        println!("transaction: {:?}", transaction);
        let receipt = client.get_transaction_receipt(&transaction_hash);
        println!("receipt: {:?}", receipt);
        if transaction.to.is_empty() {
            continue;
        }
        let code = client.get_code(&transaction.to, &block.number);
        println!("code: {:?}", code);

        let context = from_rpc_transaction_and_code(&transaction, &code);

        let mut vm = SeqVM::new(context, block_header.clone(), Patch::empty());
        loop {
            match vm.fire() {
                Ok(()) => {
                    println!("VM exited successfully, checking results ...");
                    break;
                },
                Err(RequireError::Account(address)) => {
                    println!("Feeding VM account at 0x{:x} ...", address);
                    let nonce = M256::from_str(&client.get_transaction_count(&format!("0x{:x}", address),
                                                                             &block.number)).unwrap();
                    let balance = U256::from_str(&client.get_balance(&format!("0x{:x}", address),
                                                                    &block.number)).unwrap();
                    let code = read_hex(&client.get_code(&format!("0x{:x}", address),
                                                         &block.number)).unwrap();
                    vm.commit_account(AccountCommitment::Full {
                        nonce: nonce,
                        address: address,
                        balance: balance,
                        code: code,
                    });
                },
                Err(RequireError::AccountStorage(address, index)) => {
                    println!("Feeding VM account storage at 0x{:x} with index 0x{:x} ...", address, index);
                    let value = M256::from_str(&client.get_storage_at(&format!("0x{:x}", address),
                                                                      &format!("0x{:x}", index),
                                                                      &block.number)).unwrap();
                    vm.commit_account(AccountCommitment::Storage {
                        address: address,
                        index: index,
                        value: value,
                    });
                }
                Err(err) => {
                    println!("Unhandled require: {:?}", err);
                    unimplemented!()
                },
            }
        }

        println!("\ntests after the vm has run:");
        println!("2. test gasUsed == {:?}", receipt.gasUsed);
        println!("3. logs and order is {:?}", receipt.logs);
    }

    println!("\nwhen the block is finished, test:");
    println!("1. balances of all used accounts.");
    println!("2. storage values touched.");

    // let matches = clap_app!(regression_test =>
    //     (version: "0.1")
    //     (author: "Ethereum Classic Contributors")
    //     (about: "Gaslighter - Tests the Ethereum Classic Virtual Machine in 5 different ways.")
    //     (@arg KEEP_GOING: -k --keep_going "Don't exit the program even if a test fails.")
    //     (@subcommand reg =>
    //         (about: "Performs an regression test on the entire Ethereum Classic blockchain.\n\nSteps to reproduce:\n* Install Ethereum Classic Geth: `$ go install github.com/ethereumproject/go-ethereum/cmd/geth`.\n* Run Geth with this command: `$ ~/go/bin/geth`.\n* Wait for the chain to sync.\n* <ctrl-c>\n* Change directory into the gaslighter directory `$ cd gaslighter`\n* Run this command: `$ RUST_BACKTRACE=1 RUST_LOG=gaslighter cargo run --bin gaslighter -- -k reg -c ~/.ethereum/chaindata/`")
    //         (@arg RPC: -r --rpc +takes_value +required "Domain of Ethereum Classic Geth's RPC endpoint. e.g. `-r localhost:8888`.")
    //     )
    // ).get_matches();
    // let mut has_regression_test_passed = true;
    // let keep_going = if matches.is_present("KEEP_GOING") { true } else { false };
    // if let Some(ref matches) = matches.subcommand_matches("reg") {
    //     let path = matches.value_of("RPC").unwrap();
    //     has_regression_test_passed = regression(path);
    // }
    // if has_regression_test_passed {
    //     process::exit(0);
    // } else {
    //     process::exit(1);
    // }
}
<|endoftext|>


<commit_before>extern crate itertools;

use itertools::Itertools;
use std::str::FromStr;

fn get_next_number<'a, I>(number: I) -> Vec<u8>
    where I: IntoIterator<Item = &'a u8>
{
    number.into_iter()
          .group_by(|&n| *n)
          .flat_map(|(key, group)| {
              vec![group.len() as u8, key]
          })
          .collect()
}

fn get_number_after_n_iterations<'a, I>(number: I, n: usize) -> Vec<u8>
    where I: IntoIterator<Item = &'a u8>
{
    (0..n).fold(number.into_iter().cloned().collect(),
                |n, _| get_next_number(&n))
}

fn main() {
    let n = match std::env::args().nth(1).and_then(|arg| usize::from_str(&arg).ok()) {
        Some(arg) => arg,
        None => {
            println!("Call with: day-10 <iterations>");
            return;
        }
    };

    let input = [3, 1, 1, 3, 3, 2, 2, 1, 1, 3];

    let n_iterations = get_number_after_n_iterations(&input, n);
    println!("Length of Number after {} iterations: {}",
             n,
             n_iterations.len());
}

#[test]
fn test_next_number() {
    assert_eq!(get_next_number(&[1]), [1, 1]);
    assert_eq!(get_next_number(&[1, 1]), [2, 1]);
    assert_eq!(get_next_number(&[2, 1]), [1, 2, 1, 1]);
    assert_eq!(get_next_number(&[1, 2, 1, 1]), [1, 1, 1, 2, 2, 1]);
    assert_eq!(get_next_number(&[1, 1, 1, 2, 2, 1]), [3, 1, 2, 2, 1, 1]);

    assert_eq!(get_next_number(&[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]),
               [1, 2, 3]);
}

#[test]
fn test_number_after_n_iterations() {
    assert_eq!(get_number_after_n_iterations(&[1], 0), [1]);
    assert_eq!(get_number_after_n_iterations(&[1], 1), [1, 1]);
    assert_eq!(get_number_after_n_iterations(&[1], 2), [2, 1]);
    assert_eq!(get_number_after_n_iterations(&[1], 3), [1, 2, 1, 1]);
    assert_eq!(get_number_after_n_iterations(&[1], 4), [1, 1, 1, 2, 2, 1]);
    assert_eq!(get_number_after_n_iterations(&[1], 5), [3, 1, 2, 2, 1, 1]);
}
<commit_msg>Add faster version of Day 10<commit_after>extern crate itertools;

use itertools::Itertools;
use std::str::FromStr;

fn get_next_number_itertools(number: &Vec<u8>) -> Vec<u8>
{
    let mut result = Vec::with_capacity(2 * number.len());
    for (key, group) in number.into_iter().group_by(|&n| *n) {
        result.push(group.len() as u8);
        result.push(key);
    }
    result
}

fn get_next_number_fast(number: Vec<u8>) -> Vec<u8>
{
    let mut result = Vec::with_capacity(2 * number.len());
    let mut iter = number.into_iter();
    let mut maybe_digit = iter.next();
    while let Some(digit) = maybe_digit {
        let mut repeat = 1;
        maybe_digit = None;
        while let Some(other_digit) = iter.next() {
            if other_digit != digit {
                maybe_digit = Some(other_digit);
                break;
            }
            repeat += 1;
        }
        result.push(repeat);
        result.push(digit);
    }
    return result;
}

fn get_number_after_n_iterations<'a, I>(number: I, n: usize) -> Vec<u8>
    where I: IntoIterator<Item = &'a u8>
{
    (0..n).fold(number.into_iter().cloned().collect(),
                |n, _| get_next_number_fast(n))
}

fn main() {
    let n = match std::env::args().nth(1).and_then(|arg| usize::from_str(&arg).ok()) {
        Some(arg) => arg,
        None => {
            println!("Call with: day-10 <iterations>");
            return;
        }
    };

    let input = [3, 1, 1, 3, 3, 2, 2, 1, 1, 3];

    let n_iterations = get_number_after_n_iterations(&input, n);
    println!("Length of Number after {} iterations: {}",
             n,
             n_iterations.len());
}

#[test]
fn test_next_number_itertools() {
    assert_eq!(get_next_number_itertools(&vec![1]), vec![1, 1]);
    assert_eq!(get_next_number_itertools(&vec![1, 1]), vec![2, 1]);
    assert_eq!(get_next_number_itertools(&vec![2, 1]), vec![1, 2, 1, 1]);
    assert_eq!(get_next_number_itertools(&vec![1, 2, 1, 1]), vec![1, 1, 1, 2, 2, 1]);
    assert_eq!(get_next_number_itertools(&vec![1, 1, 1, 2, 2, 1]), vec![3, 1, 2, 2, 1, 1]);
}

#[test]
fn test_next_number_fast() {
    assert_eq!(get_next_number_fast(vec![1]), vec![1, 1]);
    assert_eq!(get_next_number_fast(vec![1, 1]), vec![2, 1]);
    assert_eq!(get_next_number_fast(vec![2, 1]), vec![1, 2, 1, 1]);
    assert_eq!(get_next_number_fast(vec![1, 2, 1, 1]), vec![1, 1, 1, 2, 2, 1]);
    assert_eq!(get_next_number_fast(vec![1, 1, 1, 2, 2, 1]), vec![3, 1, 2, 2, 1, 1]);
}

#[test]
fn test_number_after_n_iterations() {
    assert_eq!(get_number_after_n_iterations(&vec![1], 0), vec![1]);
    assert_eq!(get_number_after_n_iterations(&vec![1], 1), vec![1, 1]);
    assert_eq!(get_number_after_n_iterations(&vec![1], 2), vec![2, 1]);
    assert_eq!(get_number_after_n_iterations(&vec![1], 3), vec![1, 2, 1, 1]);
    assert_eq!(get_number_after_n_iterations(&vec![1], 4), vec![1, 1, 1, 2, 2, 1]);
    assert_eq!(get_number_after_n_iterations(&vec![1], 5), vec![3, 1, 2, 2, 1, 1]);
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::Path;
use std::cmp;

fn make_bitset32(indices: &[usize]) -> u32 {
    indices.iter().fold(0, |bits, &i| bits | (1 << i as u32))
}

#[derive(Debug,Copy,Clone)]
struct Group {
    count: u32,
    weight: u64,
    qe: u64, // quantum entanglement
    bitset: u32,
}
impl Group {
    fn new(weights: &[u32], indices: &[usize]) -> Group {
        let count = indices.len() as u32;
        let weight = indices.iter().fold(0u64, |sum, &i| sum + weights[i] as u64);
        let qe = indices.iter().fold(1u64, |prod, &i| prod * weights[i] as u64);
        let bitset = make_bitset32(indices);

        Group{count: count, weight: weight, qe: qe, bitset: bitset}
    }
}

fn collect_indices(vals: &[bool]) -> Vec<usize> {
    vals.iter().enumerate().filter(|&(_, val)| *val == true).map(|(i, _)| i).collect()
}

// For each index in the array:
//  Add the corrosponding value to the current sum
//  If size equal to target size:
//      add to the list.
//  else
//      Recursively iterate over all indices larger than the current one
//  Unset the current index to remove it from the active set.
fn find_subsets(weights: &[u32],
                start: usize,
                target_size: u32,
                starting_size: u32,
                used_indices: &mut Vec<bool>,
                results: &mut Vec<Vec<usize>>) {

    for idx in start..weights.len() {
        let used = used_indices[idx];
        let weight = weights[idx];

        if !used && starting_size + weight <= target_size {
            used_indices[idx] = true;
            let current_size = starting_size + weight;
            if current_size == target_size {
                results.push(collect_indices(&used_indices));
            } else {
                find_subsets(&weights,
                             idx,
                             target_size,
                             current_size,
                             used_indices,
                             results);
            }

            used_indices[idx] = false;
        }
    }
}

fn main() {

    // Read weights to vector
    let path = Path::new("input.txt");
    let file = match File::open(&path) {
        Err(why) => {
            panic!("couldn't open {}: {}",
                   path.display(),
                   Error::description(&why))
        }
        Ok(file) => file,
    };

    let lines = BufReader::new(file).lines();
    // ok() converts Result into Option
    let weights: Vec<u32> = lines.into_iter()
                                 .map(|l| l.ok().and_then(|s| s.parse().ok()).unwrap_or(0))
                                 .collect();

    let total_weight = weights.iter().fold(0, |sum, &n| sum + n);
    let bin_size = total_weight / 3;

    println!("Trying to fit {} items of total weight {} into three bins of size {} each.",
             weights.len(),
             total_weight,
             bin_size);

    let mut used = vec![false; weights.len()];
    let mut results = Vec::new();
    find_subsets(&weights, 0, bin_size, 0, &mut used, &mut results);

    println!("Found {} sets of size {}", results.len(), bin_size);

    let mut groups: Vec<Group> = results.iter().map(|ref indices| Group::new(&weights, &indices)).collect();

    // Sort by package count
    groups.sort_by_key(|a| a.count);

    // Now that the groups are sorted by package order, find the first one that
    // has at least one other non-overlapping group (bits & bits) == 0
    // If two groups can exist at the same time, the third exists by default
    let mut lowest_count = u32::max_value();
    let mut lowest_qe = u64::max_value();
    let mut lowest_weight = u64::max_value();
    let mut best_group = Group{count: 0, weight:0, qe: 0, bitset: 0};
    for group_1 in &groups {
        if group_1.count > lowest_count {
            break;
        }

        for group_2 in &groups {
            let overlap = group_1.bitset & group_2.bitset;

            // If compatible and the weight has not increased
            if overlap == 0 && group_1.weight <= lowest_weight && group_1.qe < lowest_qe {
                lowest_count = cmp::min(lowest_count, group_1.count);
                lowest_weight = cmp::min(lowest_weight, group_1.weight);
                lowest_qe = cmp::min(lowest_qe, group_1.qe);
                best_group = group_1.clone();
            }
        }
    }

    println!("Found best group_1: {:?}", best_group);

    assert_eq!(best_group.qe, 11846773891);
}
<commit_msg>Day 24, part 2.<commit_after>use std::error::Error;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::Path;
use std::cmp;

fn make_bitset32(indices: &[usize]) -> u32 {
    indices.iter().fold(0, |bits, &i| bits | (1 << i as u32))
}

#[derive(Debug,Copy,Clone)]
struct Group {
    count: u32,
    weight: u64,
    qe: u64, // quantum entanglement
    bitset: u32,
}
impl Group {
    fn new(weights: &[u32], indices: &[usize]) -> Group {
        let count = indices.len() as u32;
        let weight = indices.iter().fold(0u64, |sum, &i| sum + weights[i] as u64);
        let qe = indices.iter().fold(1u64, |prod, &i| prod * weights[i] as u64);
        let bitset = make_bitset32(indices);

        Group {
            count: count,
            weight: weight,
            qe: qe,
            bitset: bitset,
        }
    }
}

fn collect_indices(vals: &[bool]) -> Vec<usize> {
    vals.iter().enumerate().filter(|&(_, val)| *val == true).map(|(i, _)| i).collect()
}

// For each index in the array:
//  Add the corrosponding value to the current sum
//  If size equal to target size:
//      add to the list.
//  else
//      Recursively iterate over all indices larger than the current one
//  Unset the current index to remove it from the active set.
fn find_subsets(weights: &[u32],
                start: usize,
                target_size: u32,
                starting_size: u32,
                used_indices: &mut Vec<bool>,
                results: &mut Vec<Vec<usize>>) {

    for idx in start..weights.len() {
        let used = used_indices[idx];
        let weight = weights[idx];

        if !used && starting_size + weight <= target_size {
            used_indices[idx] = true;
            let current_size = starting_size + weight;
            if current_size == target_size {
                results.push(collect_indices(&used_indices));
            } else {
                find_subsets(&weights,
                             idx,
                             target_size,
                             current_size,
                             used_indices,
                             results);
            }

            used_indices[idx] = false;
        }
    }
}

fn main() {

    // Read weights to vector
    let path = Path::new("input.txt");
    let file = match File::open(&path) {
        Err(why) => {
            panic!("couldn't open {}: {}",
                   path.display(),
                   Error::description(&why))
        }
        Ok(file) => file,
    };

    let lines = BufReader::new(file).lines();
    // ok() converts Result into Option
    let weights: Vec<u32> = lines.into_iter()
                                 .map(|l| l.ok().and_then(|s| s.parse().ok()).unwrap_or(0))
                                 .collect();

    let total_weight = weights.iter().fold(0, |sum, &n| sum + n);
    let bin_size_3 = total_weight / 3;

    println!("Part 1: Trying to fit {} items of total weight {} into three bins of size {} each.",
             weights.len(),
             total_weight,
             bin_size_3);

    let mut used = vec![false; weights.len()];
    let mut results = Vec::new();
    find_subsets(&weights, 0, bin_size_3, 0, &mut used, &mut results);
    println!("Part 1: found {} sets of size {}",
             results.len(),
             bin_size_3);

    let mut groups: Vec<Group> = results.iter()
                                        .map(|ref indices| Group::new(&weights, &indices))
                                        .collect();
    groups.sort_by_key(|a| a.count);    // Sort by package count

    // Now that the groups are sorted by package order, find the first one that
    // has at least one other non-overlapping group (bits & bits) == 0
    // If two groups can exist at the same time, the third exists by default
    let mut lowest_count = u32::max_value();
    let mut lowest_qe = u64::max_value();
    let mut lowest_weight = u64::max_value();
    let mut best_group = Group {
        count: 0,
        weight: 0,
        qe: 0,
        bitset: 0,
    };
    for group_1 in &groups {
        if group_1.count > lowest_count {
            break;
        }

        for group_2 in &groups {
            let overlap = group_1.bitset & group_2.bitset;

            // If compatible and the weight has not increased
            if overlap == 0 && group_1.weight <= lowest_weight && group_1.qe < lowest_qe {
                lowest_count = cmp::min(lowest_count, group_1.count);
                lowest_weight = cmp::min(lowest_weight, group_1.weight);
                lowest_qe = cmp::min(lowest_qe, group_1.qe);
                best_group = group_1.clone();
            }
        }
    }

    println!("Part 1: found best group_1: {:?}", best_group);
    assert_eq!(best_group.qe, 11846773891);

    // Part 2
    // Create four equal weight groups instead of three.
    println!("");

    let bin_size_4 = total_weight / 4;
    println!("Part 2: Trying to fit {} items of total weight {} into four bins of size {} each.",
             weights.len(),
             total_weight,
             bin_size_4);

    let mut used = vec![false; weights.len()];
    let mut results = Vec::new();
    find_subsets(&weights, 0, bin_size_4, 0, &mut used, &mut results);
    println!("Part 2: found {} sets of size {}",
             results.len(),
             bin_size_4);

    let mut groups: Vec<Group> = results.iter()
                                        .map(|ref indices| Group::new(&weights, &indices))
                                        .collect();
    groups.sort_by_key(|a| a.count);    // Sort by package count

    println!("sorted. Now filtering...");

    // Now that the groups are sorted by package order, find the first one that
    // has at least two other non-overlapping group (bits1 & bits2 & bits3) == 0
    // If three groups can exist at the same time, the fourth exists by default
    //
    // Note: this is extremely slow without breaking on the first result. Should find a better way.
    let mut best_group = Group {
        count: 0,
        weight: 0,
        qe: 0,
        bitset: 0,
    };
    'outer: for group_1 in &groups {
        if group_1.count > lowest_count {
            break;
        }
        for group_2 in &groups {
            if group_1.bitset & group_2.bitset == 0 {
                for group_3 in &groups {
                    if group_1.bitset & group_2.bitset & group_3.bitset == 0 {
                        best_group = group_1.clone();
                        break 'outer;
                    }
                }
            }
        }
        println!("group_1.count {}", group_1.count);
    }

    println!("Part 2: found best group_1: {:?}", best_group);
    assert_eq!(best_group.qe, 80393059);
}
<|endoftext|>


<commit_before>use std::mem::transmute;
use std::os::unix::io::AsRawFd;
use std::time::Duration;
use std::thread::sleep;
use std::io::Write;

use wayland_client::wayland::get_display;
use wayland_client::wayland::compositor::{WlCompositor, WlSurface};
use wayland_client::wayland::shell::{WlShellSurface, WlShell};
use wayland_client::wayland::shm::{WlBuffer, WlShm, WlShmFormat};
use wayland_client::wayland::seat::{WlSeat, WlPointerEvent};
use wayland_client::wayland::WlDisplay;
use wayland_client::cursor::{CursorTheme, Cursor, load_theme};
use wayland_client::{EventIterator, Proxy};

use rustwlc::WlcOutput;
use tempfile;

use byteorder::{NativeEndian, WriteBytesExt};

wayland_env!(WaylandEnv,
             compositor: WlCompositor,
             shell: WlShell,
             shm: WlShm,
             seat: WlSeat
);

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
/// Holds the bytes to represent a colored background.
/// To be written into a wayland surface.
pub struct Color(pub [u8; 4]);

impl Color {
    /// Generate a new color out of a u32.
    /// E.G: 0xFFFFFFFF
    pub fn from_u32(color: u32) -> Self {
        unsafe { Color(transmute(color)) }
    }
}

pub fn generate_solid_background(color: Color, output: WlcOutput) {
    // Get shortcuts to the globals.
    let (display, iter) = get_display()
        .expect("Unable to connect to a wayland compositor");
    let (env, mut evt_iter) = WaylandEnv::init(display, iter);
    let compositor = env.compositor.as_ref().map(|o| &o.0).unwrap();
    let shell = env.shell.as_ref().map(|o| &o.0).unwrap();
    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();
    let seat = env.seat.as_ref().map(|o| &o.0).unwrap();

    // Create the surface we are going to write into
    let surface = compositor.create_surface();
    let shell_surface = shell.get_shell_surface(&surface);
    let mut tmp = tempfile::tempfile().ok().expect("Unable to create a tempfile.");

    // Calculate how big the buffer needs to be from the output resolution
    let resolution = output.get_resolution().clone();
    let (width, height) = (resolution.w as i32, resolution.h as i32);
    let size = (resolution.w * resolution.h) as i32;

    // Write in the color coding to the surface
    for _ in 0..size {
        unsafe {
            tmp.write_u32::<NativeEndian>(transmute(color.0))
                .expect("Could not write to file")
        }
    }
    tmp.flush()
        .expect("Could not flush buffer");

    // Create the buffer that is mem-mapped to the temp file descriptor
    let pool = shm.create_pool(tmp.as_raw_fd(), size);
    let buffer = pool.create_buffer(0, width, height, width, WlShmFormat::Argb8888);
    // Tell Way Cooler not to set put this in the tree, treat as background
    shell_surface.set_class("Background".into());

    // Attach the buffer to the surface
    surface.attach(Some(&buffer), 0, 0);
    surface.set_buffer_scale(4);
    surface.commit();
    evt_iter.sync_roundtrip().unwrap();

    main_background_loop(compositor, shell, shm, seat, surface,
                         shell_surface, buffer, evt_iter);
}

/// Main loop for rendering backgrounds.
/// Need to keep the surface alive, and update it if the
/// user wants to change the background.
#[allow(unused_variables)]
fn main_background_loop(compositor: &WlCompositor, shell: &WlShell, shm: &WlShm,
                        seat: &WlSeat,
                        surface: WlSurface, shell_surface: WlShellSurface,
                        buffer: WlBuffer, mut event_iter: EventIterator) {
    use wayland_client::wayland::WaylandProtocolEvent;
    use wayland_client::Event;
    println!("Entering main loop");
    // For now just loop and do nothing
    // Eventually need to query the background state and update
    let cursor_surface = compositor.create_surface();
    let mut pointer = seat.get_pointer();
    let cursor_theme = load_theme(None, 16, shm);
    // TODO Figure out why not working on Timidger's machine
    let cursor = cursor_theme.get_cursor("default")
        .expect("Couldn't load cursor from theme");
    let cursor_buffer = cursor.frame_buffer(0).expect("Couldn't get frame_buffer");
    cursor_surface.attach(Some(&*cursor_buffer), 0, 0);
    pointer.set_event_iterator(&event_iter);
    loop {
        for event in &mut event_iter {
            match event {
                Event::Wayland(wayland_event) => {
                    match wayland_event {
                        WaylandProtocolEvent::WlPointer(id, pointer_event) => {
                            match pointer_event {
                                WlPointerEvent::Enter(serial, surface, surface_x, surface_y) => {
                                    warn!("Enter event at ({}, {})", surface_x, surface_y);
                                    // Set the surface to use a cursor
                                    //pointer.set_cursor(0/*??*/, Some(&cursor_surface), 0, 0);
                                },
                                _ => {
                                    pointer.set_cursor(0/*??*/, Some(&cursor_surface), 0, 0)
                                }
                            }
                        },
                        _ => {/* unhandled events */}
                    }
                }
                _ => { /* unhandled events */ }
            }
        }
        event_iter.dispatch().expect("Connection with the compositor was lost.");
    }
}
<commit_msg>Register cursor before event loop!!!!<commit_after>use std::mem::transmute;
use std::os::unix::io::AsRawFd;
use std::time::Duration;
use std::thread::sleep;
use std::io::Write;

use wayland_client::wayland::get_display;
use wayland_client::wayland::compositor::{WlCompositor, WlSurface};
use wayland_client::wayland::shell::{WlShellSurface, WlShell};
use wayland_client::wayland::shm::{WlBuffer, WlShm, WlShmFormat};
use wayland_client::wayland::seat::{WlSeat, WlPointerEvent};
use wayland_client::wayland::WlDisplay;
use wayland_client::cursor::{CursorTheme, Cursor, load_theme};
use wayland_client::{EventIterator, Proxy};

use rustwlc::WlcOutput;
use tempfile;

use byteorder::{NativeEndian, WriteBytesExt};

wayland_env!(WaylandEnv,
             compositor: WlCompositor,
             shell: WlShell,
             shm: WlShm,
             seat: WlSeat
);

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
/// Holds the bytes to represent a colored background.
/// To be written into a wayland surface.
pub struct Color(pub [u8; 4]);

impl Color {
    /// Generate a new color out of a u32.
    /// E.G: 0xFFFFFFFF
    pub fn from_u32(color: u32) -> Self {
        unsafe { Color(transmute(color)) }
    }
}

pub fn generate_solid_background(color: Color, output: WlcOutput) {
    // Get shortcuts to the globals.
    let (display, iter) = get_display()
        .expect("Unable to connect to a wayland compositor");
    let (env, mut evt_iter) = WaylandEnv::init(display, iter);
    let compositor = env.compositor.as_ref().map(|o| &o.0).unwrap();
    let shell = env.shell.as_ref().map(|o| &o.0).unwrap();
    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();
    let seat = env.seat.as_ref().map(|o| &o.0).unwrap();

    // Create the surface we are going to write into
    let surface = compositor.create_surface();
    let shell_surface = shell.get_shell_surface(&surface);
    let mut tmp = tempfile::tempfile().ok().expect("Unable to create a tempfile.");

    // Calculate how big the buffer needs to be from the output resolution
    let resolution = output.get_resolution().clone();
    let (width, height) = (resolution.w as i32, resolution.h as i32);
    let size = (resolution.w * resolution.h) as i32;

    // Write in the color coding to the surface
    for _ in 0..size {
        unsafe {
            tmp.write_u32::<NativeEndian>(transmute(color.0))
                .expect("Could not write to file")
        }
    }
    tmp.flush()
        .expect("Could not flush buffer");

    // Create the buffer that is mem-mapped to the temp file descriptor
    let pool = shm.create_pool(tmp.as_raw_fd(), size);
    let buffer = pool.create_buffer(0, width, height, width, WlShmFormat::Argb8888);
    // Tell Way Cooler not to set put this in the tree, treat as background
    shell_surface.set_class("Background".into());

    // Attach the buffer to the surface
    surface.attach(Some(&buffer), 0, 0);
    surface.set_buffer_scale(4);
    surface.commit();
    evt_iter.sync_roundtrip().unwrap();

    main_background_loop(compositor, shell, shm, seat, surface,
                         shell_surface, buffer, evt_iter);
}

/// Main loop for rendering backgrounds.
/// Need to keep the surface alive, and update it if the
/// user wants to change the background.
#[allow(unused_variables)]
fn main_background_loop(compositor: &WlCompositor, shell: &WlShell, shm: &WlShm,
                        seat: &WlSeat,
                        surface: WlSurface, shell_surface: WlShellSurface,
                        buffer: WlBuffer, mut event_iter: EventIterator) {
    use wayland_client::wayland::WaylandProtocolEvent;
    use wayland_client::Event;
    println!("Entering main loop");
    // For now just loop and do nothing
    // Eventually need to query the background state and update
    let cursor_surface = compositor.create_surface();
    let mut pointer = seat.get_pointer();
    let cursor_theme = load_theme(None, 16, shm);
    // TODO Figure out why not working on Timidger's machine
    let cursor = cursor_theme.get_cursor("default")
        .expect("Couldn't load cursor from theme");
    let cursor_buffer = cursor.frame_buffer(0).expect("Couldn't get frame_buffer");
    cursor_surface.attach(Some(&*cursor_buffer), 0, 0);
    pointer.set_event_iterator(&event_iter);

    pointer.set_cursor(0/*??*/, Some(&cursor_surface), 0, 0);
    loop {
        for event in &mut event_iter {
            match event {
                Event::Wayland(wayland_event) => {
                    match wayland_event {
                        WaylandProtocolEvent::WlPointer(id, pointer_event) => {
                            match pointer_event {
                                WlPointerEvent::Enter(serial, surface, surface_x, surface_y) => {
                                    // Set the surface to use a cursor
                                    pointer.set_cursor(0/*??*/, Some(&cursor_surface), 0, 0);
                                },
                                _ => {
                                }
                            }
                        },
                        _ => {/* unhandled events */}
                    }
                }
                _ => { /* unhandled events */ }
            }
        }
        event_iter.dispatch().expect("Connection with the compositor was lost.");
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut Sender<Vec<u8>>);
    fn register_stop_tx(tx: *mut Sender<()>);
}

/// Connects to the provided address, (eg "123.123.123.123:3000") and registers
/// the on data received handler
#[no_mangle]
pub extern "C" fn connect(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            println!("Invalid host address");
            return -1 as c_int;
        }
    };

    // Create and register a way to kill this client
    let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    let kill_tx = k_tx.clone();
    let mut k_tx_ptr = Box::new(k_tx);
    unsafe {
        register_stop_tx(&mut *k_tx_ptr);
    }

    // Writer thread's channel
    let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    let mut w_tx_ptr = Box::new(w_tx);
    unsafe {
        register_writer_tx(&mut *w_tx_ptr);
    }

    let result = TcpStream::connect(host_address);
    if result.is_err() {
        println!("Error connecting to {} - {}", host_address, result.unwrap_err());
        return -1 as c_int;
    }
    println!("Connected");
    on_connect_handler();

    let stream = result.unwrap();
    let client = Bstream::new(stream);

    let r_client = client.clone();
    let r_kill_tx = kill_tx.clone();

    let w_client = client.clone();
    let w_kill_tx = kill_tx.clone();

    // Start the reader thread
    thread::Builder::new()
        .name("ReaderThread".to_string())
        .spawn(move||{
            reader_thread(r_client, handler, r_kill_tx)
        }).unwrap();

    // Start the writer thread
    thread::Builder::new()
        .name("WriterThread".to_string())
        .spawn(move||{
            writer_thread(w_rx, w_client, w_kill_tx)
        }).unwrap();

    // Wait for the kill signal
    match kill_rx.recv() {
        Ok(_) => { }
        Err(e) => {
            println!("Error on kill channel: {}", e);
            return -1 as c_int;
        }
    };
    on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<commit_msg>Debugging<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str, ptr};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char};
use super::simple_stream::bstream::Bstream;

extern "C" {
    fn register_writer_tx(tx: *mut Sender<Vec<u8>>);
    fn register_stop_tx(tx: *mut Sender<()>);
}

/// Connects to the provided address, (eg "123.123.123.123:3000") and registers
/// the on data received handler
#[no_mangle]
pub extern "C" fn connect(address: *const c_char,
    handler: extern fn(*const c_char, c_int),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    println!("Rust - connect");

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            println!("Invalid host address");
            return -1 as c_int;
        }
    };

    // Create and register a way to kill this client
    let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    let kill_tx = k_tx.clone();
    let mut k_tx_ptr = Box::new(k_tx);
    unsafe {
        register_stop_tx(&mut *k_tx_ptr);
    }

    // Writer thread's channel
    let (w_tx, w_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    let mut w_tx_ptr = Box::new(w_tx);
    unsafe {
        register_writer_tx(&mut *w_tx_ptr);
    }

    println!("Attempting connect to: {}", host_address);

    let result = TcpStream::connect(host_address);
    if result.is_err() {
        println!("Error connecting to {} - {}", host_address, result.unwrap_err());
        return -1 as c_int;
    }
    println!("Connected");
    on_connect_handler();

    let stream = result.unwrap();
    let client = Bstream::new(stream);

    let r_client = client.clone();
    let r_kill_tx = kill_tx.clone();

    let w_client = client.clone();
    let w_kill_tx = kill_tx.clone();

    // Start the reader thread
    thread::Builder::new()
        .name("ReaderThread".to_string())
        .spawn(move||{
            reader_thread(r_client, handler, r_kill_tx)
        }).unwrap();

    // Start the writer thread
    thread::Builder::new()
        .name("WriterThread".to_string())
        .spawn(move||{
            writer_thread(w_rx, w_client, w_kill_tx)
        }).unwrap();

    // Wait for the kill signal
    match kill_rx.recv() {
        Ok(_) => { }
        Err(e) => {
            println!("Error on kill channel: {}", e);
            return -1 as c_int;
        }
    };
    on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn send_to_writer(w_tx: *mut Sender<Vec<u8>>,
                                 buffer: *const c_char,
                                 count: c_int,
                                 k_tx: *mut Sender<()>) -> c_int {
    if count < 1 {
        println!("Error - count must be greater than zero");
        return -1 as c_int;
    }

    let num_elts = count as usize;
    let mut n_buffer = Vec::<u8>::with_capacity(num_elts);
    for x in 0..num_elts as isize {
        unsafe {
            n_buffer.push(ptr::read(buffer.offset(x)) as u8);
        }
    }

    unsafe {
        match (*w_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                println!("Error sending buffer: {}", e);
                let _ = (*k_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream,
                 event_handler: extern fn(*const c_char, c_int),
                 kill_tx: Sender<()>) {

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        event_handler(c_buffer.as_ptr(), buffer.len() as c_int);
                    }).unwrap();
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Reader thread finished");
    let _ = kill_tx.send(());
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream, kill_tx: Sender<()>) {
    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        println!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                println!("Error: {}", e);
                break;
            }
        };
    }
    println!("Writer thread finished");
    let _ = kill_tx.send(());
}
<|endoftext|>