<commit_before>use common;
use json::iterators::Members;
use nickel::status::StatusCode;
use hyper::client::Client;
use nickel::{Request, Response, MiddlewareResult, QueryString};
use mustache::MapBuilder;
use time;
use itertools::Itertools;
use json;
use std::collections::HashSet;

pub fn arrivals_handler<'a, D>(request: &mut Request<D>,
                               mut response: Response<'a, D>)
                               -> MiddlewareResult<'a, D> {
    let client = Client::new();
    let favourites = common::favourites(&request.origin);
    let stopid = request.param("stopid").expect("Missing stopid").to_string();
    let line_filter = request.query().get("line");
    let obj =
        match common::json_for_request(
            client.get(&format!("https://api.tfl.gov.uk/StopPoint/{}/Arrivals",
                          stopid))) {
            Ok(val) => val,
            Err(val) => {
                response.set(StatusCode::BadGateway);
                return response.send(val);
            }
        };

    let members = match obj.members() {
        Members::Some(val) => val,
        Members::None => {
            response.set(StatusCode::BadGateway);
            return response.send(format!("No stops in: {:?}", obj));
        }
    };
    let member_slice = members.as_slice();
    let data = {
        if member_slice.len() == 0 {
            let stopobj = match common::json_for_request(
                client.get(&format!("https://api.tfl.gov.uk/StopPoint/{}",
                              stopid))) {
                Ok(val) => val,
                Err(val) => {
                    response.set(StatusCode::BadGateway);
                    return response.send(val);
                }
            };
            MapBuilder::new()
                .insert_str("stopName",
                            stopobj["commonName"].as_str().expect("commonName"))
                .insert_str("stopNumber", "".to_string())
                .insert_str("when", time::now().strftime("%H:%M").expect("time.now"))
                .build()
        } else {
            let last_item = member_slice[0].clone();
            let sorted_members = members.sorted_by(|a, b| {
                a["expectedArrival"].as_str().unwrap().cmp(b["expectedArrival"].as_str().unwrap())
            });
            let platform_name = last_item["platformName"].as_str().unwrap();
            let stop_number = if platform_name == "null" {
                format!(" towards {}", last_item["destinationName"].as_str().unwrap())
            } else {
                format!(" (Stop {})", platform_name)
            };

            let mut lines = HashSet::new();
            MapBuilder::new()
                .insert_vec("buses", |vecbuilder| {
                    let mut vecb = vecbuilder;
                    for stop in sorted_members.clone() {
                        let line = stop["lineName"].as_str().unwrap();
                        lines.insert(line);
                        if line_filter.is_some() && line_filter.unwrap() != line {
                            continue;
                        }
                        vecb = vecb.push_map(|mapbuilder| {
                            let when = time::strptime(stop["expectedArrival"].as_str().unwrap(),
                                                      "%FT%TZ")
                                .unwrap();
                            let until = (when - time::now()).num_minutes();
                            let until_text = if until == 1 {
                                "1 minute".to_string()
                            } else if until > 0 {
                                format!("{} minutes", until)
                            } else {
                                "due".to_string()
                            };
                            mapbuilder.insert_str("line", line)
                                .insert_str("destination",
                                            stop["destinationName"].as_str().unwrap())
                                .insert_str("towards", stop["towards"].as_str().unwrap())
                                .insert_str("minutes", until_text)
                                .insert_str("expectedArrival",
                                            when.to_local().strftime("%H:%M").unwrap())
                        });
                    }
                    vecb
                })
                .insert_vec("lines", |vecbuilder| {
                    let mut vecb = vecbuilder;
                    let mut linesv: Vec<&&str> = lines.iter().collect();
                    linesv.sort_by_key(|k| k.parse::<i32>().unwrap_or(0));
                    for line in linesv {
                        vecb = vecb.push_map(|mapbuilder| mapbuilder.insert_str("line", line))
                    }
                    vecb
                })
                .insert_str("stopId", &stopid)
                .insert_bool("inFavourites", favourites[&stopid] != json::JsonValue::Null)
                .insert_str("stopName", last_item["stationName"].as_str().unwrap())
                .insert_str("stopNumber", stop_number)
                .insert_str("when", time::now().strftime("%H:%M").unwrap())
                .build()
        }
    };

    common::render_to_response(response, "resources/templates/arrivals.mustache", &data)
}
<commit_msg>Redo Arrivals with expect not unwrap to make it easier to debug<commit_after>use common;
use json::iterators::Members;
use nickel::status::StatusCode;
use hyper::client::Client;
use nickel::{Request, Response, MiddlewareResult, QueryString};
use mustache::MapBuilder;
use time;
use itertools::Itertools;
use json;
use std::collections::HashSet;

pub fn arrivals_handler<'a, D>(request: &mut Request<D>,
                               mut response: Response<'a, D>)
                               -> MiddlewareResult<'a, D> {
    let client = Client::new();
    let favourites = common::favourites(&request.origin);
    let stopid = request.param("stopid").expect("Missing stopid").to_string();
    let line_filter = request.query().get("line");
    let obj =
        match common::json_for_request(
            client.get(&format!("https://api.tfl.gov.uk/StopPoint/{}/Arrivals",
                          stopid))) {
            Ok(val) => val,
            Err(val) => {
                response.set(StatusCode::BadGateway);
                return response.send(val);
            }
        };

    let members = match obj.members() {
        Members::Some(val) => val,
        Members::None => {
            response.set(StatusCode::BadGateway);
            return response.send(format!("No stops in: {:?}", obj));
        }
    };
    let member_slice = members.as_slice();
    let data = {
        if member_slice.len() == 0 {
            let stopobj = match common::json_for_request(
                client.get(&format!("https://api.tfl.gov.uk/StopPoint/{}",
                              stopid))) {
                Ok(val) => val,
                Err(val) => {
                    response.set(StatusCode::BadGateway);
                    return response.send(val);
                }
            };
            MapBuilder::new()
                .insert_str("stopName",
                            stopobj["commonName"].as_str().expect("commonName"))
                .insert_str("stopNumber", "".to_string())
                .insert_str("when", time::now().strftime("%H:%M").expect("time.now"))
                .build()
        } else {
            let last_item = member_slice[0].clone();
            let sorted_members = members.sorted_by(|a, b| {
                a["expectedArrival"].as_str().expect("expectedArrival a").cmp(b["expectedArrival"].as_str().expect("expectedArrival a"))
            });
            let platform_name = last_item["platformName"].as_str().expect("platformName");
            let stop_number = if platform_name == "null" {
                format!(" towards {}", last_item["destinationName"].as_str().expect("destinationName"))
            } else {
                format!(" (Stop {})", platform_name)
            };

            let mut lines = HashSet::new();
            MapBuilder::new()
                .insert_vec("buses", |vecbuilder| {
                    let mut vecb = vecbuilder;
                    for stop in sorted_members.clone() {
                        let line = stop["lineName"].as_str().expect("lineName");
                        lines.insert(line);
                        if line_filter.is_some() && line_filter.expect("line filter") != line {
                            continue;
                        }
                        vecb = vecb.push_map(|mapbuilder| {
                            let expected_arrival = stop["expectedArrival"].as_str().expect("expectedArrival");
                            let when = time::strptime(expected_arrival, "%FT%TZ")
                                .expect(&format!("strptime: {}", expected_arrival));
                            let until = (when - time::now()).num_minutes();
                            let until_text = if until == 1 {
                                "1 minute".to_string()
                            } else if until > 0 {
                                format!("{} minutes", until)
                            } else {
                                "due".to_string()
                            };
                            mapbuilder.insert_str("line", line)
                                .insert_str("destination",
                                            stop["destinationName"].as_str().expect("destinationName"))
                                .insert_str("towards", stop["towards"].as_str().expect("towards"))
                                .insert_str("minutes", until_text)
                                .insert_str("expectedArrival",
                                            when.to_local().strftime("%H:%M").expect("when"))
                        });
                    }
                    vecb
                })
                .insert_vec("lines", |vecbuilder| {
                    let mut vecb = vecbuilder;
                    let mut linesv: Vec<&&str> = lines.iter().collect();
                    linesv.sort_by_key(|k| k.parse::<i32>().unwrap_or(0));
                    for line in linesv {
                        vecb = vecb.push_map(|mapbuilder| mapbuilder.insert_str("line", line))
                    }
                    vecb
                })
                .insert_str("stopId", &stopid)
                .insert_bool("inFavourites", favourites[&stopid] != json::JsonValue::Null)
                .insert_str("stopName", last_item["stationName"].as_str().expect("stationName"))
                .insert_str("stopNumber", stop_number)
                .insert_str("when", time::now().strftime("%H:%M").expect("time now"))
                .build()
        }
    };

    common::render_to_response(response, "resources/templates/arrivals.mustache", &data)
}
<|endoftext|>


<commit_before>
use std::marker::PhantomData;
use gfx;
use gfx::traits::*;
use graphics::{ Context, DrawState, Graphics };
use graphics::BACK_END_MAX_VERTEX_COUNT as BUFFER_SIZE;

use Texture;

static VERTEX_SHADER: [&'static [u8]; 2] = [
b"#version 120
uniform vec4 color;

attribute vec2 pos;

void main() {
    gl_Position = vec4(pos, 0.0, 1.0);
}
",
b"#version 150 core
uniform vec4 color;

in vec2 pos;

void main() {
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
];

static FRAGMENT_SHADER: [&'static [u8]; 2] = [
b"#version 120
uniform vec4 color;

void main() {
    gl_FragColor = color;
}
",
b"#version 150 core
uniform vec4 color;

out vec4 o_Color;

void main() {
    o_Color = color;
}
"
];

static VERTEX_SHADER_UV: [&'static [u8]; 2] = [
b"#version 120
uniform sampler2D s_texture;
uniform vec4 color;

attribute vec2 pos;
attribute vec2 uv;

varying vec2 v_UV;

void main() {
    v_UV = uv;
    gl_Position = vec4(pos, 0.0, 1.0);
}
",
b"#version 150 core
uniform sampler2D s_texture;
uniform vec4 color;

in vec2 pos;
in vec2 uv;
out vec2 v_UV;
void main() {
    v_UV = uv;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
];

static FRAGMENT_SHADER_UV: [&'static [u8]; 2] = [
b"#version 120
uniform sampler2D s_texture;
uniform vec4 color;

varying vec2 v_UV;

void main()
{
    gl_FragColor = texture2D(s_texture, v_UV) * color;
}
",
b"#version 150 core
uniform sampler2D s_texture;
uniform vec4 color;

out vec4 o_Color;

in vec2 v_UV;

void main()
{
    o_Color = texture(s_texture, v_UV) * color;
}
"
];

static POS_COMPONENTS: usize = 2;
static UV_COMPONENTS: usize = 2;

// Boiler plate for automatic attribute construction.
// Needs to be improved on gfx-rs side.
// For some reason, using ``*_COMPONENT` triggers some macros errors.

#[vertex_format]
struct PositionFormat { pos: [f32; 2] }

#[vertex_format]
struct ColorFormat { color: [f32; 4] }

#[vertex_format]
struct TexCoordsFormat { uv: [f32; 2] }

#[shader_param]
struct Params<R: gfx::Resources> {
    color: [f32; 4],
    _dummy: PhantomData<R>,
}

#[shader_param]
struct ParamsUV<R: gfx::Resources> {
    color: [f32; 4],
    s_texture: gfx::shade::TextureParam<R>,
}

/// The data used for drawing 2D graphics.
pub struct Gfx2d<D: gfx::Device> {
    buffer_pos: gfx::BufferHandle<D::Resources, f32>,
    buffer_uv: gfx::BufferHandle<D::Resources, f32>,
    batch: gfx::batch::OwnedBatch<Params<D::Resources>>,
    batch_uv: gfx::batch::OwnedBatch<ParamsUV<D::Resources>>,
}

impl<D: gfx::Device> Gfx2d<D> {
    /// Creates a new G2D object.
    pub fn new(device: &mut D) -> Gfx2d<D> {
        let shader_model = device.get_capabilities().shader_model;

        let vertex = gfx::ShaderSource {
            glsl_120: Some(VERTEX_SHADER[0]),
            glsl_150: Some(VERTEX_SHADER[1]),
            .. gfx::ShaderSource::empty()
        };
        let fragment = gfx::ShaderSource {
            glsl_120: Some(FRAGMENT_SHADER[0]),
            glsl_150: Some(FRAGMENT_SHADER[1]),
            .. gfx::ShaderSource::empty()
        };

        let program = device.link_program(
            vertex.choose(shader_model).unwrap(),
            fragment.choose(shader_model).unwrap())
            .unwrap();

        let vertex = gfx::ShaderSource {
            glsl_120: Some(VERTEX_SHADER_UV[0]),
            glsl_150: Some(VERTEX_SHADER_UV[1]),
            .. gfx::ShaderSource::empty()
        };
        let fragment = gfx::ShaderSource {
            glsl_120: Some(FRAGMENT_SHADER_UV[0]),
            glsl_150: Some(FRAGMENT_SHADER_UV[1]),
            .. gfx::ShaderSource::empty()
        };

        let program_uv = device.link_program(
            vertex.choose(shader_model).unwrap(),
            fragment.choose(shader_model).unwrap())
            .unwrap();

        let buffer_pos = device.create_buffer(
            POS_COMPONENTS * BUFFER_SIZE,
            gfx::BufferUsage::Dynamic);
        let buffer_uv = device.create_buffer(
            UV_COMPONENTS * BUFFER_SIZE,
            gfx::BufferUsage::Dynamic);

        let mut mesh = gfx::Mesh::new(BUFFER_SIZE as u32);
        mesh.attributes.extend(gfx::VertexFormat::generate(
            None::<&PositionFormat>,
            buffer_pos.raw()
        ).into_iter());

        // Reuse parameters from `mesh`.
        let mut mesh_uv = mesh.clone();
        mesh_uv.attributes.extend(gfx::VertexFormat::generate(
            None::<&TexCoordsFormat>,
            buffer_uv.raw()
        ).into_iter());

        let params = Params {
            color: [1.0; 4],
            _dummy: PhantomData,
        };
        let mut batch = gfx::batch::OwnedBatch::new(mesh, program, params)
            .unwrap();

        let sampler = device.create_sampler(
            gfx::tex::SamplerInfo::new(
                gfx::tex::FilterMethod::Trilinear,
                gfx::tex::WrapMode::Clamp)
        );

        // Create a dummy texture
        let texture_info = gfx::tex::TextureInfo {
            width: 1,
            height: 1,
            depth: 1,
            levels: 1,
            kind: gfx::tex::TextureKind::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info)
            .unwrap();
        device.update_texture(&texture, &image_info,
                &[0x20u8, 0xA0u8, 0xC0u8, 0x00u8])
            .unwrap();
        let params_uv = ParamsUV {
            color: [1.0; 4],
            s_texture: (texture, Some(sampler))
        };
        let mut batch_uv = gfx::batch::OwnedBatch::new(
            mesh_uv, program_uv, params_uv)
            .unwrap();

        // Disable culling.
        batch.state.primitive.method =
            gfx::state::RasterMethod::Fill(gfx::state::CullFace::Nothing);
        batch_uv.state.primitive.method =
            gfx::state::RasterMethod::Fill(gfx::state::CullFace::Nothing);

        Gfx2d {
            buffer_pos: buffer_pos,
            buffer_uv: buffer_uv,
            batch: batch,
            batch_uv: batch_uv,
        }
    }

    /// Renders graphics to a Gfx renderer.
    pub fn draw<F: FnMut(Context, &mut GfxGraphics<D>)>(
        &mut self,
        renderer: &mut gfx::Renderer<D::Resources, D::CommandBuffer>,
        frame: &gfx::Frame<D::Resources>,
        mut f: F
    ) {
        let ref mut g = GfxGraphics::new(
            renderer,
            frame,
            self
        );
        let c = Context::abs(
            frame.width as f64,
            frame.height as f64
        );
        f(c, g);
    }
}

/// Used for rendering 2D graphics.
pub struct GfxGraphics<'a, D>
    where
        D: 'a + gfx::Device,
        <D as gfx::Device>::CommandBuffer: 'a,
        <D as gfx::Device>::Resources: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Sampler: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Texture: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Surface: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::FrameBuffer: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Program: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Shader: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::ArrayBuffer: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Buffer: 'a
{
    renderer: &'a mut gfx::Renderer<D::Resources, D::CommandBuffer>,
    frame: &'a gfx::Frame<D::Resources>,
    g2d: &'a mut Gfx2d<D>,
}

impl<'a, D: gfx::Device> GfxGraphics<'a, D> {
    /// Creates a new object for rendering 2D graphics.
    pub fn new(renderer: &'a mut gfx::Renderer<D::Resources, D::CommandBuffer>,
               frame: &'a gfx::Frame<D::Resources>,
               g2d: &'a mut Gfx2d<D>) -> GfxGraphics<'a, D> {
        GfxGraphics {
            renderer: renderer,
            frame: frame,
            g2d: g2d,
        }
    }

    /// Returns true if texture has alpha channel.
    pub fn has_texture_alpha(&self, texture: &Texture<D>) -> bool {
        use gfx::tex::Components::RGBA;

        texture.handle.get_info().format.get_components() == Some(RGBA)
    }
}

impl<'a, D: gfx::Device> Graphics
for GfxGraphics<'a, D>
    where
        D::Resources: 'a,
{
    type Texture = Texture<D::Resources>;

    fn clear(&mut self, color: [f32; 4]) {
        let &mut GfxGraphics {
            ref mut renderer,
            frame,
            ..
        } = self;
        renderer.clear(
                gfx::ClearData {
                    color: color,
                    depth: 0.0,
                    stencil: 0,
                },
                gfx::COLOR,
                frame
            );
    }

    fn tri_list<F>(
        &mut self,
        draw_state: &DrawState,
        color: &[f32; 4],
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32]))
    {
        let &mut GfxGraphics {
            ref mut renderer,
            ref frame,
            g2d: &mut Gfx2d {
                ref mut buffer_pos,
                ref mut batch,
                ..
            },
        } = self;

        batch.state = *draw_state;
        batch.param.color = *color;

        f(&mut |vertices: &[f32]| {
            renderer.update_buffer_vec(buffer_pos.clone(), vertices, 0);

            let n = vertices.len() / POS_COMPONENTS;
            batch.slice = gfx::Slice {
                    prim_type: gfx::PrimitiveType::TriangleList,
                    start: 0,
                    end: n as u32,
                    kind: gfx::SliceKind::Vertex
                };
            let _ = renderer.draw(batch, *frame);
        })
    }

    fn tri_list_uv<F>(
        &mut self,
        draw_state: &DrawState,
        color: &[f32; 4],
        texture: &<Self as Graphics>::Texture,
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32], &[f32]))
    {
        let &mut GfxGraphics {
            ref mut renderer,
            ref frame,
            g2d: &mut Gfx2d {
                ref mut buffer_pos,
                ref mut buffer_uv,
                ref mut batch_uv,
                ..
            },
        } = self;

        batch_uv.state = *draw_state;
        batch_uv.param.s_texture.0 = texture.handle;
        batch_uv.param.color = *color;

        f(&mut |vertices: &[f32], texture_coords: &[f32]| {
            assert_eq!(
                vertices.len() * UV_COMPONENTS,
                texture_coords.len() * POS_COMPONENTS
            );
            renderer.update_buffer_vec(buffer_pos.clone(), vertices, 0);
            renderer.update_buffer_vec(buffer_uv.clone(), texture_coords, 0);

            let n = vertices.len() / POS_COMPONENTS;
            batch_uv.slice = gfx::Slice {
                    prim_type: gfx::PrimitiveType::TriangleList,
                    start: 0,
                    end: n as u32,
                    kind: gfx::SliceKind::Vertex
                };
            let _ = renderer.draw(batch_uv, *frame);
        })
    }
}
<commit_msg>A bit closer to latest Gfx<commit_after>
use std::marker::PhantomData;
use gfx;
use gfx::traits::*;
use graphics::{ Context, DrawState, Graphics };
use graphics::BACK_END_MAX_VERTEX_COUNT as BUFFER_SIZE;

use Texture;

static VERTEX_SHADER: [&'static [u8]; 2] = [
b"#version 120
uniform vec4 color;

attribute vec2 pos;

void main() {
    gl_Position = vec4(pos, 0.0, 1.0);
}
",
b"#version 150 core
uniform vec4 color;

in vec2 pos;

void main() {
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
];

static FRAGMENT_SHADER: [&'static [u8]; 2] = [
b"#version 120
uniform vec4 color;

void main() {
    gl_FragColor = color;
}
",
b"#version 150 core
uniform vec4 color;

out vec4 o_Color;

void main() {
    o_Color = color;
}
"
];

static VERTEX_SHADER_UV: [&'static [u8]; 2] = [
b"#version 120
uniform sampler2D s_texture;
uniform vec4 color;

attribute vec2 pos;
attribute vec2 uv;

varying vec2 v_UV;

void main() {
    v_UV = uv;
    gl_Position = vec4(pos, 0.0, 1.0);
}
",
b"#version 150 core
uniform sampler2D s_texture;
uniform vec4 color;

in vec2 pos;
in vec2 uv;
out vec2 v_UV;
void main() {
    v_UV = uv;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
];

static FRAGMENT_SHADER_UV: [&'static [u8]; 2] = [
b"#version 120
uniform sampler2D s_texture;
uniform vec4 color;

varying vec2 v_UV;

void main()
{
    gl_FragColor = texture2D(s_texture, v_UV) * color;
}
",
b"#version 150 core
uniform sampler2D s_texture;
uniform vec4 color;

out vec4 o_Color;

in vec2 v_UV;

void main()
{
    o_Color = texture(s_texture, v_UV) * color;
}
"
];

static POS_COMPONENTS: usize = 2;
static UV_COMPONENTS: usize = 2;

// Boiler plate for automatic attribute construction.
// Needs to be improved on gfx-rs side.
// For some reason, using ``*_COMPONENT` triggers some macros errors.

#[vertex_format]
struct PositionFormat { pos: [f32; 2] }

#[vertex_format]
struct ColorFormat { color: [f32; 4] }

#[vertex_format]
struct TexCoordsFormat { uv: [f32; 2] }

#[shader_param]
struct Params<R: gfx::Resources> {
    color: [f32; 4],
    _dummy: PhantomData<R>,
}

#[shader_param]
struct ParamsUV<R: gfx::Resources> {
    color: [f32; 4],
    s_texture: gfx::shade::TextureParam<R>,
}

/// The data used for drawing 2D graphics.
pub struct Gfx2d<D: gfx::Device> {
    buffer_pos: gfx::BufferHandle<D::Resources, f32>,
    buffer_uv: gfx::BufferHandle<D::Resources, f32>,
    batch: gfx::batch::OwnedBatch<Params<D::Resources>>,
    batch_uv: gfx::batch::OwnedBatch<ParamsUV<D::Resources>>,
}

impl<D: gfx::Device> Gfx2d<D> {
    /// Creates a new G2D object.
    pub fn new(device: &mut D) -> Gfx2d<D> {
        let shader_model = device.get_capabilities().shader_model;

        let vertex = gfx::ShaderSource {
            glsl_120: Some(VERTEX_SHADER[0]),
            glsl_150: Some(VERTEX_SHADER[1]),
            .. gfx::ShaderSource::empty()
        };
        let fragment = gfx::ShaderSource {
            glsl_120: Some(FRAGMENT_SHADER[0]),
            glsl_150: Some(FRAGMENT_SHADER[1]),
            .. gfx::ShaderSource::empty()
        };

        let program = device.link_program(
            vertex.choose(shader_model).unwrap(),
            fragment.choose(shader_model).unwrap())
            .unwrap();

        let vertex = gfx::ShaderSource {
            glsl_120: Some(VERTEX_SHADER_UV[0]),
            glsl_150: Some(VERTEX_SHADER_UV[1]),
            .. gfx::ShaderSource::empty()
        };
        let fragment = gfx::ShaderSource {
            glsl_120: Some(FRAGMENT_SHADER_UV[0]),
            glsl_150: Some(FRAGMENT_SHADER_UV[1]),
            .. gfx::ShaderSource::empty()
        };

        let program_uv = device.link_program(
            vertex.choose(shader_model).unwrap(),
            fragment.choose(shader_model).unwrap())
            .unwrap();

        let buffer_pos = device.create_buffer(
            POS_COMPONENTS * BUFFER_SIZE,
            gfx::BufferUsage::Dynamic);
        let buffer_uv = device.create_buffer(
            UV_COMPONENTS * BUFFER_SIZE,
            gfx::BufferUsage::Dynamic);

        let mut mesh = gfx::Mesh::new(BUFFER_SIZE as u32);
        mesh.attributes.extend(gfx::VertexFormat::generate(
            None::<&PositionFormat>,
            buffer_pos.raw()
        ).into_iter());

        // Reuse parameters from `mesh`.
        let mut mesh_uv = mesh.clone();
        mesh_uv.attributes.extend(gfx::VertexFormat::generate(
            None::<&TexCoordsFormat>,
            buffer_uv.raw()
        ).into_iter());

        let params = Params {
            color: [1.0; 4],
            _dummy: PhantomData,
        };
        let mut batch = gfx::batch::OwnedBatch::new(mesh, program, params)
            .unwrap();

        let sampler = device.create_sampler(
            gfx::tex::SamplerInfo::new(
                gfx::tex::FilterMethod::Trilinear,
                gfx::tex::WrapMode::Clamp)
        );

        // Create a dummy texture
        let texture_info = gfx::tex::TextureInfo {
            width: 1,
            height: 1,
            depth: 1,
            levels: 1,
            kind: gfx::tex::TextureKind::Texture2D,
            format: gfx::tex::RGBA8,
        };
        let image_info = texture_info.to_image_info();
        let texture = device.create_texture(texture_info)
            .unwrap();
        device.update_texture(&texture, &image_info,
                &[0x20u8, 0xA0u8, 0xC0u8, 0x00u8])
            .unwrap();
        let params_uv = ParamsUV {
            color: [1.0; 4],
            s_texture: (texture, Some(sampler))
        };
        let mut batch_uv = gfx::batch::OwnedBatch::new(
            mesh_uv, program_uv, params_uv)
            .unwrap();

        // Disable culling.
        batch.state.primitive.method =
            gfx::state::RasterMethod::Fill(gfx::state::CullFace::Nothing);
        batch_uv.state.primitive.method =
            gfx::state::RasterMethod::Fill(gfx::state::CullFace::Nothing);

        Gfx2d {
            buffer_pos: buffer_pos,
            buffer_uv: buffer_uv,
            batch: batch,
            batch_uv: batch_uv,
        }
    }

    /// Renders graphics to a Gfx renderer.
    pub fn draw<F: FnMut(Context, &mut GfxGraphics<D>)>(
        &mut self,
        renderer: &mut gfx::Renderer<D::Resources, D::CommandBuffer>,
        frame: &gfx::Frame<D::Resources>,
        mut f: F
    ) {
        let ref mut g = GfxGraphics::new(
            renderer,
            frame,
            self
        );
        let c = Context::abs(
            frame.width as f64,
            frame.height as f64
        );
        f(c, g);
    }
}

/// Used for rendering 2D graphics.
pub struct GfxGraphics<'a, D>
    where
        D: 'a + gfx::Device,
        <D as gfx::Device>::CommandBuffer: 'a,
        <D as gfx::Device>::Resources: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Sampler: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Texture: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Surface: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::FrameBuffer: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Program: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Shader: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::ArrayBuffer: 'a,
        <<D as gfx::device::Device>::Resources as gfx::device::Resources>::Buffer: 'a
{
    renderer: &'a mut gfx::Renderer<D::Resources, D::CommandBuffer>,
    frame: &'a gfx::Frame<D::Resources>,
    g2d: &'a mut Gfx2d<D>,
}

impl<'a, D: gfx::Device> GfxGraphics<'a, D> {
    /// Creates a new object for rendering 2D graphics.
    pub fn new(renderer: &'a mut gfx::Renderer<D::Resources, D::CommandBuffer>,
               frame: &'a gfx::Frame<D::Resources>,
               g2d: &'a mut Gfx2d<D>) -> GfxGraphics<'a, D> {
        GfxGraphics {
            renderer: renderer,
            frame: frame,
            g2d: g2d,
        }
    }

    /// Returns true if texture has alpha channel.
    pub fn has_texture_alpha(&self, texture: &Texture<D::Resources>) -> bool {
        use gfx::tex::Components::RGBA;

        texture.handle.get_info().format.get_components() == Some(RGBA)
    }
}

impl<'a, D: gfx::Device> Graphics
for GfxGraphics<'a, D>
    where
        D::Resources: 'a,
        <D as gfx::device::Device>::CommandBuffer: 'a,
{
    type Texture = Texture<D::Resources>;

    fn clear(&mut self, color: [f32; 4]) {
        let &mut GfxGraphics {
            ref mut renderer,
            frame,
            ..
        } = self;
        renderer.clear(
                gfx::ClearData {
                    color: color,
                    depth: 0.0,
                    stencil: 0,
                },
                gfx::COLOR,
                frame
            );
    }

    fn tri_list<F>(
        &mut self,
        draw_state: &DrawState,
        color: &[f32; 4],
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32]))
    {
        let &mut GfxGraphics {
            ref mut renderer,
            ref frame,
            g2d: &mut Gfx2d {
                ref mut buffer_pos,
                ref mut batch,
                ..
            },
        } = self;

        batch.state = *draw_state;
        batch.param.color = *color;

        f(&mut |vertices: &[f32]| {
            renderer.update_buffer_vec(&buffer_pos, vertices, 0);

            let n = vertices.len() / POS_COMPONENTS;
            batch.slice = gfx::Slice {
                    prim_type: gfx::PrimitiveType::TriangleList,
                    start: 0,
                    end: n as u32,
                    kind: gfx::SliceKind::Vertex
                };
            let _ = renderer.draw(batch, *frame);
        })
    }

    fn tri_list_uv<F>(
        &mut self,
        draw_state: &DrawState,
        color: &[f32; 4],
        texture: &<Self as Graphics>::Texture,
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32], &[f32]))
    {
        let &mut GfxGraphics {
            ref mut renderer,
            ref frame,
            g2d: &mut Gfx2d {
                ref mut buffer_pos,
                ref mut buffer_uv,
                ref mut batch_uv,
                ..
            },
        } = self;

        batch_uv.state = *draw_state;
        batch_uv.param.s_texture.0 = texture.handle;
        batch_uv.param.color = *color;

        f(&mut |vertices: &[f32], texture_coords: &[f32]| {
            assert_eq!(
                vertices.len() * UV_COMPONENTS,
                texture_coords.len() * POS_COMPONENTS
            );
            renderer.update_buffer_vec(&buffer_pos, vertices, 0);
            renderer.update_buffer_vec(&buffer_uv, texture_coords, 0);

            let n = vertices.len() / POS_COMPONENTS;
            batch_uv.slice = gfx::Slice {
                    prim_type: gfx::PrimitiveType::TriangleList,
                    start: 0,
                    end: n as u32,
                    kind: gfx::SliceKind::Vertex
                };
            let _ = renderer.draw(batch_uv, *frame);
        })
    }
}
<|endoftext|>


<commit_before>extern crate portaudio;

static SECONDS: uint = 1;

fn main()
{
    portaudio::pa::initialize().unwrap();
    print_devs();
    println!("{}", demo());
    portaudio::pa::terminate().unwrap();
}

fn print_devs()
{
    for i in range(0, portaudio::device::get_count().unwrap())
    {
        match portaudio::device::get_info(i)
        {
            None => {},
            Some(info) => println!("{}: {}", i, info.name),
        }
    }
}

fn demo() -> portaudio::pa::PaResult
{
    let stream = try!(portaudio::stream::Stream::open_default(1, 1, 44100.0, portaudio::stream::FRAMES_PER_BUFFER_UNSPECIFIED, None));

    try!(stream.start());

    let input = try!(stream.read(44100));

    let mut phase = 0.0f32;
    let mut buffer = Vec::with_capacity(44100 * SECONDS);
    for _i in range(0u, 44100 * SECONDS)
    {
        buffer.push(phase);

        phase += 0.007;
        if phase > 1.0 { phase -= 2.0; }
    }

    let mut timer = match std::io::timer::Timer::new()
    {
        Err(e) => { panic!("{}", e); },
        Ok(t) => t,
    };
    let waiter = timer.oneshot(std::time::duration::Duration::seconds(SECONDS as i64));

    match stream.write(buffer.as_slice())
    {
        Err(e) => { println!("write 1: Err({})", e); },
        Ok(()) => {},
    }

    match stream.write(input.as_slice())
    {
        Err(e) => { println!("write 2: Err({})", e); },
        Ok(()) => {},
    }

    waiter.recv();

    Ok(())
}
<commit_msg>Ignore waiter result<commit_after>extern crate portaudio;

static SECONDS: uint = 1;

fn main()
{
    portaudio::pa::initialize().unwrap();
    print_devs();
    println!("{}", demo());
    portaudio::pa::terminate().unwrap();
}

fn print_devs()
{
    for i in range(0, portaudio::device::get_count().unwrap())
    {
        match portaudio::device::get_info(i)
        {
            None => {},
            Some(info) => println!("{}: {}", i, info.name),
        }
    }
}

fn demo() -> portaudio::pa::PaResult
{
    let stream = try!(portaudio::stream::Stream::open_default(1, 1, 44100.0, portaudio::stream::FRAMES_PER_BUFFER_UNSPECIFIED, None));

    try!(stream.start());

    let input = try!(stream.read(44100));

    let mut phase = 0.0f32;
    let mut buffer = Vec::with_capacity(44100 * SECONDS);
    for _i in range(0u, 44100 * SECONDS)
    {
        buffer.push(phase);

        phase += 0.007;
        if phase > 1.0 { phase -= 2.0; }
    }

    let mut timer = match std::io::timer::Timer::new()
    {
        Err(e) => { panic!("{}", e); },
        Ok(t) => t,
    };
    let waiter = timer.oneshot(std::time::duration::Duration::seconds(SECONDS as i64));

    match stream.write(buffer.as_slice())
    {
        Err(e) => { println!("write 1: Err({})", e); },
        Ok(()) => {},
    }

    match stream.write(input.as_slice())
    {
        Err(e) => { println!("write 2: Err({})", e); },
        Ok(()) => {},
    }

    let _ = waiter.recv();

    Ok(())
}
<|endoftext|>


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

//! Main for building the binary of a Grin peer-to-peer node.

#[macro_use]
extern crate clap;

#[macro_use]
extern crate log;
use crate::config::config::SERVER_CONFIG_FILE_NAME;
use crate::core::global;
use crate::util::init_logger;
use clap::App;
use grin_api as api;
use grin_config as config;
use grin_core as core;
use grin_p2p as p2p;
use grin_servers as servers;
use grin_util as util;

mod cmd;
pub mod tui;

// include build information
pub mod built_info {
	include!(concat!(env!("OUT_DIR"), "/built.rs"));
}

pub fn info_strings() -> (String, String) {
	(
		format!(
			"This is Grin version {}{}, built for {} by {}.",
			built_info::PKG_VERSION,
			built_info::GIT_VERSION.map_or_else(|| "".to_owned(), |v| format!(" (git {})", v)),
			built_info::TARGET,
			built_info::RUSTC_VERSION,
		)
		.to_string(),
		format!(
			"Built with profile \"{}\", features \"{}\".",
			built_info::PROFILE,
			built_info::FEATURES_STR,
		)
		.to_string(),
	)
}

fn log_build_info() {
	let (basic_info, detailed_info) = info_strings();
	info!("{}", basic_info);
	debug!("{}", detailed_info);
}

fn main() {
	let exit_code = real_main();
	std::process::exit(exit_code);
}

fn real_main() -> i32 {
	let yml = load_yaml!("grin.yml");
	let args = App::from_yaml(yml).get_matches();
	let node_config;

	// Temporary wallet warning message
	match args.subcommand() {
		("wallet", _) => {
			println!();
			println!("As of v1.1.0, the wallet has been split into a seperate executable.");
			println!(
				"Please visit https://github.com/mimblewinble/grin-wallet/releases to download"
			);
			println!();
			return 0;
		}
		_ => {}
	}

	let chain_type = if args.is_present("floonet") {
		global::ChainTypes::Floonet
	} else if args.is_present("usernet") {
		global::ChainTypes::UserTesting
	} else {
		global::ChainTypes::Mainnet
	};

	// Deal with configuration file creation
	match args.subcommand() {
		("server", Some(server_args)) => {
			// If it's just a server config command, do it and exit
			if let ("config", Some(_)) = server_args.subcommand() {
				cmd::config_command_server(&chain_type, SERVER_CONFIG_FILE_NAME);
				return 0;
			}
		}
		_ => {}
	}

	// Load relevant config
	match args.subcommand() {
		// When the subscommand is 'server' take into account the 'config_file' flag
		("server", Some(server_args)) => {
			if let Some(_path) = server_args.value_of("config_file") {
				node_config = Some(config::GlobalConfig::new(_path).unwrap_or_else(|e| {
					panic!("Error loading server configuration: {}", e);
				}));
			} else {
				node_config = Some(
					config::initial_setup_server(&chain_type).unwrap_or_else(|e| {
						panic!("Error loading server configuration: {}", e);
					}),
				);
			}
		}
		// Otherwise load up the node config as usual
		_ => {
			node_config = Some(
				config::initial_setup_server(&chain_type).unwrap_or_else(|e| {
					panic!("Error loading server configuration: {}", e);
				}),
			);
		}
	}

	if let Some(mut config) = node_config.clone() {
		let mut l = config.members.as_mut().unwrap().logging.clone().unwrap();
		let run_tui = config.members.as_mut().unwrap().server.run_tui;
		if let Some(true) = run_tui {
			l.log_to_stdout = false;
			l.tui_running = Some(true);
		}
		init_logger(Some(l));

		global::set_mining_mode(config.members.unwrap().server.clone().chain_type);

		if let Some(file_path) = &config.config_file_path {
			info!(
				"Using configuration file at {}",
				file_path.to_str().unwrap()
			);
		} else {
			info!("Node configuration file not found, using default");
		}
	}

	log_build_info();

	// Execute subcommand
	match args.subcommand() {
		// server commands and options
		("server", Some(server_args)) => {
			cmd::server_command(Some(server_args), node_config.unwrap())
		}

		// client commands and options
		("client", Some(client_args)) => cmd::client_command(client_args, node_config.unwrap()),

		// If nothing is specified, try to just use the config file instead
		// this could possibly become the way to configure most things
		// with most command line options being phased out
		_ => cmd::server_command(None, node_config.unwrap()),
	}
}
<commit_msg>fix typo (#2802)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Main for building the binary of a Grin peer-to-peer node.

#[macro_use]
extern crate clap;

#[macro_use]
extern crate log;
use crate::config::config::SERVER_CONFIG_FILE_NAME;
use crate::core::global;
use crate::util::init_logger;
use clap::App;
use grin_api as api;
use grin_config as config;
use grin_core as core;
use grin_p2p as p2p;
use grin_servers as servers;
use grin_util as util;

mod cmd;
pub mod tui;

// include build information
pub mod built_info {
	include!(concat!(env!("OUT_DIR"), "/built.rs"));
}

pub fn info_strings() -> (String, String) {
	(
		format!(
			"This is Grin version {}{}, built for {} by {}.",
			built_info::PKG_VERSION,
			built_info::GIT_VERSION.map_or_else(|| "".to_owned(), |v| format!(" (git {})", v)),
			built_info::TARGET,
			built_info::RUSTC_VERSION,
		)
		.to_string(),
		format!(
			"Built with profile \"{}\", features \"{}\".",
			built_info::PROFILE,
			built_info::FEATURES_STR,
		)
		.to_string(),
	)
}

fn log_build_info() {
	let (basic_info, detailed_info) = info_strings();
	info!("{}", basic_info);
	debug!("{}", detailed_info);
}

fn main() {
	let exit_code = real_main();
	std::process::exit(exit_code);
}

fn real_main() -> i32 {
	let yml = load_yaml!("grin.yml");
	let args = App::from_yaml(yml).get_matches();
	let node_config;

	// Temporary wallet warning message
	match args.subcommand() {
		("wallet", _) => {
			println!();
			println!("As of v1.1.0, the wallet has been split into a seperate executable.");
			println!(
				"Please visit https://github.com/mimblewimble/grin-wallet/releases to download"
			);
			println!();
			return 0;
		}
		_ => {}
	}

	let chain_type = if args.is_present("floonet") {
		global::ChainTypes::Floonet
	} else if args.is_present("usernet") {
		global::ChainTypes::UserTesting
	} else {
		global::ChainTypes::Mainnet
	};

	// Deal with configuration file creation
	match args.subcommand() {
		("server", Some(server_args)) => {
			// If it's just a server config command, do it and exit
			if let ("config", Some(_)) = server_args.subcommand() {
				cmd::config_command_server(&chain_type, SERVER_CONFIG_FILE_NAME);
				return 0;
			}
		}
		_ => {}
	}

	// Load relevant config
	match args.subcommand() {
		// When the subscommand is 'server' take into account the 'config_file' flag
		("server", Some(server_args)) => {
			if let Some(_path) = server_args.value_of("config_file") {
				node_config = Some(config::GlobalConfig::new(_path).unwrap_or_else(|e| {
					panic!("Error loading server configuration: {}", e);
				}));
			} else {
				node_config = Some(
					config::initial_setup_server(&chain_type).unwrap_or_else(|e| {
						panic!("Error loading server configuration: {}", e);
					}),
				);
			}
		}
		// Otherwise load up the node config as usual
		_ => {
			node_config = Some(
				config::initial_setup_server(&chain_type).unwrap_or_else(|e| {
					panic!("Error loading server configuration: {}", e);
				}),
			);
		}
	}

	if let Some(mut config) = node_config.clone() {
		let mut l = config.members.as_mut().unwrap().logging.clone().unwrap();
		let run_tui = config.members.as_mut().unwrap().server.run_tui;
		if let Some(true) = run_tui {
			l.log_to_stdout = false;
			l.tui_running = Some(true);
		}
		init_logger(Some(l));

		global::set_mining_mode(config.members.unwrap().server.clone().chain_type);

		if let Some(file_path) = &config.config_file_path {
			info!(
				"Using configuration file at {}",
				file_path.to_str().unwrap()
			);
		} else {
			info!("Node configuration file not found, using default");
		}
	}

	log_build_info();

	// Execute subcommand
	match args.subcommand() {
		// server commands and options
		("server", Some(server_args)) => {
			cmd::server_command(Some(server_args), node_config.unwrap())
		}

		// client commands and options
		("client", Some(client_args)) => cmd::client_command(client_args, node_config.unwrap()),

		// If nothing is specified, try to just use the config file instead
		// this could possibly become the way to configure most things
		// with most command line options being phased out
		_ => cmd::server_command(None, node_config.unwrap()),
	}
}
<|endoftext|>


<commit_before>#![deny(warnings)]

// TODO support reading from standard input

extern crate coreutils;
extern crate termion;

use std::env::args;
use std::fs::File;
use std::io::{self, Write, Read, StdoutLock, Stderr};
use std::path::Path;

use coreutils::extra::OptionalExt;

use termion::{terminal_size, TermRead, TermWrite, IntoRawMode, Color, Key, RawTerminal};

static LONG_HELP: &'static str = r#"
    NAME
        less - view a text file.
    SYNOPSIS
        less [-h | --help] [input]
    DESCRIPTION
        This utility views text files. If no input file is specified as an argument, standard input is used.
    OPTIONS
        --help, -h
            Print this manual page.
    AUTHOR
        This program was written by MovingtoMars for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 MovingtoMars

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

fn main() {
    let mut args = args().skip(1);
    let mut stdout = io::stdout().lock();
    let mut stdin = io::stdin().lock();
    let mut stderr = io::stderr();

    if let Some(x) = args.next() {
        match x.as_str() {
            "--help" | "-h" => {
                // Print help.
                stdout.write(LONG_HELP.as_bytes()).try(&mut stderr);
                return;
            },
            filename => {
                let mut file = File::open(Path::new(filename)).try(&mut stderr);
                run(&mut file, &mut stdin, &mut stdout, &mut stderr);
            }
        }

        if let Some(x) = args.next() {
            let mut file = File::open(Path::new(x.as_str())).try(&mut stderr);
            run(&mut file, &mut stdin, &mut stdout, &mut stderr);
        }
    } else {
        writeln!(stderr, "Readin from stdin is not yet supported").try(&mut stderr);
        //run(&mut stdin, &mut stdin, &mut stdout, &mut stderr);
    };
}

struct Buffer {
    lines: Vec<String>,
    y_off: u16,
}

impl Buffer {
    fn new() -> Buffer {
        Buffer{
            lines: Vec::new(),
            y_off: 0,
        }
    }

    fn read(&mut self, from: &mut Read) -> std::io::Result<usize> {
        let mut tmp = String::new();
        let res = from.read_to_string(&mut tmp);
        try!(res);

        self.lines.append(&mut tmp
            .as_str()
            .split("\n")
            .map(|x| {String::from(x)})
            .collect());

        return res;
    }

    fn draw(&self, to: &mut RawTerminal<&mut StdoutLock>, w: u16, h: u16) -> std::io::Result<usize> {
        try!(to.goto(0, 0));

        let mut y = 0;
        let mut bytes_written = 0;

        let lines = if self.lines.len() <= h as usize {
            &self.lines
        } else if self.y_off as usize >= self.lines.len() {
            &self.lines[0..0]
        } else {
            &self.lines[self.y_off as usize..]
        };

        for line in lines {
            if line.len() > w as usize {
                bytes_written += try!(to.write(line[..w as usize].as_bytes()));
            } else {
                bytes_written += try!(to.write(line.as_bytes()));
            }

            y += 1;
            try!(to.goto(0, y));
            if y >= h {
                break;
            }
        }

        Ok(bytes_written)
    }

    fn scroll_up(&mut self) {
        if self.y_off > 0 {
            self.y_off -= 1;
        }
    }

    fn scroll_down(&mut self, height: u16) {
        if ((self.y_off + height) as usize) <= self.lines.len() {
            self.y_off += 1;
        }
    }
}

fn run(file: &mut Read, controls: &mut Read, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    let mut stdout = stdout.into_raw_mode().try(stderr);

    let (w, h) = {
        let (w, h) = terminal_size().try(stderr);
        (w as u16, h as u16)
    };

    stdout.clear().try(stderr);
    stdout.reset().try(stderr);

    let mut buffer = Buffer::new();
    buffer.read(file).try(stderr);

    buffer.draw(&mut stdout, w, h - 1).try(stderr);
    stdout.goto(0, h - 1).try(stderr);
    stdout.bg_color(Color::White).try(stderr);
    stdout.color(Color::Black).try(stderr);
    stdout.write(b"Press q to exit.").try(stderr);
    stdout.reset().try(stderr);
    stdout.flush().try(stderr);

    for c in controls.keys() {
        match c {
            Key::Char('q') => {
                stdout.clear().try(stderr);
                stdout.reset().try(stderr);
                stdout.goto(0, 0).try(stderr);
                return
            },
            Key::Up => buffer.scroll_up(),
            Key::Down => buffer.scroll_down(h),
            _ => {},
        }

        stdout.clear().try(stderr);
        stdout.reset().try(stderr);
        buffer.draw(&mut stdout, w, h - 1).try(stderr);
        stdout.goto(0, h - 1).try(stderr);
        stdout.bg_color(Color::White).try(stderr);
        stdout.color(Color::Black).try(stderr);
        stdout.write(b"Press q to exit.").try(stderr);
        stdout.reset().try(stderr);
        stdout.flush().try(stderr);
    }
}
<commit_msg>Fix build (less.rs)<commit_after>#![deny(warnings)]

// TODO support reading from standard input

extern crate coreutils;
extern crate termion;

use std::env::args;
use std::fs::File;
use std::io::{self, Write, Read, StdoutLock, Stderr};
use std::path::Path;

use coreutils::extra::OptionalExt;

use termion::{terminal_size, TermRead, TermWrite, IntoRawMode, Color, Key, RawTerminal};

static LONG_HELP: &'static str = r#"
    NAME
        less - view a text file.
    SYNOPSIS
        less [-h | --help] [input]
    DESCRIPTION
        This utility views text files. If no input file is specified as an argument, standard input is used.
    OPTIONS
        --help, -h
            Print this manual page.
    AUTHOR
        This program was written by MovingtoMars for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 MovingtoMars

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

fn main() {
    let mut args = args().skip(1);
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let stdin = io::stdin();
    let mut stdin = stdin.lock();
    let mut stderr = io::stderr();

    if let Some(x) = args.next() {
        match x.as_str() {
            "--help" | "-h" => {
                // Print help.
                stdout.write(LONG_HELP.as_bytes()).try(&mut stderr);
                return;
            },
            filename => {
                let mut file = File::open(Path::new(filename)).try(&mut stderr);
                run(&mut file, &mut stdin, &mut stdout, &mut stderr);
            }
        }

        if let Some(x) = args.next() {
            let mut file = File::open(Path::new(x.as_str())).try(&mut stderr);
            run(&mut file, &mut stdin, &mut stdout, &mut stderr);
        }
    } else {
        writeln!(stderr, "Readin from stdin is not yet supported").try(&mut stderr);
        //run(&mut stdin, &mut stdin, &mut stdout, &mut stderr);
    };
}

struct Buffer {
    lines: Vec<String>,
    y_off: u16,
}

impl Buffer {
    fn new() -> Buffer {
        Buffer{
            lines: Vec::new(),
            y_off: 0,
        }
    }

    fn read(&mut self, from: &mut Read) -> std::io::Result<usize> {
        let mut tmp = String::new();
        let res = from.read_to_string(&mut tmp);
        try!(res);

        self.lines.append(&mut tmp
            .as_str()
            .split("\n")
            .map(|x| {String::from(x)})
            .collect());

        return res;
    }

    fn draw(&self, to: &mut RawTerminal<&mut StdoutLock>, w: u16, h: u16) -> std::io::Result<usize> {
        try!(to.goto(0, 0));

        let mut y = 0;
        let mut bytes_written = 0;

        let lines = if self.lines.len() <= h as usize {
            &self.lines
        } else if self.y_off as usize >= self.lines.len() {
            &self.lines[0..0]
        } else {
            &self.lines[self.y_off as usize..]
        };

        for line in lines {
            if line.len() > w as usize {
                bytes_written += try!(to.write(line[..w as usize].as_bytes()));
            } else {
                bytes_written += try!(to.write(line.as_bytes()));
            }

            y += 1;
            try!(to.goto(0, y));
            if y >= h {
                break;
            }
        }

        Ok(bytes_written)
    }

    fn scroll_up(&mut self) {
        if self.y_off > 0 {
            self.y_off -= 1;
        }
    }

    fn scroll_down(&mut self, height: u16) {
        if ((self.y_off + height) as usize) <= self.lines.len() {
            self.y_off += 1;
        }
    }
}

fn run(file: &mut Read, controls: &mut Read, stdout: &mut StdoutLock, stderr: &mut Stderr) {
    let mut stdout = stdout.into_raw_mode().try(stderr);

    let (w, h) = {
        let (w, h) = terminal_size().try(stderr);
        (w as u16, h as u16)
    };

    stdout.clear().try(stderr);
    stdout.reset().try(stderr);

    let mut buffer = Buffer::new();
    buffer.read(file).try(stderr);

    buffer.draw(&mut stdout, w, h - 1).try(stderr);
    stdout.goto(0, h - 1).try(stderr);
    stdout.bg_color(Color::White).try(stderr);
    stdout.color(Color::Black).try(stderr);
    stdout.write(b"Press q to exit.").try(stderr);
    stdout.reset().try(stderr);
    stdout.flush().try(stderr);

    for c in controls.keys() {
        match c {
            Key::Char('q') => {
                stdout.clear().try(stderr);
                stdout.reset().try(stderr);
                stdout.goto(0, 0).try(stderr);
                return
            },
            Key::Up => buffer.scroll_up(),
            Key::Down => buffer.scroll_down(h),
            _ => {},
        }

        stdout.clear().try(stderr);
        stdout.reset().try(stderr);
        buffer.draw(&mut stdout, w, h - 1).try(stderr);
        stdout.goto(0, h - 1).try(stderr);
        stdout.bg_color(Color::White).try(stderr);
        stdout.color(Color::Black).try(stderr);
        stdout.write(b"Press q to exit.").try(stderr);
        stdout.reset().try(stderr);
        stdout.flush().try(stderr);
    }
}
<|endoftext|>


<commit_before>#![crate_name = "rboy"]
#![license    = "MIT" ]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;
                       extern crate getopts;
                       extern crate sdl2;
                       extern crate rboy;

use rboy::device::Device;
use std::time::Duration;
use std::sync::{Arc,RWLock};
use std::comm::{Sender,Receiver,Disconnected,Empty};

static SCALE: uint = 2;
static EXITCODE_INCORRECTOPTIONS: int = 1;
static EXITCODE_CPULOADFAILS: int = 2;

#[cfg(not(test))]
fn set_exit_status(exitcode: int)
{
    std::os::set_exit_status(exitcode);
}

fn main() {
	let args = std::os::args();
	let opts = &[ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free[0].clone()
	} else {
		let mut info_start = args[0].clone();
		info_start.push_str(" <filename>");
		println!("{}", getopts::usage(info_start.as_slice(), opts));
		set_exit_status(EXITCODE_INCORRECTOPTIONS);
		return;
	};

	sdl2::init(sdl2::INIT_VIDEO);
	let window = match sdl2::video::Window::new("RBoy - A gameboy in Rust",
												sdl2::video::WindowPos::PosUndefined,
												sdl2::video::WindowPos::PosUndefined,
												160*SCALE as int,
												144*SCALE as int,
												sdl2::video::WindowFlags::empty()) {
		Ok(window) => window,
		Err(err) => panic!("failed to open window: {}", err),
	};
	let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED) {
		Ok(screen) => screen,
		Err(err) => panic!("failed to open screen: {}", err),
	};

	let (sdl_tx, cpu_rx) = std::comm::channel();
	let (cpu_tx, sdl_rx) = std::comm::channel();
	let rawscreen = [0x00u8,.. 160*144*3];
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();

	spawn(proc() cpuloop(&cpu_tx, &cpu_rx, arc2, filename.as_slice(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(Duration::milliseconds(8));

	'main : loop {
		periodic.recv();
		match sdl_rx.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&renderer, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl2::event::poll_event() {
				sdl2::event::Event::Quit(_) => break 'main,
				sdl2::event::Event::None => break 'event,
				sdl2::event::Event::KeyDown(_, _, sdl2::keycode::KeyCode::Escape, _, _, _)
					=> break 'main,
				sdl2::event::Event::KeyDown(_, _, sdl2::keycode::KeyCode::LShift, _, _, _)
					=> sdl_tx.send(GBEvent::SpeedUp),
				sdl2::event::Event::KeyUp(_, _, sdl2::keycode::KeyCode::LShift, _, _, _)
					=> sdl_tx.send(GBEvent::SlowDown),
				sdl2::event::Event::KeyDown(_, _, sdlkey, _, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdl_tx.send(GBEvent::KeyDown(key)),
						None => {},
					}
				},
				sdl2::event::Event::KeyUp(_, _, sdlkey, _, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdl_tx.send(GBEvent::KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl2::keycode::KeyCode) -> Option<rboy::KeypadKey> {
	match key {
		sdl2::keycode::KeyCode::Z => Some(rboy::KeypadKey::A),
		sdl2::keycode::KeyCode::X => Some(rboy::KeypadKey::B),
		sdl2::keycode::KeyCode::Up => Some(rboy::KeypadKey::Up),
		sdl2::keycode::KeyCode::Down => Some(rboy::KeypadKey::Down),
		sdl2::keycode::KeyCode::Left => Some(rboy::KeypadKey::Left),
		sdl2::keycode::KeyCode::Right => Some(rboy::KeypadKey::Right),
		sdl2::keycode::KeyCode::Space => Some(rboy::KeypadKey::Select),
		sdl2::keycode::KeyCode::Return => Some(rboy::KeypadKey::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl2::render::Renderer, arc: &Arc<RWLock<[u8,.. 160*144*3]>>) {
	screen.set_draw_color(sdl2::pixels::Color::RGB(0xFF, 0xFF, 0xFF)).unwrap();
	screen.clear().unwrap();

	let data =  arc.read().clone();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.set_draw_color(sdl2::pixels::Color::RGB(data[y*160*3 + x*3 + 0],
															data[y*160*3 + x*3 + 1],
															data[y*160*3 + x*3 + 2])).unwrap();
			screen.draw_rect(&sdl2::rect::Rect::new((x*SCALE) as i32, (y*SCALE) as i32, SCALE as i32, SCALE as i32)).unwrap();
		}
	}
	screen.present();
}

enum GBEvent {
	KeyUp(rboy::KeypadKey),
	KeyDown(rboy::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(cpu_tx: &Sender<uint>, cpu_rx: &Receiver<GBEvent>, arc: Arc<RWLock<[u8,.. 160*144*3]>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => Device::new(filename),
		false => Device::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); set_exit_status(EXITCODE_CPULOADFAILS); return; },
	};
	c.set_stdout(matches.opt_present("serial"));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(Duration::milliseconds(8));
	let mut limit_speed = true;

	let waitticks = (4194.304f32 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.do_cycle();
			if c.check_and_reset_gpu_updated() {
				let mut data = arc.write();
				let gpu_data = c.get_gpu_data();
				for i in range(0, data.len()) { data[i] = gpu_data[i]; }
				if cpu_tx.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		if limit_speed { periodic.recv(); }

		match cpu_rx.try_recv() {
			Ok(event) => match event {
				GBEvent::KeyUp(key) => c.keyup(key),
				GBEvent::KeyDown(key) => c.keydown(key),
				GBEvent::SpeedUp => limit_speed = false,
				GBEvent::SlowDown => limit_speed = true,
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<commit_msg>Fix stack overflow on OSX<commit_after>#![crate_name = "rboy"]
#![license    = "MIT" ]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;
                       extern crate getopts;
                       extern crate sdl2;
                       extern crate rboy;

use rboy::device::Device;
use std::time::Duration;
use std::sync::{Arc,RWLock};
use std::comm::{Sender,Receiver,Disconnected,Empty};

static SCALE: uint = 2;
static EXITCODE_INCORRECTOPTIONS: int = 1;
static EXITCODE_CPULOADFAILS: int = 2;

#[cfg(not(test))]
fn set_exit_status(exitcode: int)
{
    std::os::set_exit_status(exitcode);
}

fn main() {
	let args = std::os::args();
	let opts = &[ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f); return }
	};

	let filename = if !matches.free.is_empty() {
		matches.free[0].clone()
	} else {
		let mut info_start = args[0].clone();
		info_start.push_str(" <filename>");
		println!("{}", getopts::usage(info_start.as_slice(), opts));
		set_exit_status(EXITCODE_INCORRECTOPTIONS);
		return;
	};

	sdl2::init(sdl2::INIT_VIDEO);
	let window = match sdl2::video::Window::new("RBoy - A gameboy in Rust",
												sdl2::video::WindowPos::PosUndefined,
												sdl2::video::WindowPos::PosUndefined,
												160*SCALE as int,
												144*SCALE as int,
												sdl2::video::WindowFlags::empty()) {
		Ok(window) => window,
		Err(err) => panic!("failed to open window: {}", err),
	};
	let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED) {
		Ok(screen) => screen,
		Err(err) => panic!("failed to open screen: {}", err),
	};

	let (sdl_tx, cpu_rx) = std::comm::channel();
	let (cpu_tx, sdl_rx) = std::comm::channel();
	let rawscreen = Vec::from_elem(160*144*3, 0u8);
	let arc = Arc::new(RWLock::new(rawscreen));
	let arc2 = arc.clone();

	spawn(proc() cpuloop(&cpu_tx, &cpu_rx, arc2, filename.as_slice(), &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(Duration::milliseconds(8));

	'main : loop {
		periodic.recv();
		match sdl_rx.try_recv() {
			Err(Disconnected) => { break 'main },
			Ok(_) => recalculate_screen(&renderer, &arc),
			Err(Empty) => {},
		}
		'event : loop {
			match sdl2::event::poll_event() {
				sdl2::event::Event::Quit(_) => break 'main,
				sdl2::event::Event::None => break 'event,
				sdl2::event::Event::KeyDown(_, _, sdl2::keycode::KeyCode::Escape, _, _, _)
					=> break 'main,
				sdl2::event::Event::KeyDown(_, _, sdl2::keycode::KeyCode::LShift, _, _, _)
					=> sdl_tx.send(GBEvent::SpeedUp),
				sdl2::event::Event::KeyUp(_, _, sdl2::keycode::KeyCode::LShift, _, _, _)
					=> sdl_tx.send(GBEvent::SlowDown),
				sdl2::event::Event::KeyDown(_, _, sdlkey, _, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdl_tx.send(GBEvent::KeyDown(key)),
						None => {},
					}
				},
				sdl2::event::Event::KeyUp(_, _, sdlkey, _, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdl_tx.send(GBEvent::KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl2::keycode::KeyCode) -> Option<rboy::KeypadKey> {
	match key {
		sdl2::keycode::KeyCode::Z => Some(rboy::KeypadKey::A),
		sdl2::keycode::KeyCode::X => Some(rboy::KeypadKey::B),
		sdl2::keycode::KeyCode::Up => Some(rboy::KeypadKey::Up),
		sdl2::keycode::KeyCode::Down => Some(rboy::KeypadKey::Down),
		sdl2::keycode::KeyCode::Left => Some(rboy::KeypadKey::Left),
		sdl2::keycode::KeyCode::Right => Some(rboy::KeypadKey::Right),
		sdl2::keycode::KeyCode::Space => Some(rboy::KeypadKey::Select),
		sdl2::keycode::KeyCode::Return => Some(rboy::KeypadKey::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl2::render::Renderer, arc: &Arc<RWLock<Vec<u8>>>) {
	screen.set_draw_color(sdl2::pixels::Color::RGB(0xFF, 0xFF, 0xFF)).unwrap();
	screen.clear().unwrap();

	let data =  arc.read().clone();
	for y in range(0u, 144) {
		for x in range(0u, 160) {
			screen.set_draw_color(sdl2::pixels::Color::RGB(data[y*160*3 + x*3 + 0],
															data[y*160*3 + x*3 + 1],
															data[y*160*3 + x*3 + 2])).unwrap();
			screen.draw_rect(&sdl2::rect::Rect::new((x*SCALE) as i32, (y*SCALE) as i32, SCALE as i32, SCALE as i32)).unwrap();
		}
	}
	screen.present();
}

enum GBEvent {
	KeyUp(rboy::KeypadKey),
	KeyDown(rboy::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(cpu_tx: &Sender<uint>, cpu_rx: &Receiver<GBEvent>, arc: Arc<RWLock<Vec<u8>>>, filename: &str, matches: &getopts::Matches) {
	let opt_c = match matches.opt_present("classic") {
		true => Device::new(filename),
		false => Device::new_cgb(filename),
	};
	let mut c = match opt_c
	{
		Some(cpu) => { cpu },
		None => { error!("Could not get a valid gameboy"); set_exit_status(EXITCODE_CPULOADFAILS); return; },
	};
	c.set_stdout(matches.opt_present("serial"));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(Duration::milliseconds(8));
	let mut limit_speed = true;

	let waitticks = (4194.304f32 * 4.0) as uint;

	let mut ticks = 0;
	'cpuloop: loop {
		while ticks < waitticks {
			ticks += c.do_cycle();
			if c.check_and_reset_gpu_updated() {
				let mut data = arc.write();
				let gpu_data = c.get_gpu_data();
				for i in range(0, data.len()) { data[i] = gpu_data[i]; }
				if cpu_tx.send_opt(0).is_err() { break 'cpuloop };
			}
		}
		ticks -= waitticks;
		if limit_speed { periodic.recv(); }

		match cpu_rx.try_recv() {
			Ok(event) => match event {
				GBEvent::KeyUp(key) => c.keyup(key),
				GBEvent::KeyDown(key) => c.keydown(key),
				GBEvent::SpeedUp => limit_speed = false,
				GBEvent::SlowDown => limit_speed = true,
			},
			Err(Empty) => {},
			Err(Disconnected) => { break },
		};
	}
}
<|endoftext|>


<commit_before>use libc;
use std::ptr;
use std::ffi::CStr;
use error::*;
use capstone_sys::*;
use capstone_sys;
use instruction::Instructions;

/// An instance of the capstone disassembler
pub struct Capstone {
    csh: capstone_sys::csh,
    _arch: Arch,
}

/// Architectures for the disassembler
#[derive(Clone, Debug)]
pub enum Arch {
    ARM,
    ARM64,
    MIPS,
    X86,
    PPC,
    SPARC,
    SYSZ,
    XCORE,
    MAX,
    /// used for `cs_support()`
    ALL,
}

impl Arch {
    pub fn to_cs_arch(&self) -> cs_arch {
        use Arch::*;
        match *self {
            ARM => CS_ARCH_ARM,
            ARM64 => CS_ARCH_ARM64,
            MIPS => CS_ARCH_MIPS,
            X86 => CS_ARCH_X86,
            PPC => CS_ARCH_PPC,
            SPARC => CS_ARCH_SPARC,
            SYSZ => CS_ARCH_SYSZ,
            XCORE => CS_ARCH_XCORE,
            MAX => CS_ARCH_MAX,
            ALL => CS_ARCH_ALL,
        }
    }
}

/// Disassembler modes
#[derive(Debug, Clone)]
pub enum Mode {
    /// little-endian mode (default mode)
    LittleEndian,
    /// 32-bit ARM
    Arm32,
    /// 16-bit mode (X86)
    Mode16,
    /// 32-bit mode (X86)
    Mode32,
    /// 64-bit mode (X86, PPC)
    Mode64,
    /// ARM's Thumb mode, including Thumb-2
    Thumb,
    /// ARM's Cortex-M series
    MClass,
    /// ARMv8 A32 encodings for ARM
    V8,
    /// MicroMips mode (MIPS)
    Micro,
    /// Mips III ISA
    Mips3,
    /// Mips32r6 ISA
    Mips32R6,
    /// General Purpose Registers are 64-bit wide (MIPS)
    MipsGP64,
    /// SparcV9 mode (Sparc)
    V9,
    /// big-endian mode
    BigEndian,
    /// Mips32 ISA (Mips)
    Mips32,
    /// Mips64 ISA (Mips)
    Mips64,
}

impl Mode {
    pub fn to_cs_mode(&self) -> capstone_sys::cs_mode {
        use Mode::*;
        match *self {
            LittleEndian => CS_MODE_LITTLE_ENDIAN,
            Arm32 => CS_MODE_ARM,
            Mode16 => CS_MODE_16,
            Mode32 => CS_MODE_32,
            Mode64 => CS_MODE_64,
            Thumb => CS_MODE_THUMB,
            MClass => CS_MODE_MCLASS,
            V8 => CS_MODE_V8,
            Micro => CS_MODE_MICRO,
            Mips3 => CS_MODE_MIPS3,
            Mips32R6 => CS_MODE_MIPS32R6,
            MipsGP64 => CS_MODE_MIPSGP64,
            V9 => CS_MODE_V9,
            BigEndian => CS_MODE_BIG_ENDIAN,
            Mips32 => CS_MODE_MIPS32,
            Mips64 => CS_MODE_MIPS64,
        }
    }
}

impl Capstone {
    /// Create a new instance of the decompiler. Defaults to 64-bit little-endian mode.
    ///
    /// ```
    /// use capstone::{self, Capstone};
    /// let cs = Capstone::new(capstone::Arch::X86);
    /// assert!(cs.is_ok());
    /// ```
    pub fn new(arch: Arch) -> Result<Capstone> {
        let mut handle: capstone_sys::csh = 0;
        let csarch = arch.to_cs_arch();
        let csmode = CS_MODE_LITTLE_ENDIAN;
        let err = unsafe { cs_open(csarch, csmode, &mut handle) };
        // this can be put into a macro, cs_try, but i guess who cares
        if CS_ERR_OK == err {
            Ok(Capstone { csh: handle, _arch: arch })
        } else {
            Err(Error::from(err))
        }
    }

    #[inline]
    fn set_option(&self, opt_type: cs_opt_type, value: libc::size_t) -> Result<()> {
        let err = unsafe {
            cs_option(self.csh, opt_type, value)
        };
        if CS_ERR_OK == err {
            Ok(())
        } else {
            Err(Error::from(err))
        }
    }

    /// Set the disassembly engine to use detail mode
    pub fn detail(&self) -> Result<()> {
        self.set_option(capstone_sys::CS_OPT_DETAIL, capstone_sys::CS_OPT_ON)
    }

    /// Sets the engine's disassembly mode.
    /// Be careful, various combinations of modes aren't supported
    /// See the capstone-sys documentation for more information.
    pub fn mode(&mut self, modes: &[Mode]) -> Result<()> {
        let mut value = 0;
        for mode in modes {
            value |= mode.to_cs_mode();
        }
        self.set_option(CS_OPT_MODE, value as capstone_sys::cs_opt_value)
    }

    /// Set the X86 assembly to AT&T style (has no effect on other platforms)
    pub fn att(&self) {
        self.set_option(capstone_sys::CS_OPT_SYNTAX, capstone_sys::CS_OPT_SYNTAX_ATT).unwrap()
    }

    /// Set the X86 assembly to Intel style (default)
    pub fn intel(&self) {
        self.set_option(capstone_sys::CS_OPT_SYNTAX, capstone_sys::CS_OPT_SYNTAX_INTEL).unwrap()
    }

    /// Disassemble a &[u8] `buffer` full of instructions
    ///
    /// Disassembles all instructions in `code`. If you want to disassemble less, then pass a smaller slice :]
    pub fn disassemble(&self, buffer: &[u8], addr: u64) -> Result<Instructions> {
        let mut ptr: *mut capstone_sys::cs_insn = ptr::null_mut();
        let insn_count = unsafe {
            cs_disasm(self.csh,
                      buffer.as_ptr(),
                      buffer.len() as libc::size_t,
                      addr,
                      0 as libc::size_t,
                      &mut ptr)
        };
        if insn_count == 0 {
            // we can just simply not have found instructions in the buffer; this isn't an error
            // so we just return an empty instructions
            // I worry this will explode when freeing, we need a better api to just convert to a
            // straight vector
            let err = unsafe { cs_errno(self.csh) };
            if err != CS_ERR_OK {
                return Err(Error::from(err))
            }
        }
        Ok(unsafe { Instructions::from_raw_parts(ptr, insn_count as isize) })
    }

    /// Convert a reg_id to a String naming the register
    pub fn reg_name(&self, reg_id: u64) -> Option<String> {
        let reg_name = unsafe {
            let _reg_name = cs_reg_name(self.csh, reg_id as libc::c_uint);
            if _reg_name == ptr::null() {
                return None
            }

            CStr::from_ptr(_reg_name).to_string_lossy().into_owned()
        };

        Some(reg_name)
    }

    /// Convert an instruction_id to a String naming the instruction
    pub fn insn_name(&self, insn_id: u64) -> Option<String> {
        let insn_name = unsafe {
            let _insn_name = cs_insn_name(self.csh, insn_id as libc::c_uint);
            if _insn_name == ptr::null() {
                return None
            }
            CStr::from_ptr(_insn_name).to_string_lossy().into_owned()
        };

        Some(insn_name)
    }
}

impl Drop for Capstone {
    fn drop(&mut self) {
        unsafe { cs_close(&mut self.csh) };
    }
}
<commit_msg>capstone: add partial eq and copy to mode and arch<commit_after>use libc;
use std::ptr;
use std::ffi::CStr;
use error::*;
use capstone_sys::*;
use capstone_sys;
use instruction::Instructions;

/// An instance of the capstone disassembler
pub struct Capstone {
    csh: capstone_sys::csh,
    _arch: Arch,
}

/// Architectures for the disassembler
#[derive(Clone, Debug, PartialEq, Copy)]
pub enum Arch {
    ARM,
    ARM64,
    MIPS,
    X86,
    PPC,
    SPARC,
    SYSZ,
    XCORE,
    MAX,
    /// used for `cs_support()`
    ALL,
}

impl Arch {
    pub fn to_cs_arch(&self) -> cs_arch {
        use Arch::*;
        match *self {
            ARM => CS_ARCH_ARM,
            ARM64 => CS_ARCH_ARM64,
            MIPS => CS_ARCH_MIPS,
            X86 => CS_ARCH_X86,
            PPC => CS_ARCH_PPC,
            SPARC => CS_ARCH_SPARC,
            SYSZ => CS_ARCH_SYSZ,
            XCORE => CS_ARCH_XCORE,
            MAX => CS_ARCH_MAX,
            ALL => CS_ARCH_ALL,
        }
    }
}

/// Disassembler modes
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum Mode {
    /// little-endian mode (default mode)
    LittleEndian,
    /// 32-bit ARM
    Arm32,
    /// 16-bit mode (X86)
    Mode16,
    /// 32-bit mode (X86)
    Mode32,
    /// 64-bit mode (X86, PPC)
    Mode64,
    /// ARM's Thumb mode, including Thumb-2
    Thumb,
    /// ARM's Cortex-M series
    MClass,
    /// ARMv8 A32 encodings for ARM
    V8,
    /// MicroMips mode (MIPS)
    Micro,
    /// Mips III ISA
    Mips3,
    /// Mips32r6 ISA
    Mips32R6,
    /// General Purpose Registers are 64-bit wide (MIPS)
    MipsGP64,
    /// SparcV9 mode (Sparc)
    V9,
    /// big-endian mode
    BigEndian,
    /// Mips32 ISA (Mips)
    Mips32,
    /// Mips64 ISA (Mips)
    Mips64,
}

impl Mode {
    pub fn to_cs_mode(&self) -> capstone_sys::cs_mode {
        use Mode::*;
        match *self {
            LittleEndian => CS_MODE_LITTLE_ENDIAN,
            Arm32 => CS_MODE_ARM,
            Mode16 => CS_MODE_16,
            Mode32 => CS_MODE_32,
            Mode64 => CS_MODE_64,
            Thumb => CS_MODE_THUMB,
            MClass => CS_MODE_MCLASS,
            V8 => CS_MODE_V8,
            Micro => CS_MODE_MICRO,
            Mips3 => CS_MODE_MIPS3,
            Mips32R6 => CS_MODE_MIPS32R6,
            MipsGP64 => CS_MODE_MIPSGP64,
            V9 => CS_MODE_V9,
            BigEndian => CS_MODE_BIG_ENDIAN,
            Mips32 => CS_MODE_MIPS32,
            Mips64 => CS_MODE_MIPS64,
        }
    }
}

impl Capstone {
    /// Create a new instance of the decompiler. Defaults to 64-bit little-endian mode.
    ///
    /// ```
    /// use capstone::{self, Capstone};
    /// let cs = Capstone::new(capstone::Arch::X86);
    /// assert!(cs.is_ok());
    /// ```
    pub fn new(arch: Arch) -> Result<Capstone> {
        let mut handle: capstone_sys::csh = 0;
        let csarch = arch.to_cs_arch();
        let csmode = CS_MODE_LITTLE_ENDIAN;
        let err = unsafe { cs_open(csarch, csmode, &mut handle) };
        // this can be put into a macro, cs_try, but i guess who cares
        if CS_ERR_OK == err {
            Ok(Capstone { csh: handle, _arch: arch })
        } else {
            Err(Error::from(err))
        }
    }

    #[inline]
    fn set_option(&self, opt_type: cs_opt_type, value: libc::size_t) -> Result<()> {
        let err = unsafe {
            cs_option(self.csh, opt_type, value)
        };
        if CS_ERR_OK == err {
            Ok(())
        } else {
            Err(Error::from(err))
        }
    }

    /// Set the disassembly engine to use detail mode
    pub fn detail(&self) -> Result<()> {
        self.set_option(capstone_sys::CS_OPT_DETAIL, capstone_sys::CS_OPT_ON)
    }

    /// Sets the engine's disassembly mode.
    /// Be careful, various combinations of modes aren't supported
    /// See the capstone-sys documentation for more information.
    pub fn mode(&mut self, modes: &[Mode]) -> Result<()> {
        let mut value = 0;
        for mode in modes {
            value |= mode.to_cs_mode();
        }
        self.set_option(CS_OPT_MODE, value as capstone_sys::cs_opt_value)
    }

    /// Set the X86 assembly to AT&T style (has no effect on other platforms)
    pub fn att(&self) {
        self.set_option(capstone_sys::CS_OPT_SYNTAX, capstone_sys::CS_OPT_SYNTAX_ATT).unwrap()
    }

    /// Set the X86 assembly to Intel style (default)
    pub fn intel(&self) {
        self.set_option(capstone_sys::CS_OPT_SYNTAX, capstone_sys::CS_OPT_SYNTAX_INTEL).unwrap()
    }

    /// Disassemble a &[u8] `buffer` full of instructions
    ///
    /// Disassembles all instructions in `code`. If you want to disassemble less, then pass a smaller slice :]
    pub fn disassemble(&self, buffer: &[u8], addr: u64) -> Result<Instructions> {
        let mut ptr: *mut capstone_sys::cs_insn = ptr::null_mut();
        let insn_count = unsafe {
            cs_disasm(self.csh,
                      buffer.as_ptr(),
                      buffer.len() as libc::size_t,
                      addr,
                      0 as libc::size_t,
                      &mut ptr)
        };
        if insn_count == 0 {
            // we can just simply not have found instructions in the buffer; this isn't an error
            // so we just return an empty instructions
            // I worry this will explode when freeing, we need a better api to just convert to a
            // straight vector
            let err = unsafe { cs_errno(self.csh) };
            if err != CS_ERR_OK {
                return Err(Error::from(err))
            }
        }
        Ok(unsafe { Instructions::from_raw_parts(ptr, insn_count as isize) })
    }

    /// Convert a reg_id to a String naming the register
    pub fn reg_name(&self, reg_id: u64) -> Option<String> {
        let reg_name = unsafe {
            let _reg_name = cs_reg_name(self.csh, reg_id as libc::c_uint);
            if _reg_name == ptr::null() {
                return None
            }

            CStr::from_ptr(_reg_name).to_string_lossy().into_owned()
        };

        Some(reg_name)
    }

    /// Convert an instruction_id to a String naming the instruction
    pub fn insn_name(&self, insn_id: u64) -> Option<String> {
        let insn_name = unsafe {
            let _insn_name = cs_insn_name(self.csh, insn_id as libc::c_uint);
            if _insn_name == ptr::null() {
                return None
            }
            CStr::from_ptr(_insn_name).to_string_lossy().into_owned()
        };

        Some(insn_name)
    }
}

impl Drop for Capstone {
    fn drop(&mut self) {
        unsafe { cs_close(&mut self.csh) };
    }
}
<|endoftext|>


<commit_before>// Implements the `zakopane checksum` subcommand.

use crate::structs::ZakopaneError;

const MAX_TASKS: usize = 8;

#[derive(Default)]
struct ChecksumTaskManager {
    // Non-associative container enumerating paths and checksums.
    sums: std::vec::Vec<(String, String)>,

    // Map of outstanding checksum tasks.
    // *    Keys: absolute paths being checksummed
    // *    Values: tokio JoinHandles for checksum tasks
    tasks: std::collections::HashMap<String, tokio::task::JoinHandle<String>>,
}

async fn do_checksum(path: std::path::PathBuf) -> Result<String, ZakopaneError> {
    todo!()
}

impl ChecksumTaskManager {
    pub fn new() -> Self {
        Default::default()
    }

    pub async fn spawn_task(&self, path: std::path::PathBuf) {
        assert!(
            self.tasks.len() < MAX_TASKS,
            "attempted to spawn too many tasks"
        );
        tokio::spawn(do_checksum(path));
    }
}

async fn checksum_impl() -> Result<String, ZakopaneError> {
    // *    Walk the target path.
    // *    If we can, then spawn a task, providing the current path
    //      in the walk and a cloned transmitter.
    // *    Call `poll_recv()` on the receiver repeatedly, updating
    //      our checksum map and `join()`ing the completed tasks.
    todo!()
}

#[allow(dead_code)]
fn checksum() -> Result<String, ZakopaneError> {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(checksum_impl())
}
<commit_msg>checksum: Introduce ChecksumResult type<commit_after>// Implements the `zakopane checksum` subcommand.

use crate::structs::ZakopaneError;

const MAX_TASKS: usize = 8;
type ChecksumResult = Result<String, ZakopaneError>;

#[derive(Default)]
struct ChecksumTaskManager {
    // Non-associative container enumerating paths and checksums.
    sums: std::vec::Vec<(String, String)>,

    // Map of outstanding checksum tasks.
    // *    Keys: absolute paths being checksummed
    // *    Values: tokio JoinHandles for checksum tasks
    tasks: std::collections::HashMap<String, tokio::task::JoinHandle<ChecksumResult>>,
}

async fn do_checksum(path: std::path::PathBuf) -> ChecksumResult {
    todo!()
}

impl ChecksumTaskManager {
    pub fn new() -> Self {
        Default::default()
    }

    pub async fn spawn_task(&mut self, path: std::path::PathBuf) {
        assert!(
            self.tasks.len() < MAX_TASKS,
            "attempted to spawn too many tasks"
        );
        self.tasks.insert(String::from(path.to_str().unwrap()), tokio::spawn(do_checksum(path)));
    }
}

async fn checksum_impl() -> ChecksumResult {
    // *    Walk the target path.
    // *    If we can, then spawn a task, providing the current path
    //      in the walk and a cloned transmitter.
    // *    Call `poll_recv()` on the receiver repeatedly, updating
    //      our checksum map and `join()`ing the completed tasks.
    todo!()
}

#[allow(dead_code)]
fn checksum() -> ChecksumResult {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(checksum_impl())
}
<|endoftext|>