<commit_before>// Copyright 2016 Alexander Reece
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod class_mod;
mod frame_payload_enum;
mod header_enum;
mod method_enum;

use std::iter::ExactSizeIterator;
use std::io;

use WriteRust;
use common::Spec;

use self::class_mod::ClassModuleWriter;
use self::frame_payload_enum::FramePayloadEnumWriter;
use self::header_enum::HeaderEnumWriter;
use self::method_enum::MethodEnumWriter;

pub struct SpecModuleWriter<'a> {
    spec: &'a Spec,
}

impl<'a> WriteRust for SpecModuleWriter<'a> {
    fn write_rust_to<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        if self.spec.classes().len() == 0 {
            return Ok(());
        }

        try!(writeln!(writer, "#![allow(too_many_arguments)]\n"));

        try!(self.write_class_constants(writer));
        try!(self.write_method_constants(writer));

        let header_enum = HeaderEnumWriter::new(&self.spec);
        try!(header_enum.write_rust_to(writer));
        try!(self.write_frame_struct(writer));

        let frame_payload_enum = FramePayloadEnumWriter::new(&self.spec);
        try!(frame_payload_enum.write_rust_to(writer));

        try!(writeln!(writer, "\n// Class Modules"));
        for class in self.spec.classes() {
            let module_writer = ClassModuleWriter::new(class);
            try!(module_writer.write_rust_to(writer));
        }

        // aliases
        try!(writeln!(writer, "\n// Class methods"));
        for class in self.spec.classes() {
            try!(writeln!(writer, "pub use self::{}::ClassMethod as {}Method;", class.snake_case(), class.pascal_case()));
        }

        try!(writeln!(writer, "\n// Class headers"));
        for class in self.spec.classes() {
            if class.fields().is_empty() {
                continue;
            }
            try!(writeln!(writer, "pub use self::{}::Header as {}Header;", class.snake_case(), class.pascal_case()));
        }

        let method_enum = MethodEnumWriter::new(&self.spec);
        try!(method_enum.write_rust_to(writer));

        Ok(())
    }
}

impl<'a> SpecModuleWriter<'a> {
    pub fn new(spec: &'a Spec) -> Self {
        SpecModuleWriter {
            spec: spec,
        }
    }

    pub fn mod_name(&self) -> &str {
        self.spec.mod_name()
    }

    pub fn write_class_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(writer, "// Class Constants"));
        try!(writeln!(writer, "// Generated by primalgen::codegen::spec_module::SpecModuleWriter"));
        for (index, class_names) in self.spec.class_indexes() {
            for class_name in class_names {
                let class = self.spec.class(class_name).unwrap();
                let constant_class = class.constant_case();
                try!(writeln!(writer, "pub const CLASS_{}: u16 = {};", constant_class, class.index()));
            }
        }

        Ok(())
    }

    /// Write the correct frame strucutre
    /// 0.8.x had a "cycle" in each frame, 0.9.x doesn't
    pub fn write_frame_struct<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        let version = self.spec.version();

        let (cycle_prop, cycle_getter, cycle_arg, cycle_create) = if version.minor() == 8 {
            (
                "cycle: u8,\n",
                "\n\
                    pub fn cycle(&self) -> u8 {{\n\
                        self.cycle\n\
                    }} // fn cycle()\n\
                 \n",
                "cycle: u8,\n",
                "cycle: cycle,\n",
            )
        } else {
            ("", "", "", "")
        };

        // struct Frame
        try!(writeln!(writer, "\n\
                // Generated by primalgen::codegen::spec_module::SpecModuleWriter
                #[derive(Debug)]
                pub struct Frame<'a> {{\n\
                    channel: u16,\n\
                    {}\
                    payload: FramePayload<'a>,\n\
                }} // struct Frame\n\
                \n\
                impl<'a> Frame<'a> {{\n\
                    pub fn new<P>(channel: u16, {}payload: P) -> Self\n\
                        where P: Into<FramePayload<'a>>\n\
                    {{\n\
                        Frame {{\n\
                            channel: channel,\n\
                            {}\
                            payload: payload.into(),\n\
                        }} // Frame\n\
                    }} // fn new()\n\
                    \n\
                    pub fn channel(&self) -> u16 {{\n\
                        self.channel\n\
                    }} // fn channel()\n\
                    \n\
                    pub fn payload(&self) -> &FramePayload<'a> {{\n\
                        &self.payload\n\
                    }} // fn payload()\n\
                    {}\n\
                 }} // impl Frame<'a>
                    ",
                      cycle_prop, // struct Frame<'a>...
                      cycle_arg, // fn new()...
                      cycle_create, // Frame { cycle: ... }
                      cycle_getter, // fn cycle() -> u8
        ));

        Ok(())
    }

    pub fn write_method_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(writer, "\n// Class Methods"));
        try!(write!(writer, "// Generated by codegen::spec_module::SpecModuleWriter"));
        for class in self.spec.classes() {
            try!(writeln!(writer, ""));
            let constant_class = class.constant_case();
            for (index, method_names) in class.method_indexes() {
                for method_name in method_names {
                    let method = class.method(method_name).unwrap();

                    try!(writeln!(
                        writer,
                        "pub const METHOD_{}_{}: u16 = {};",
                        class.constant_case(),
                        method.constant_case(),
                        method.index()
                    ));
                }
            }
        }

        Ok(())
    }
}<commit_msg>[primalgen] Remove unused variables from SpecModuleWriter<commit_after>// Copyright 2016 Alexander Reece
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod class_mod;
mod frame_payload_enum;
mod header_enum;
mod method_enum;

use std::iter::ExactSizeIterator;
use std::io;

use WriteRust;
use common::Spec;

use self::class_mod::ClassModuleWriter;
use self::frame_payload_enum::FramePayloadEnumWriter;
use self::header_enum::HeaderEnumWriter;
use self::method_enum::MethodEnumWriter;

pub struct SpecModuleWriter<'a> {
    spec: &'a Spec,
}

impl<'a> WriteRust for SpecModuleWriter<'a> {
    fn write_rust_to<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        if self.spec.classes().len() == 0 {
            return Ok(());
        }

        try!(writeln!(writer, "#![allow(too_many_arguments)]\n"));

        try!(self.write_class_constants(writer));
        try!(self.write_method_constants(writer));

        let header_enum = HeaderEnumWriter::new(&self.spec);
        try!(header_enum.write_rust_to(writer));
        try!(self.write_frame_struct(writer));

        let frame_payload_enum = FramePayloadEnumWriter::new(&self.spec);
        try!(frame_payload_enum.write_rust_to(writer));

        try!(writeln!(writer, "\n// Class Modules"));
        for class in self.spec.classes() {
            let module_writer = ClassModuleWriter::new(class);
            try!(module_writer.write_rust_to(writer));
        }

        // aliases
        try!(writeln!(writer, "\n// Class methods"));
        for class in self.spec.classes() {
            try!(writeln!(writer, "pub use self::{}::ClassMethod as {}Method;", class.snake_case(), class.pascal_case()));
        }

        try!(writeln!(writer, "\n// Class headers"));
        for class in self.spec.classes() {
            if class.fields().is_empty() {
                continue;
            }
            try!(writeln!(writer, "pub use self::{}::Header as {}Header;", class.snake_case(), class.pascal_case()));
        }

        let method_enum = MethodEnumWriter::new(&self.spec);
        try!(method_enum.write_rust_to(writer));

        Ok(())
    }
}

impl<'a> SpecModuleWriter<'a> {
    pub fn new(spec: &'a Spec) -> Self {
        SpecModuleWriter {
            spec: spec,
        }
    }

    pub fn mod_name(&self) -> &str {
        self.spec.mod_name()
    }

    pub fn write_class_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(writer, "// Class Constants"));
        try!(writeln!(writer, "// Generated by primalgen::codegen::spec_module::SpecModuleWriter"));
        for (_, class_names) in self.spec.class_indexes() {
            for class_name in class_names {
                let class = self.spec.class(class_name).unwrap();
                let constant_class = class.constant_case();
                try!(writeln!(writer, "pub const CLASS_{}: u16 = {};", constant_class, class.index()));
            }
        }

        Ok(())
    }

    /// Write the correct frame strucutre
    /// 0.8.x had a "cycle" in each frame, 0.9.x doesn't
    pub fn write_frame_struct<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        let version = self.spec.version();

        let (cycle_prop, cycle_getter, cycle_arg, cycle_create) = if version.minor() == 8 {
            (
                "cycle: u8,\n",
                "\n\
                    pub fn cycle(&self) -> u8 {{\n\
                        self.cycle\n\
                    }} // fn cycle()\n\
                 \n",
                "cycle: u8,\n",
                "cycle: cycle,\n",
            )
        } else {
            ("", "", "", "")
        };

        // struct Frame
        try!(writeln!(writer, "\n\
                // Generated by primalgen::codegen::spec_module::SpecModuleWriter
                #[derive(Debug)]
                pub struct Frame<'a> {{\n\
                    channel: u16,\n\
                    {}\
                    payload: FramePayload<'a>,\n\
                }} // struct Frame\n\
                \n\
                impl<'a> Frame<'a> {{\n\
                    pub fn new<P>(channel: u16, {}payload: P) -> Self\n\
                        where P: Into<FramePayload<'a>>\n\
                    {{\n\
                        Frame {{\n\
                            channel: channel,\n\
                            {}\
                            payload: payload.into(),\n\
                        }} // Frame\n\
                    }} // fn new()\n\
                    \n\
                    pub fn channel(&self) -> u16 {{\n\
                        self.channel\n\
                    }} // fn channel()\n\
                    \n\
                    pub fn payload(&self) -> &FramePayload<'a> {{\n\
                        &self.payload\n\
                    }} // fn payload()\n\
                    {}\n\
                 }} // impl Frame<'a>
                    ",
                      cycle_prop, // struct Frame<'a>...
                      cycle_arg, // fn new()...
                      cycle_create, // Frame { cycle: ... }
                      cycle_getter, // fn cycle() -> u8
        ));

        Ok(())
    }

    pub fn write_method_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(writer, "\n// Class Methods"));
        try!(write!(writer, "// Generated by codegen::spec_module::SpecModuleWriter"));
        for class in self.spec.classes() {
            try!(writeln!(writer, ""));
            let constant_class = class.constant_case();
            for (_, method_names) in class.method_indexes() {
                for method_name in method_names {
                    let method = class.method(method_name).unwrap();
                    try!(writeln!(
                        writer,
                        "pub const METHOD_{}_{}: u16 = {};",
                        class.constant_case(),
                        method.constant_case(),
                        method.index()
                    ));
                }
            }
        }

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


<commit_before>// Copyright 2014 The Gfx-rs 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.

extern crate cgmath;
#[macro_use]
extern crate gfx;
extern crate gfx_app;
extern crate genmesh;
extern crate noise;
extern crate rand;
extern crate winit;

pub use gfx::format::{DepthStencil};
pub use gfx_app::{ColorFormat, DepthFormat};

use cgmath::{Deg, Matrix4, Point3, SquareMatrix, Vector3};
use genmesh::{Vertices, Triangulate};
use genmesh::generators::{Plane, SharedVertex, IndexedPolygon};
use noise::{Seed, perlin2};
use rand::Rng;
use std::time::{Instant};

gfx_defines!{
    vertex Vertex {
        pos: [f32; 3] = "a_Pos",
        color: [f32; 3] = "a_Color",
    }

    constant Locals {
        model: [[f32; 4]; 4] = "u_Model",
        view: [[f32; 4]; 4] = "u_View",
        proj: [[f32; 4]; 4] = "u_Proj",
    }

    pipeline pipe {
        vbuf: gfx::VertexBuffer<Vertex> = (),
        locals: gfx::ConstantBuffer<Locals> = "Locals",
        model: gfx::Global<[[f32; 4]; 4]> = "u_Model",
        view: gfx::Global<[[f32; 4]; 4]> = "u_View",
        proj: gfx::Global<[[f32; 4]; 4]> = "u_Proj",
        out_color: gfx::RenderTarget<ColorFormat> = "Target0",
        out_depth: gfx::DepthTarget<DepthFormat> =
            gfx::preset::depth::LESS_EQUAL_WRITE,
    }
}

fn calculate_color(height: f32) -> [f32; 3] {
    if height > 8.0 {
        [0.9, 0.9, 0.9] // white
    } else if height > 0.0 {
        [0.7, 0.7, 0.7] // greay
    } else if height > -5.0 {
        [0.2, 0.7, 0.2] // green
    } else {
        [0.2, 0.2, 0.7] // blue
    }
}

struct App<R: gfx::Resources> {
    pso: gfx::PipelineState<R, pipe::Meta>,
    data: pipe::Data<R>,
    slice: gfx::Slice<R>,
    start_time: Instant,
}

impl<R: gfx::Resources> gfx_app::Application<R> for App<R> {
    fn new<F: gfx::Factory<R>>(factory: &mut F, backend: gfx_app::shade::Backend,
           window_targets: gfx_app::WindowTargets<R>) -> Self {
        use gfx::traits::FactoryExt;

        let vs = gfx_app::shade::Source {
            glsl_120: include_bytes!("shader/terrain_120.glslv"),
            glsl_150: include_bytes!("shader/terrain_150.glslv"),
            hlsl_40:  include_bytes!("data/vertex.fx"),
            msl_11: include_bytes!("shader/terrain_vertex.metal"),
            vulkan:   include_bytes!("data/vert.spv"),
            .. gfx_app::shade::Source::empty()
        };
        let ps = gfx_app::shade::Source {
            glsl_120: include_bytes!("shader/terrain_120.glslf"),
            glsl_150: include_bytes!("shader/terrain_150.glslf"),
            hlsl_40:  include_bytes!("data/pixel.fx"),
            msl_11: include_bytes!("shader/terrain_frag.metal"),
            vulkan:   include_bytes!("data/frag.spv"),
            .. gfx_app::shade::Source::empty()
        };

        let rand_seed = rand::thread_rng().gen();
        let seed = Seed::new(rand_seed);
        let plane = Plane::subdivide(256, 256);
        let vertex_data: Vec<Vertex> = plane.shared_vertex_iter()
            .map(|(x, y)| {
                let h = perlin2(&seed, &[x, y]) * 32.0;
                Vertex {
                    pos: [25.0 * x, 25.0 * y, h],
                    color: calculate_color(h),
                }
            })
            .collect();

        let index_data: Vec<u32> = plane.indexed_polygon_iter()
            .triangulate()
            .vertices()
            .map(|i| i as u32)
            .collect();

        let (vbuf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, &index_data[..]);

        App {
            pso: factory.create_pipeline_simple(
                vs.select(backend).unwrap(),
                ps.select(backend).unwrap(),
                pipe::new()
                ).unwrap(),
            data: pipe::Data {
                vbuf: vbuf,
                locals: factory.create_constant_buffer(1),
                model: Matrix4::identity().into(),
                view: Matrix4::identity().into(),
                proj: cgmath::perspective(
                    Deg(60.0f32), window_targets.aspect_ratio, 0.1, 1000.0
                    ).into(),
                out_color: window_targets.color,
                out_depth: window_targets.depth,
            },
            slice: slice,
            start_time: Instant::now(),
        }
    }

    fn render<C: gfx::CommandBuffer<R>>(&mut self, encoder: &mut gfx::Encoder<R, C>) {
        let elapsed = self.start_time.elapsed();
        let time = elapsed.as_secs() as f32 + elapsed.subsec_nanos() as f32 / 1000_000_000.0;
        let x = time.sin();
        let y = time.cos();
        let view = Matrix4::look_at(
            Point3::new(x * 32.0, y * 32.0, 16.0),
            Point3::new(0.0, 0.0, 0.0),
            Vector3::unit_z(),
        );

        self.data.view = view.into();
        let locals = Locals {
            model: self.data.model,
            view: self.data.view,
            proj: self.data.proj,
        };

        encoder.update_buffer(&self.data.locals, &[locals], 0).unwrap();
        encoder.clear(&self.data.out_color, [0.3, 0.3, 0.3, 1.0]);
        encoder.clear_depth(&self.data.out_depth, 1.0);
        encoder.draw(&self.slice, &self.pso, &self.data);
    }

    fn on_resize(&mut self, window_targets: gfx_app::WindowTargets<R>) {
        self.data.out_color = window_targets.color;
        self.data.out_depth = window_targets.depth;
        self.data.proj = cgmath::perspective(
                Deg(60.0f32), window_targets.aspect_ratio, 0.1, 1000.0
            ).into();
    }
}

pub fn main() {
    use gfx_app::Application;
    App::launch_simple("Terrain example");
}
<commit_msg>[ll] Update terrain example<commit_after>// Copyright 2014 The Gfx-rs 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.

extern crate cgmath;
#[macro_use]
extern crate gfx;
extern crate gfx_app;
extern crate genmesh;
extern crate noise;
extern crate rand;
extern crate winit;

use gfx::format::{DepthStencil};
use gfx::GraphicsPoolExt;
use gfx_app::{BackbufferView, ColorFormat, DepthFormat};

use cgmath::{Deg, Matrix4, Point3, SquareMatrix, Vector3};
use genmesh::{Vertices, Triangulate};
use genmesh::generators::{Plane, SharedVertex, IndexedPolygon};
use noise::{Seed, perlin2};
use rand::Rng;
use std::time::{Instant};

gfx_defines!{
    vertex Vertex {
        pos: [f32; 3] = "a_Pos",
        color: [f32; 3] = "a_Color",
    }

    constant Locals {
        model: [[f32; 4]; 4] = "u_Model",
        view: [[f32; 4]; 4] = "u_View",
        proj: [[f32; 4]; 4] = "u_Proj",
    }

    pipeline pipe {
        vbuf: gfx::VertexBuffer<Vertex> = (),
        locals: gfx::ConstantBuffer<Locals> = "Locals",
        model: gfx::Global<[[f32; 4]; 4]> = "u_Model",
        view: gfx::Global<[[f32; 4]; 4]> = "u_View",
        proj: gfx::Global<[[f32; 4]; 4]> = "u_Proj",
        out_color: gfx::RenderTarget<ColorFormat> = "Target0",
        out_depth: gfx::DepthTarget<DepthFormat> =
            gfx::preset::depth::LESS_EQUAL_WRITE,
    }
}

fn calculate_color(height: f32) -> [f32; 3] {
    if height > 8.0 {
        [0.9, 0.9, 0.9] // white
    } else if height > 0.0 {
        [0.7, 0.7, 0.7] // greay
    } else if height > -5.0 {
        [0.2, 0.7, 0.2] // green
    } else {
        [0.2, 0.2, 0.7] // blue
    }
}

struct App<B: gfx::Backend> {
    views: Vec<BackbufferView<B::Resources>>,
    pso: gfx::PipelineState<B::Resources, pipe::Meta>,
    data: pipe::Data<B::Resources>,
    slice: gfx::Slice<B::Resources>,
    start_time: Instant,
}

impl<B: gfx::Backend> gfx_app::Application<B> for App<B> {
    fn new(factory: &mut B::Factory,
           backend: gfx_app::shade::Backend,
           window_targets: gfx_app::WindowTargets<B::Resources>) -> Self
    {
        use gfx::traits::FactoryExt;

        let vs = gfx_app::shade::Source {
            glsl_120: include_bytes!("shader/terrain_120.glslv"),
            glsl_150: include_bytes!("shader/terrain_150.glslv"),
            hlsl_40:  include_bytes!("data/vertex.fx"),
            msl_11: include_bytes!("shader/terrain_vertex.metal"),
            vulkan:   include_bytes!("data/vert.spv"),
            .. gfx_app::shade::Source::empty()
        };
        let ps = gfx_app::shade::Source {
            glsl_120: include_bytes!("shader/terrain_120.glslf"),
            glsl_150: include_bytes!("shader/terrain_150.glslf"),
            hlsl_40:  include_bytes!("data/pixel.fx"),
            msl_11: include_bytes!("shader/terrain_frag.metal"),
            vulkan:   include_bytes!("data/frag.spv"),
            .. gfx_app::shade::Source::empty()
        };

        let rand_seed = rand::thread_rng().gen();
        let seed = Seed::new(rand_seed);
        let plane = Plane::subdivide(256, 256);
        let vertex_data: Vec<Vertex> = plane.shared_vertex_iter()
            .map(|(x, y)| {
                let h = perlin2(&seed, &[x, y]) * 32.0;
                Vertex {
                    pos: [25.0 * x, 25.0 * y, h],
                    color: calculate_color(h),
                }
            })
            .collect();

        let index_data: Vec<u32> = plane.indexed_polygon_iter()
            .triangulate()
            .vertices()
            .map(|i| i as u32)
            .collect();

        let (vbuf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, &index_data[..]);
        let (out_color, out_depth) = window_targets.views[0].clone(); // initial placeholder values

        App {
            views: window_targets.views,
            pso: factory.create_pipeline_simple(
                vs.select(backend).unwrap(),
                ps.select(backend).unwrap(),
                pipe::new()
                ).unwrap(),
            data: pipe::Data {
                vbuf,
                locals: factory.create_constant_buffer(1),
                model: Matrix4::identity().into(),
                view: Matrix4::identity().into(),
                proj: cgmath::perspective(
                    Deg(60.0f32), window_targets.aspect_ratio, 0.1, 1000.0
                    ).into(),
                out_color,
                out_depth,
            },
            slice,
            start_time: Instant::now(),
        }
    }

     fn render<Gp>(&mut self, (frame, semaphore): (gfx::Frame, &gfx::handle::Semaphore<B::Resources>),
                  pool: &mut Gp, queue: &mut gfx::queue::GraphicsQueueMut<B>)
        where Gp: gfx::GraphicsCommandPool<B>
    {
        let elapsed = self.start_time.elapsed();
        let time = elapsed.as_secs() as f32 + elapsed.subsec_nanos() as f32 / 1000_000_000.0;
        let x = time.sin();
        let y = time.cos();
        let view = Matrix4::look_at(
            Point3::new(x * 32.0, y * 32.0, 16.0),
            Point3::new(0.0, 0.0, 0.0),
            Vector3::unit_z(),
        );

        let (cur_color, cur_depth) = self.views[frame.id()].clone();
        self.data.out_color = cur_color;
        self.data.out_depth = cur_depth;
        self.data.view = view.into();
        let locals = Locals {
            model: self.data.model,
            view: self.data.view,
            proj: self.data.proj,
        };

        let mut encoder = pool.acquire_graphics_encoder();
        encoder.update_buffer(&self.data.locals, &[locals], 0).unwrap();
        encoder.clear(&self.data.out_color, [0.3, 0.3, 0.3, 1.0]);
        encoder.clear_depth(&self.data.out_depth, 1.0);
        encoder.draw(&self.slice, &self.pso, &self.data);
        encoder.synced_flush(queue, &[semaphore], &[], None);
    }

    fn on_resize(&mut self, window_targets: gfx_app::WindowTargets<B::Resources>) {
        self.views = window_targets.views;
        self.data.proj = cgmath::perspective(
                Deg(60.0f32), window_targets.aspect_ratio, 0.1, 1000.0
            ).into();
    }
}

pub fn main() {
    use gfx_app::Application;
    App::launch_simple("Terrain example");
}
<|endoftext|>


<commit_before>//! Implementation of a simple uTP client and server.

extern crate utp;
use std::io::net::ip::{Ipv4Addr, SocketAddr};

fn usage() {
    println!("Usage: utp [-s|-c] <address> <port>");
}

fn main() {
    use utp::UtpStream;
    use std::from_str::FromStr;
    use std::io::{stdin, stdout, stderr};

    // Defaults
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();

    if args.len() != 2 && args.len() != 4 {
        usage();
        return;
    }

    if args.len() == 4 {
        addr = SocketAddr {
            ip:   FromStr::from_str(args[2].as_slice()).unwrap(),
            port: FromStr::from_str(args[3].as_slice()).unwrap(),
        };
    }

    match args[1].as_slice() {
        "-s" => {
            let mut stream = UtpStream::bind(addr);
            let mut writer = stdout();
            let _ = writeln!(stderr(), "Serving on {}", addr);

            let payload = match stream.read_to_end() {
                Ok(v) => v,
                Err(e) => fail!("{}", e),
            };

            match writer.write(payload.as_slice()) {
                Ok(_) => {},
                Err(e) => fail!("{}", e),
            }
        }
        "-c" => {
            let mut stream = UtpStream::connect(addr);
            let mut reader = stdin();

            let payload = match reader.read_to_end() {
                Ok(v) => v,
                Err(e) => fail!("{}", e),
            };

            match stream.write(payload.as_slice()) {
                Ok(_) => {},
                Err(e) => fail!("{}", e),
            };

            match stream.close() {
                Ok(_) => {},
                Err(e) => fail!("{}", e),
            }
            drop(stream);
        }
        _ => usage(),
    }
}
<commit_msg>Use macro to avoid repeating tedious matching.<commit_after>//! Implementation of a simple uTP client and server.
#![feature(macro_rules)]

extern crate utp;
use std::io::net::ip::{Ipv4Addr, SocketAddr};

macro_rules! iotry(
    ($e:expr) => (match $e { Ok(v) => v, Err(e) => fail!("{}", e), })
)

fn usage() {
    println!("Usage: utp [-s|-c] <address> <port>");
}

fn main() {
    use utp::UtpStream;
    use std::from_str::FromStr;
    use std::io::{stdin, stdout, stderr};

    // Defaults
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();

    if args.len() != 2 && args.len() != 4 {
        usage();
        return;
    }

    if args.len() == 4 {
        addr = SocketAddr {
            ip:   FromStr::from_str(args[2].as_slice()).unwrap(),
            port: FromStr::from_str(args[3].as_slice()).unwrap(),
        };
    }

    match args[1].as_slice() {
        "-s" => {
            let mut stream = UtpStream::bind(addr);
            let mut writer = stdout();
            let _ = writeln!(stderr(), "Serving on {}", addr);

            let payload = iotry!(stream.read_to_end());
            iotry!(writer.write(payload.as_slice()));
        }
        "-c" => {
            let mut stream = UtpStream::connect(addr);
            let mut reader = stdin();

            let payload = iotry!(reader.read_to_end());
            iotry!(stream.write(payload.as_slice()));
            iotry!(stream.close());
            drop(stream);
        }
        _ => usage(),
    }
}
<|endoftext|>


<commit_before> #![crate_id = "github.com/csherratt/snowmew#snowmew-render:0.1"]
#![license = "ASL2"]
#![crate_type = "lib"]
#![comment = "A game engine in rust"]
#![allow(dead_code)]

extern crate std;
extern crate glfw;
extern crate cgmath;
extern crate snowmew;
extern crate cow;
extern crate gl;
extern crate OpenCL;
extern crate ovr = "oculus-vr";
extern crate collections;
extern crate native;
extern crate time;
extern crate libc;
extern crate sync;
extern crate gl_cl;
extern crate position = "snowmew-position";
extern crate graphics = "snowmew-graphics";

use std::ptr;
use std::mem;
use std::comm::{Receiver, Sender, Empty, Disconnected};

use cgmath::matrix::{Matrix, ToMatrix4};
use cgmath::vector::{Vector, Vector3};
use cgmath::rotation::{Rotation3};
use cgmath::angle::{ToRad, deg};

use OpenCL::hl::{CommandQueue, Context, Device};
use sync::Arc;

use snowmew::common::ObjectKey;
use snowmew::camera::Camera;
use snowmew::io::Window;
use position::Positions;
use graphics::Graphics;

pub use config::Config;

use pipeline::{DrawTarget, Pipeline};
use drawlist::{Drawlist, DrawlistStandard};

mod db;
mod shader;
mod vertex_buffer;
mod drawlist;
mod hmd;
mod pipeline;
mod query;
mod compute_accelerator;
mod config;

pub trait RenderData : Graphics + Positions + Clone {}

enum RenderCommand {
    Update(Box<RenderData:Send>, ObjectKey, ObjectKey),
    Waiting(Sender<Option<DrawlistStandard>>),
    Complete(DrawlistStandard),
    Setup(Sender<Option<CommandQueue>>),
    Finish(Sender<()>)
}

fn swap_buffers(disp: &mut Window) {
    disp.swap_buffers();
    unsafe {
        gl::DrawElements(gl::TRIANGLES, 6i32, gl::UNSIGNED_INT, ptr::null());
        let sync = gl::FenceSync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0);
        gl::ClientWaitSync(sync, gl::SYNC_FLUSH_COMMANDS_BIT, 1_000_000_000u64);
        gl::DeleteSync(sync);
    }
}

fn render_task(chan: Sender<RenderCommand>) {
    let (sender, receiver) = channel();
    chan.send(Setup(sender));
    let _ = receiver.recv();

    let (sender, receiver) = channel();
    chan.send(Waiting(sender.clone()));
    loop {
        for dl in receiver.iter() {
            match dl {
                Some(mut dl) => {
                    dl.setup_scene_async();
                    chan.send(Waiting(sender.clone()));
                    chan.send(Complete(dl));
                },
                None => {
                    println!("render task: exiting");
                    return
                }
            }

        }
    }
}

fn render_server(port: Receiver<RenderCommand>, db: Box<RenderData>, window: Window, size: (i32, i32),
                 cl: Option<(Arc<Context>, Arc<CommandQueue>, Arc<Device>)>) {
    let (_, _, queue) = OpenCL::util::create_compute_context_prefer(OpenCL::util::GPUPrefered).unwrap();

    let mut queue = Some(queue);

    let mut db = db::GlState::new(db);
    let mut scene = 0;
    let mut camera = 0;
    let mut window = window;
    let cfg = Config::new(window.get_context_version());

    window.make_context_current();

    let mut pipeline = {
        let (width, height) = size;
        if !window.is_hmd() {
            box pipeline::Defered::new(pipeline::Forward::new(), width as uint, height as uint) as Box<Pipeline>
        } else {
            box pipeline::Hmd::new(
                pipeline::Defered::new(pipeline::Forward::new(), width as uint, height as uint),
                1.,
                window.hmdinfo()
            ) as Box<Pipeline>
        }
    };

    // todo move!
    gl::Enable(gl::SCISSOR_TEST);
    gl::Enable(gl::DEPTH_TEST);
    gl::Enable(gl::CULL_FACE);
    gl::Enable(gl::LINE_SMOOTH);
    gl::Enable(gl::BLEND);
    gl::CullFace(gl::BACK);

    db.load(&cfg);

    //let accl = PositionGlAccelerator::new();

    let mut drawlists = vec!(DrawlistStandard::from_config(&cfg, cl.clone()),
                             DrawlistStandard::from_config(&cfg, cl.clone()));

    let mut num_workers = 1;
    let mut waiting = Vec::new();

    loop {
        let cmd = if drawlists.len() == 0 || waiting.len() == 0 || scene == 0 {
            Some(port.recv())
        } else {
            match port.try_recv() {
                Err(Empty) => None,
                Err(Disconnected) => return,
                Ok(dat) => Some(dat)
            }
        };

        match cmd {
            Some(Setup(ch)) => {
                let mut out = None;
                mem::swap(&mut queue, &mut out);
                ch.send(out)
            },
            Some(Update(new, s, c)) => {
                db.update(new);
                db.load(&cfg);
                scene = s;
                camera = c;
            },
            Some(Waiting(ch)) => {
                if scene != 0 && drawlists.len() != 0 {
                    let mut dl = drawlists.pop().unwrap();
                    dl.bind_scene(db.clone(), scene);
                    ch.send(Some(dl));
                } else {
                    waiting.push(ch);
                }
            },
            Some(Complete(mut dl)) => {
                dl.setup_scene();
                let rot = db.location(camera).unwrap().get().rot;
                let camera_trans = db.position(camera);

                let camera = if window.is_hmd() {
                    let sf = window.sensor_fusion();
                    let rift = sf.get_predicted_orientation(None);
                    let rift = rift.mul_q(&Rotation3::from_axis_angle(&Vector3::new(0f32, 1f32, 0f32), deg(180 as f32).to_rad()));
                    Camera::new(rot.mul_q(&rift), camera_trans.mul_m(&rift.to_matrix4()))
                } else {
                    Camera::new(rot, camera_trans)
                };

                let dt = DrawTarget::new(0, (0, 0), (1280, 800), ~[gl::BACK_LEFT]);

                pipeline.render(&mut dl, &db, &camera.get_matrices(size), &dt);
                swap_buffers(&mut window);
                drawlists.push(dl);
            },
            Some(Finish(ack)) => {
                // flush the port, this should release any
                // async drawlist workers
                println!("render: dropping waiting");
                while waiting.len() > 0 {
                    let c = waiting.pop().unwrap();
                    c.send(None);
                    num_workers -= 1;
                }
                println!("render: waiting for open connections to close");
                while num_workers > 0 {
                    match port.recv() {
                        Waiting(ch) => {
                            num_workers -= 1;
                            ch.send(None)
                        },
                        _ => ()
                    }
                }
                ack.send(());
                println!("render: exiting");
                return;
            },
            None => {
                if drawlists.len() > 0 && waiting.len() > 0 {
                    println!("sending");
                    let ch = waiting.pop().unwrap();
                    let mut dl = drawlists.pop().unwrap();
                    dl.bind_scene(db.clone(), scene);
                    ch.send(Some(dl));
                }
            }
        }
    }
}

pub struct RenderManager {
    ch: Sender<RenderCommand>
}

impl RenderManager {
    fn _new(db: Box<RenderData:Send>, window: Window, size: (i32, i32), dev: Option<Arc<Device>>) -> RenderManager {
        let (sender, receiver) = channel();

        window.make_context_current();
        let cl = match dev {
            Some(dev) => {
                let ctx = gl_cl::create_context(dev.deref());
                match ctx {
                    Some(ctx) => {
                        let queue = ctx.create_command_queue(dev.deref());
                        Some((Arc::new(ctx), Arc::new(queue), dev))
                    }
                    None => None
                }
            },
            None => None
        };
        glfw::make_context_current(None);

        let mut taskopts = std::task::TaskOpts::new();
        taskopts.name = Some("render-main".into_maybe_owned());

        native::task::spawn_opts(taskopts, proc() {
            let db = db;
            let window = window;

            render_server(receiver, db, window, size, cl);
        });

        let mut taskopts = std::task::TaskOpts::new();
        taskopts.name = Some("render worker #0".into_maybe_owned());

        let task_c = sender.clone();
        native::task::spawn_opts(taskopts, proc() {
            render_task(task_c);
        });

        RenderManager { ch: sender }
    }

    pub fn new_cl(db: Box<RenderData:Send>, window: Window, size: (i32, i32), device: Arc<Device>) -> RenderManager {
        RenderManager::_new(db, window, size, Some(device))
    }

    pub fn new(db: Box<RenderData:Send>, window: Window, size: (i32, i32)) -> RenderManager {
        RenderManager::_new(db, window, size, None)
    }

    pub fn update(&mut self, db: Box<RenderData:Send>, scene: ObjectKey, camera: ObjectKey) {
        self.ch.send(Update(db, scene, camera));
    }
}

impl Drop for RenderManager {
    fn drop(&mut self) {
        let (c, p) = channel();
        self.ch.send(Finish(c));
        let _ = self.ch;
        p.recv();
    }
}<commit_msg>Fixed render context outliving the main<commit_after> #![crate_id = "github.com/csherratt/snowmew#snowmew-render:0.1"]
#![license = "ASL2"]
#![crate_type = "lib"]
#![comment = "A game engine in rust"]
#![allow(dead_code)]

extern crate std;
extern crate glfw;
extern crate cgmath;
extern crate snowmew;
extern crate cow;
extern crate gl;
extern crate OpenCL;
extern crate ovr = "oculus-vr";
extern crate collections;
extern crate native;
extern crate time;
extern crate libc;
extern crate sync;
extern crate gl_cl;
extern crate position = "snowmew-position";
extern crate graphics = "snowmew-graphics";

use std::ptr;
use std::mem;
use std::task::{TaskResult, TaskBuilder};
use std::comm::{Receiver, Sender, Empty, Disconnected};

use cgmath::matrix::{Matrix, ToMatrix4};
use cgmath::vector::{Vector3};
use cgmath::rotation::{Rotation3};
use cgmath::angle::{ToRad, deg};

use OpenCL::hl::{CommandQueue, Context, Device};
use sync::Arc;

use snowmew::common::ObjectKey;
use snowmew::camera::Camera;
use snowmew::io::Window;
use position::Positions;
use graphics::Graphics;

pub use config::Config;

use pipeline::{DrawTarget, Pipeline};
use drawlist::{Drawlist, DrawlistStandard};

mod db;
mod shader;
mod vertex_buffer;
mod drawlist;
mod hmd;
mod pipeline;
mod query;
mod compute_accelerator;
mod config;

pub trait RenderData : Graphics + Positions + Clone {}

enum RenderCommand {
    Update(Box<RenderData:Send>, ObjectKey, ObjectKey),
    Waiting(Sender<Option<DrawlistStandard>>),
    Complete(DrawlistStandard),
    Setup(Sender<Option<CommandQueue>>),
    Finish
}

fn swap_buffers(disp: &mut Window) {
    disp.swap_buffers();
    unsafe {
        gl::DrawElements(gl::TRIANGLES, 6i32, gl::UNSIGNED_INT, ptr::null());
        let sync = gl::FenceSync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0);
        gl::ClientWaitSync(sync, gl::SYNC_FLUSH_COMMANDS_BIT, 1_000_000_000u64);
        gl::DeleteSync(sync);
    }
}

fn render_task(chan: Sender<RenderCommand>) {
    let (sender, receiver) = channel();
    chan.send(Setup(sender));
    let _ = receiver.recv();

    let (sender, receiver) = channel();
    chan.send(Waiting(sender.clone()));
    loop {
        for dl in receiver.iter() {
            match dl {
                Some(mut dl) => {
                    dl.setup_scene_async();
                    chan.send(Waiting(sender.clone()));
                    chan.send(Complete(dl));
                },
                None => {
                    println!("render task: exiting");
                    return
                }
            }

        }
    }
}

fn render_server(port: Receiver<RenderCommand>, db: Box<RenderData>, window: Window, size: (i32, i32),
                 cl: Option<(Arc<Context>, Arc<CommandQueue>, Arc<Device>)>) {
    let (_, _, queue) = OpenCL::util::create_compute_context_prefer(OpenCL::util::GPUPrefered).unwrap();

    let mut queue = Some(queue);

    let mut db = db::GlState::new(db);
    let mut scene = 0;
    let mut camera = 0;
    let mut window = window;
    let cfg = Config::new(window.get_context_version());

    window.make_context_current();

    let mut pipeline = {
        let (width, height) = size;
        if !window.is_hmd() {
            box pipeline::Defered::new(pipeline::Forward::new(), width as uint, height as uint) as Box<Pipeline>
        } else {
            box pipeline::Hmd::new(
                pipeline::Defered::new(pipeline::Forward::new(), width as uint, height as uint),
                1.,
                window.hmdinfo()
            ) as Box<Pipeline>
        }
    };

    // todo move!
    gl::Enable(gl::SCISSOR_TEST);
    gl::Enable(gl::DEPTH_TEST);
    gl::Enable(gl::CULL_FACE);
    gl::Enable(gl::LINE_SMOOTH);
    gl::Enable(gl::BLEND);
    gl::CullFace(gl::BACK);

    db.load(&cfg);

    //let accl = PositionGlAccelerator::new();

    let mut drawlists = vec!(DrawlistStandard::from_config(&cfg, cl.clone()),
                             DrawlistStandard::from_config(&cfg, cl.clone()));

    let mut num_workers = 1;
    let mut waiting = Vec::new();

    loop {
        let cmd = if drawlists.len() == 0 || waiting.len() == 0 || scene == 0 {
            Some(port.recv())
        } else {
            match port.try_recv() {
                Err(Empty) => None,
                Err(Disconnected) => return,
                Ok(dat) => Some(dat)
            }
        };

        match cmd {
            Some(Setup(ch)) => {
                let mut out = None;
                mem::swap(&mut queue, &mut out);
                ch.send(out)
            },
            Some(Update(new, s, c)) => {
                db.update(new);
                db.load(&cfg);
                scene = s;
                camera = c;
            },
            Some(Waiting(ch)) => {
                if scene != 0 && drawlists.len() != 0 {
                    let mut dl = drawlists.pop().unwrap();
                    dl.bind_scene(db.clone(), scene);
                    ch.send(Some(dl));
                } else {
                    waiting.push(ch);
                }
            },
            Some(Complete(mut dl)) => {
                dl.setup_scene();
                let rot = db.location(camera).unwrap().get().rot;
                let camera_trans = db.position(camera);

                let camera = if window.is_hmd() {
                    let sf = window.sensor_fusion();
                    let rift = sf.get_predicted_orientation(None);
                    let rift = rift.mul_q(&Rotation3::from_axis_angle(&Vector3::new(0f32, 1f32, 0f32), deg(180 as f32).to_rad()));
                    Camera::new(rot.mul_q(&rift), camera_trans.mul_m(&rift.to_matrix4()))
                } else {
                    Camera::new(rot, camera_trans)
                };

                let dt = DrawTarget::new(0, (0, 0), (1280, 800), ~[gl::BACK_LEFT]);

                pipeline.render(&mut dl, &db, &camera.get_matrices(size), &dt);
                swap_buffers(&mut window);
                drawlists.push(dl);
            },
            Some(Finish) => {
                // flush the port, this should release any
                // async drawlist workers
                println!("render: dropping waiting");
                while waiting.len() > 0 {
                    let c = waiting.pop().unwrap();
                    c.send(None);
                    num_workers -= 1;
                }
                println!("render: waiting for open connections to close");
                while num_workers > 0 {
                    match port.recv() {
                        Waiting(ch) => {
                            num_workers -= 1;
                            ch.send(None)
                        },
                        _ => ()
                    }
                }
                println!("render: exiting");
                return;
            },
            None => {
                if drawlists.len() > 0 && waiting.len() > 0 {
                    println!("sending");
                    let ch = waiting.pop().unwrap();
                    let mut dl = drawlists.pop().unwrap();
                    dl.bind_scene(db.clone(), scene);
                    ch.send(Some(dl));
                }
            }
        }
    }
}

pub struct RenderManager {
    ch: Sender<RenderCommand>,
    render_done: Receiver<TaskResult>
}

impl RenderManager {
    fn _new(db: Box<RenderData:Send>, window: Window, size: (i32, i32), dev: Option<Arc<Device>>) -> RenderManager {
        let (sender, receiver) = channel();

        window.make_context_current();
        let cl = match dev {
            Some(dev) => {
                let ctx = gl_cl::create_context(dev.deref());
                match ctx {
                    Some(ctx) => {
                        let queue = ctx.create_command_queue(dev.deref());
                        Some((Arc::new(ctx), Arc::new(queue), dev))
                    }
                    None => None
                }
            },
            None => None
        };
        glfw::make_context_current(None);

        let mut taskbuilder = TaskBuilder::new();
        taskbuilder = taskbuilder.named("render-main".into_maybe_owned());
        let render_main_result = taskbuilder.future_result();

        taskbuilder.spawn(proc() {
            let db = db;
            let window = window;

            render_server(receiver, db, window, size, cl);
        });

        let mut taskopts = std::task::TaskOpts::new();
        taskopts.name = Some("render worker #0".into_maybe_owned());

        let task_c = sender.clone();
        native::task::spawn_opts(taskopts, proc() {
            render_task(task_c);
        });

        RenderManager {
            ch: sender,
            render_done: render_main_result
        }
    }

    pub fn new_cl(db: Box<RenderData:Send>, window: Window, size: (i32, i32), device: Arc<Device>) -> RenderManager {
        RenderManager::_new(db, window, size, Some(device))
    }

    pub fn new(db: Box<RenderData:Send>, window: Window, size: (i32, i32)) -> RenderManager {
        RenderManager::_new(db, window, size, None)
    }

    pub fn update(&mut self, db: Box<RenderData:Send>, scene: ObjectKey, camera: ObjectKey) {
        self.ch.send(Update(db, scene, camera));
    }
}

impl Drop for RenderManager {
    fn drop(&mut self) {
        self.ch.send(Finish);
        drop(self.render_done.recv());
    }
}<|endoftext|>


<commit_before>use diesel;
use diesel::prelude::*;
use rocket_contrib::{JSON, SerdeError};
use uuid::Uuid;

use data::types::*;
use data::researches::get_research_list;
use data::helper::{get_research_dependency_strings, dependencies_fulfilled};

use helpers::db::DB;
use responses::{APIResponse, bad_request, created, ok};

use models::pod::Pod;
use models::user::User;
use models::research::Research;
use models::resource::Resource;

use schema::queue_entries;
use schema::pods::dsl as pods_dsl;
use schema::queues::dsl as queues_dsl;
use schema::resources::dsl as resources_dsl;
use schema::researches::dsl as research_dsl;
use schema::queue_entries::dsl as queue_entries_dsl;

use models::queue::{QueueEntry, Queue, NewQueueEntry};
use validation::queue::ResearchSerializer;

/// The user needs to be logged in to access this route!
///
/// This route returns the list of all researches and their levels/costs,
/// as well as the current level of the research for the pod of the current user.
#[get("/pod")]
pub fn get_researches(current_user: User, db: DB) -> APIResponse {

    let mut research_list = get_research_list();
    // Create changed pod model and push it to the DB

    let pod = pods_dsl::pods
        .filter(pods_dsl::user_id.eq(current_user.id))
        .get_result::<Pod>(&*db)
        .expect("Failed to get user pod.");

    let pod_result = research_dsl::researches
        .filter(research_dsl::pod_id.eq(pod.id))
        .get_results::<Research>(&*db);

    if pod_result.is_ok() {
        let researches = pod_result.unwrap();
        for research in researches {
            let type_result = ResearchTypes::from_string(&research.name);
            if type_result.is_err() {
                return bad_request()
                           .message(format!("Found research {}, but no matching ResearchType!",
                                            research.name)
                                            .as_str());
            }
            let research_type = type_result.unwrap();
            let list_result = research_list.get_mut(&research_type);
            if list_result.is_none() {
                return bad_request().message(format!("Found type {}, but no matching entry in our research list!", research_type).as_str());
            }

            let mut list_entry = list_result.unwrap();
            list_entry.current_level = research.level;
        }
    }

    ok().message("Research data.").data(json!(&research_list))
}

/// Add a new research to the queue of the pod
/// This endpoint:
/// - Checks if dependencies for research are fulfilled
/// - Checks if there are enough resources
/// - Removes resources from db
#[post("/pod", data = "<research_data>", format = "application/json")]
pub fn start_research(research_data: Result<JSON<ResearchSerializer>, SerdeError>,
                          current_user: User,
                          db: DB)
                          -> APIResponse {

    match research_data {
        // Return specific error if invalid JSON has been sent.
        Err(error) => return bad_request().message(format!("{}", error).as_str()),
        Ok(entry) => {
            // Check if the given research name maps to a research type.
            let result = ResearchTypes::from_string(&entry.research_name);
            match result {
                // Early return if we don't know this research name
                Err(_) => {
                    return bad_request().message(format!("No such research type `{}`",
                                                         entry.research_name)
                                                         .as_str());
                }
                Ok(research_type) => {
                    let dependency_strings = get_research_dependency_strings(&research_type);
                    let mut research_level: i32;
                    let research_list = get_research_list();
                    // Get pod and queue from db
                    let pod = pods_dsl::pods
                        .filter(pods_dsl::user_id.eq(current_user.id))
                        .first::<Pod>(&*db)
                        .unwrap();

                    let research = research_dsl::researches
                        .filter(research_dsl::pod_id.eq(pod.id))
                        .filter(research_dsl::name.eq(research_type.to_string()))
                        .get_result::<Research>(&*db);
                    match research {
                        // Research exists, we don't need to check for dependencies
                        // We just increase the level by 1
                        Ok(research) => {
                            research_level = research.level + 1;
                        }
                        // The research is not yet here. We need to check for dependencies.
                        // We just increase the level by 1
                        Err(_) => {
                            let dependencies = research_dsl::researches
                                .filter(research_dsl::name.eq_any(dependency_strings))
                                .get_results::<Research>(&*db);

                            let fulfilled = dependencies_fulfilled(&research_type,
                                                                   dependencies,
                                                                   &research_list);
                            if !fulfilled {
                                return bad_request().message("Dependencies not fulfilled.");
                            }
                            research_level = 1;
                        }
                    }

                    let queue = queues_dsl::queues
                        .filter(queues_dsl::pod_id.eq(pod.id))
                        .first::<Queue>(&*db)
                        .unwrap();

                    // Check if there already are existing queue entries for this research.
                    // In case there are, we increase the level by the amount of existing entries.
                    let existing_entries: i64 = queue_entries_dsl::queue_entries
                        .count()
                        .filter(queue_entries_dsl::queue_id.eq(queue.id))
                        .filter(queue_entries_dsl::research_name.eq(research_type.to_string()))
                        .get_result(&*db)
                        .unwrap_or(0);

                    let pod_resources = resources_dsl::resources
                        .filter(resources_dsl::pod_id.eq(pod.id))
                        .get_results(&*db)
                        .expect("Failed to get user resources.");

                    research_level += existing_entries as i32;

                    let all_levels = &research_list
                                          .get(&research_type)
                                          .as_ref()
                                          .expect("No research in yml for this type.")
                                          .levels;

                    if !(all_levels.len() <= research_level as usize) {
                        return bad_request().message("Already at max level.");
                    }
                    let costs = &all_levels[research_level as usize].resources;
                    if costs.is_some() && !Resource::check_resources(costs, pod_resources, &db) {
                        return bad_request().message("Insufficient resources.");
                    }

                    // Create a new queue entry with the given research type.
                    let new_entry_model = NewQueueEntry {
                        queue_id: queue.id.clone(),
                        research_name: Some(entry.research_name.clone()),
                        module_name: None,
                        module_id: None,
                        level: research_level,
                    };

                    let new_queue_entry = diesel::insert(&new_entry_model)
                        .into(queue_entries::table)
                        .get_result::<QueueEntry>(&*db)
                        .expect("Failed to insert new queue entry.");

                    created()
                        .message("Queue entry added.")
                        .data(json!(&new_queue_entry))
                }
            }
        }
    }
}

/// Remove research from queue
#[delete("/pod/<entry_uuid>")]
pub fn stop_research(entry_uuid: &str, current_user: User, db: DB) -> APIResponse {

    // Parse and check if we got a valid id
    let result = Uuid::parse_str(entry_uuid);
    if result.is_err() {
        return bad_request().message("Got an invalid uuid");
    }
    let queue_entry_id = result.unwrap();

    // Get the queue entry
    let queue_entry_result = queue_entries_dsl::queue_entries
        .filter(queue_entries_dsl::id.eq(queue_entry_id))
        .first::<QueueEntry>(&*db);
    if queue_entry_result.is_err() {
        return bad_request().message("No queue entry with this id.");
    }
    let queue_entry = queue_entry_result.unwrap();

    // Check if we got an research queue entry
    if queue_entry.research_name.is_none() {
        return bad_request().message("Queue entry is a model queue entry.");
    }

    // Check if there already are existing queue entries for this research.
    // If there are entries with a higher level, we return a bad request.
    let level = queue_entry.level;
    let name = queue_entry.research_name.unwrap();
    let higher_entry = queue_entries_dsl::queue_entries
        .filter(queue_entries_dsl::queue_id.eq(queue_entry.queue_id))
        .filter(queue_entries_dsl::research_name.eq(&name))
        .filter(queue_entries_dsl::level.gt(queue_entry.level))
        .get_result::<QueueEntry>(&*db);
    if higher_entry.is_ok() {
        return bad_request().message("Can't delete. There is an queue entry with a higher level for this research.");
    }

    // Get all needed info for resource manipulation
    let research_list = get_research_list();

    let pod = pods_dsl::pods
        .filter(pods_dsl::user_id.eq(current_user.id))
        .first::<Pod>(&*db)
        .unwrap();

    let pod_resources = resources_dsl::resources
        .filter(resources_dsl::pod_id.eq(pod.id))
        .get_results::<Resource>(&*db)
        .expect("Failed to get user resources.");

    // Add resources from research to pod resources
    let all_levels = &research_list
                          .get(&ResearchTypes::from_string(&name).unwrap())
                          .unwrap()
                          .levels;
    let costs_result = &all_levels[level as usize].resources;

    if let Some(ref costs) = *costs_result {
        Resource::update_resources(costs, pod_resources, false, &db);
    }

    // Remove queue_entry from database
    diesel::delete(queue_entries_dsl::queue_entries
                       .filter(queue_entries_dsl::id.eq(queue_entry_id)))
            .execute(&*db)
            .expect("Failed to remove queue_entry.");

    ok().message("Resource removed.")
}
<commit_msg>Refactor start_research route<commit_after>use diesel;
use diesel::prelude::*;
use rocket_contrib::{JSON, SerdeError};
use uuid::Uuid;

use data::types::*;
use data::researches::get_research_list;
use data::helper::{get_research_dependency_strings, dependencies_fulfilled};

use helpers::db::DB;
use responses::{APIResponse, bad_request, created, ok};

use models::pod::Pod;
use models::user::User;
use models::research::Research;
use models::resource::Resource;

use schema::queue_entries;
use schema::pods::dsl as pods_dsl;
use schema::queues::dsl as queues_dsl;
use schema::resources::dsl as resources_dsl;
use schema::researches::dsl as research_dsl;
use schema::queue_entries::dsl as queue_entries_dsl;

use models::queue::{QueueEntry, Queue, NewQueueEntry};
use validation::queue::ResearchSerializer;

/// The user needs to be logged in to access this route!
///
/// This route returns the list of all researches and their levels/costs,
/// as well as the current level of the research for the pod of the current user.
#[get("/pod")]
pub fn get_researches(current_user: User, db: DB) -> APIResponse {

    let mut research_list = get_research_list();
    // Create changed pod model and push it to the DB

    let pod = pods_dsl::pods
        .filter(pods_dsl::user_id.eq(current_user.id))
        .get_result::<Pod>(&*db)
        .expect("Failed to get user pod.");

    let pod_result = research_dsl::researches
        .filter(research_dsl::pod_id.eq(pod.id))
        .get_results::<Research>(&*db);

    if pod_result.is_ok() {
        let researches = pod_result.unwrap();
        for research in researches {
            let type_result = ResearchTypes::from_string(&research.name);
            if type_result.is_err() {
                return bad_request()
                           .message(format!("Found research {}, but no matching ResearchType!",
                                            research.name)
                                            .as_str());
            }
            let research_type = type_result.unwrap();
            let list_result = research_list.get_mut(&research_type);
            if list_result.is_none() {
                return bad_request().message(format!("Found type {}, but no matching entry in our research list!", research_type).as_str());
            }

            let mut list_entry = list_result.unwrap();
            list_entry.current_level = research.level;
        }
    }

    ok().message("Research data.").data(json!(&research_list))
}

/// Add a new research to the queue of the pod
/// This endpoint:
/// - Checks if dependencies for research are fulfilled
/// - Checks if there are enough resources
/// - Removes resources from db
#[post("/pod", data = "<request_data>", format = "application/json")]
pub fn start_research(request_data: Result<JSON<ResearchSerializer>, SerdeError>,
                          current_user: User,
                          db: DB)
                          -> APIResponse {

    // Unwrap or return specific error if invalid JSON has been sent.
    if let Err(error) = request_data {
        return bad_request().message(format!("{}", error).as_str());
    };
    let research_data = request_data.unwrap();

    // Check if the given research name maps to a research type.
    let research_result = ResearchTypes::from_string(&research_data.research_name);

    // Early return if we don't know this research name
    if research_result.is_err() {
        return bad_request().message(format!("No such research type `{}`",
                                             research_data.research_name)
                                             .as_str());
    }
    let research_type =  research_result.unwrap();
    let dependency_strings = get_research_dependency_strings(&research_type);
    let mut research_level: i32;
    let research_list = get_research_list();
    // Get pod and queue from db
    let pod = pods_dsl::pods
        .filter(pods_dsl::user_id.eq(current_user.id))
        .first::<Pod>(&*db)
        .unwrap();

    let research = research_dsl::researches
        .filter(research_dsl::pod_id.eq(pod.id))
        .filter(research_dsl::name.eq(research_type.to_string()))
        .get_result::<Research>(&*db);

    match research {
        // Research exists, we don't need to check for dependencies
        // We just increase the level by 1
        Ok(research) => {
            research_level = research.level + 1;
        }
        // The research is not yet here. We need to check for dependencies.
        // We just increase the level by 1
        Err(_) => {
            let dependencies = research_dsl::researches
                .filter(research_dsl::name.eq_any(dependency_strings))
                .get_results::<Research>(&*db);

            let fulfilled = dependencies_fulfilled(&research_type,
                                                   dependencies,
                                                   &research_list);
            if !fulfilled {
                return bad_request().message("Dependencies not fulfilled.");
            }
            research_level = 1;
        }
    }

    let queue = queues_dsl::queues
        .filter(queues_dsl::pod_id.eq(pod.id))
        .first::<Queue>(&*db)
        .unwrap();

    // Check if there already are existing queue entries for this research.
    // In case there are, we increase the level by the amount of existing entries.
    let existing_entries: i64 = queue_entries_dsl::queue_entries
        .count()
        .filter(queue_entries_dsl::queue_id.eq(queue.id))
        .filter(queue_entries_dsl::research_name.eq(research_type.to_string()))
        .get_result(&*db)
        .unwrap_or(0);

    let pod_resources = resources_dsl::resources
        .filter(resources_dsl::pod_id.eq(pod.id))
        .get_results(&*db)
        .expect("Failed to get user resources.");

    research_level += existing_entries as i32;

    let all_levels = &research_list
                          .get(&research_type)
                          .as_ref()
                          .expect("No research in yml for this type.")
                          .levels;

    if !(all_levels.len() <= research_level as usize) {
        return bad_request().message("Already at max level.");
    }
    let costs = &all_levels[research_level as usize].resources;
    if costs.is_some() && !Resource::check_resources(costs, pod_resources, &db) {
        return bad_request().message("Insufficient resources.");
    }

    // Create a new queue entry with the given research type.
    let new_entry_model = NewQueueEntry {
        queue_id: queue.id.clone(),
        research_name: Some(research_data.research_name.clone()),
        module_name: None,
        module_id: None,
        level: research_level,
    };

    let new_queue_entry = diesel::insert(&new_entry_model)
        .into(queue_entries::table)
        .get_result::<QueueEntry>(&*db)
        .expect("Failed to insert new queue entry.");

    created()
        .message("Queue entry added.")
        .data(json!(&new_queue_entry))
}

/// Remove research from queue
#[delete("/pod/<entry_uuid>")]
pub fn stop_research(entry_uuid: &str, current_user: User, db: DB) -> APIResponse {

    // Parse and check if we got a valid id
    let result = Uuid::parse_str(entry_uuid);
    if result.is_err() {
        return bad_request().message("Got an invalid uuid");
    }
    let queue_entry_id = result.unwrap();

    // Get the queue entry
    let queue_entry_result = queue_entries_dsl::queue_entries
        .filter(queue_entries_dsl::id.eq(queue_entry_id))
        .first::<QueueEntry>(&*db);
    if queue_entry_result.is_err() {
        return bad_request().message("No queue entry with this id.");
    }
    let queue_entry = queue_entry_result.unwrap();

    // Check if we got an research queue entry
    if queue_entry.research_name.is_none() {
        return bad_request().message("Queue entry is a model queue entry.");
    }

    // Check if there already are existing queue entries for this research.
    // If there are entries with a higher level, we return a bad request.
    let level = queue_entry.level;
    let name = queue_entry.research_name.unwrap();
    let higher_entry = queue_entries_dsl::queue_entries
        .filter(queue_entries_dsl::queue_id.eq(queue_entry.queue_id))
        .filter(queue_entries_dsl::research_name.eq(&name))
        .filter(queue_entries_dsl::level.gt(queue_entry.level))
        .get_result::<QueueEntry>(&*db);
    if higher_entry.is_ok() {
        return bad_request().message("Can't delete. There is an queue entry with a higher level for this research.");
    }

    // Get all needed info for resource manipulation
    let research_list = get_research_list();

    let pod = pods_dsl::pods
        .filter(pods_dsl::user_id.eq(current_user.id))
        .first::<Pod>(&*db)
        .unwrap();

    let pod_resources = resources_dsl::resources
        .filter(resources_dsl::pod_id.eq(pod.id))
        .get_results::<Resource>(&*db)
        .expect("Failed to get user resources.");

    // Add resources from research to pod resources
    let all_levels = &research_list
                          .get(&ResearchTypes::from_string(&name).unwrap())
                          .unwrap()
                          .levels;
    let costs_result = &all_levels[level as usize].resources;

    if let Some(ref costs) = *costs_result {
        Resource::update_resources(costs, pod_resources, false, &db);
    }

    // Remove queue_entry from database
    diesel::delete(queue_entries_dsl::queue_entries
                       .filter(queue_entries_dsl::id.eq(queue_entry_id)))
            .execute(&*db)
            .expect("Failed to remove queue_entry.");

    ok().message("Resource removed.")
}
<|endoftext|>


<commit_before>#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
#![allow(unused_variables, dead_code)]

use libc;
use api::osmesa::{OsMesaContext};

use {Api, ContextError, CreationError, GlAttributes, PixelFormat, PixelFormatRequirements};

use std::path::Path;
use std::ptr;

mod ffi;

pub struct Context {
    opengl: OsMesaContext,
    libcaca: ffi::LibCaca,
    display: *mut ffi::caca_display_t,
    dither: *mut ffi::caca_dither_t,
}

impl Context {

    pub fn new(
        window_outer_size: (u32, u32),
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Context>,
    ) -> Result<Self, CreationError>
    {
        let gl_attr = gl_attr.clone().map_sharing(|w| &w.opengl);
        let opengl = OsMesaContext::new(window_outer_size, pf_reqs, &gl_attr)?;

        let opengl_dimensions = opengl.get_dimensions();

        let libcaca = match ffi::LibCaca::open(&Path::new("libcaca.so.0")) {
            Err(_) => return Err(CreationError::NotSupported),
            Ok(l) => l
        };

        let display = unsafe { (libcaca.caca_create_display)(ptr::null_mut()) };

        if display.is_null() {
            return Err(CreationError::OsError("caca_create_display failed".to_string()));
        }

        let dither = unsafe {
            #[cfg(target_endian = "little")]
            fn get_masks() -> (u32, u32, u32, u32) { (0xff, 0xff00, 0xff0000, 0xff000000) }
            #[cfg(target_endian = "big")]
            fn get_masks() -> (u32, u32, u32, u32) { (0xff000000, 0xff0000, 0xff00, 0xff) }

            let masks = get_masks();
            (libcaca.caca_create_dither)(32, opengl_dimensions.0 as libc::c_int,
                                         opengl_dimensions.1 as libc::c_int,
                                         opengl_dimensions.0 as libc::c_int * 4,
                                         masks.0, masks.1, masks.2, masks.3)
        };

        if dither.is_null() {
            unsafe { (libcaca.caca_free_display)(display) };
            return Err(CreationError::OsError("caca_create_dither failed".to_string()));
        }

        Ok(Context {
            libcaca: libcaca,
            display: display,
            opengl: opengl,
            dither: dither,
        })
    }

    #[inline]
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        self.opengl.make_current()
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        self.opengl.is_current()
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        self.opengl.get_proc_address(addr)
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        unsafe {
            let canvas = (self.libcaca.caca_get_canvas)(self.display);
            let width = (self.libcaca.caca_get_canvas_width)(canvas);
            let height = (self.libcaca.caca_get_canvas_height)(canvas);

            let buffer = self.opengl.get_framebuffer().chunks(self.opengl.get_dimensions().0 as usize)
                                    .flat_map(|i| i.iter().cloned()).rev().collect::<Vec<u32>>();

            (self.libcaca.caca_dither_bitmap)(canvas, 0, 0, width as libc::c_int,
                                              height as libc::c_int, self.dither,
                                              buffer.as_ptr() as *const _);
            (self.libcaca.caca_refresh_display)(self.display);
        };

        Ok(())
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        self.opengl.get_api()
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        self.opengl.get_pixel_format()
    }

}

impl Drop for Context {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            (self.libcaca.caca_free_dither)(self.dither);
            (self.libcaca.caca_free_display)(self.display);
        }
    }
}

// pub struct Window {
//     libcaca: ffi::LibCaca,
//     display: *mut ffi::caca_display_t,
//     opengl: OsMesaContext,
//     dither: *mut ffi::caca_dither_t,
// }
//
// #[derive(Clone)]
// pub struct WindowProxy;
//
// impl WindowProxy {
//     #[inline]
//     pub fn wakeup_event_loop(&self) {
//         unimplemented!()
//     }
// }
//
// pub struct MonitorId;
//
// #[inline]
// pub fn get_available_monitors() -> VecDeque<MonitorId> {
//     VecDeque::new()
// }
// #[inline]
// pub fn get_primary_monitor() -> MonitorId {
//     MonitorId
// }
//
// impl MonitorId {
//     #[inline]
//     pub fn get_name(&self) -> Option<String> {
//         unimplemented!();
//     }
//
//     #[inline]
//     pub fn get_native_identifier(&self) -> ::winit::NativeMonitorId {
//         ::winit::NativeMonitorId::Unavailable
//     }
//
//     #[inline]
//     pub fn get_dimensions(&self) -> (u32, u32) {
//         unimplemented!();
//     }
// }
//
// pub struct PollEventsIterator<'a> {
//     window: &'a Window,
// }
//
// impl<'a> Iterator for PollEventsIterator<'a> {
//     type Item = Event;
//
//     #[inline]
//     fn next(&mut self) -> Option<Event> {
//         None
//     }
// }
//
// pub struct WaitEventsIterator<'a> {
//     window: &'a Window,
// }
//
// impl<'a> Iterator for WaitEventsIterator<'a> {
//     type Item = Event;
//
//     #[inline]
//     fn next(&mut self) -> Option<Event> {
//         loop {}
//     }
// }

// impl Window {
//     pub fn new(window: &WindowAttributes, pf_reqs: &PixelFormatRequirements,
//                opengl: &GlAttributes<&Window>) -> Result<Window, CreationError>
//     {
//         let opengl = opengl.clone().map_sharing(|w| &w.opengl);
//
//         let opengl = OsMesaContext::new(window.dimensions.unwrap_or((800, 600)), pf_reqs,
//                                         &opengl)?;
//
//         let opengl_dimensions = opengl.get_dimensions();
//
//         let libcaca = match ffi::LibCaca::open(&Path::new("libcaca.so.0")) {
//             Err(_) => return Err(CreationError::NotSupported),
//             Ok(l) => l
//         };
//
//         let display = unsafe { (libcaca.caca_create_display)(ptr::null_mut()) };
//
//         if display.is_null() {
//             return Err(CreationError::OsError("caca_create_display failed".to_string()));
//         }
//
//         let dither = unsafe {
//             #[cfg(target_endian = "little")]
//             fn get_masks() -> (u32, u32, u32, u32) { (0xff, 0xff00, 0xff0000, 0xff000000) }
//             #[cfg(target_endian = "big")]
//             fn get_masks() -> (u32, u32, u32, u32) { (0xff000000, 0xff0000, 0xff00, 0xff) }
//
//             let masks = get_masks();
//             (libcaca.caca_create_dither)(32, opengl_dimensions.0 as libc::c_int,
//                                          opengl_dimensions.1 as libc::c_int,
//                                          opengl_dimensions.0 as libc::c_int * 4,
//                                          masks.0, masks.1, masks.2, masks.3)
//         };
//
//         if dither.is_null() {
//             unsafe { (libcaca.caca_free_display)(display) };
//             return Err(CreationError::OsError("caca_create_dither failed".to_string()));
//         }
//
//         Ok(Window {
//             libcaca: libcaca,
//             display: display,
//             opengl: opengl,
//             dither: dither,
//         })
//     }
//
//     #[inline]
//     pub fn set_title(&self, title: &str) {
//     }
//
//     #[inline]
//     pub fn show(&self) {
//     }
//
//     #[inline]
//     pub fn hide(&self) {
//     }
//
//     #[inline]
//     pub fn get_position(&self) -> Option<(i32, i32)> {
//         unimplemented!()
//     }
//
//     #[inline]
//     pub fn set_position(&self, x: i32, y: i32) {
//     }
//
//     #[inline]
//     pub fn get_inner_size(&self) -> Option<(u32, u32)> {
//         Some(self.opengl.get_dimensions())
//     }
//
//     #[inline]
//     pub fn get_outer_size(&self) -> Option<(u32, u32)> {
//         self.get_inner_size()
//     }
//
//     #[inline]
//     pub fn set_inner_size(&self, _x: u32, _y: u32) {
//         unimplemented!()
//     }
//
//     #[inline]
//     pub fn create_window_proxy(&self) -> WindowProxy {
//         unimplemented!()
//     }
//
//     #[inline]
//     pub fn poll_events(&self) -> PollEventsIterator {
//         PollEventsIterator {
//             window: self
//         }
//     }
//
//     #[inline]
//     pub fn wait_events(&self) -> WaitEventsIterator {
//         WaitEventsIterator {
//             window: self
//         }
//     }
//
//     #[inline]
//     pub fn platform_display(&self) -> *mut libc::c_void {
//         unimplemented!()
//     }
//
//     #[inline]
//     pub fn platform_window(&self) -> *mut libc::c_void {
//         unimplemented!()
//     }
//
//     #[inline]
//     pub fn get_pixel_format(&self) -> PixelFormat {
//         unimplemented!();
//     }
//
//     #[inline]
//     pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) {
//     }
//
//     #[inline]
//     pub fn set_cursor(&self, cursor: MouseCursor) {
//     }
//
//     #[inline]
//     pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
//         Ok(())
//     }
//
//     #[inline]
//     pub fn hidpi_factor(&self) -> f32 {
//         1.0
//     }
//
//     #[inline]
//     pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
//         Ok(())
//     }
// }
//
// impl GlContext for Window {
//     #[inline]
//     unsafe fn make_current(&self) -> Result<(), ContextError> {
//         self.opengl.make_current()
//     }
//
//     #[inline]
//     fn is_current(&self) -> bool {
//         self.opengl.is_current()
//     }
//
//     #[inline]
//     fn get_proc_address(&self, addr: &str) -> *const () {
//         self.opengl.get_proc_address(addr)
//     }
//
//     #[inline]
//     fn swap_buffers(&self) -> Result<(), ContextError> {
//         unsafe {
//             let canvas = (self.libcaca.caca_get_canvas)(self.display);
//             let width = (self.libcaca.caca_get_canvas_width)(canvas);
//             let height = (self.libcaca.caca_get_canvas_height)(canvas);
//
//             let buffer = self.opengl.get_framebuffer().chunks(self.opengl.get_dimensions().0 as usize)
//                                     .flat_map(|i| i.iter().cloned()).rev().collect::<Vec<u32>>();
//
//             (self.libcaca.caca_dither_bitmap)(canvas, 0, 0, width as libc::c_int,
//                                               height as libc::c_int, self.dither,
//                                               buffer.as_ptr() as *const _);
//             (self.libcaca.caca_refresh_display)(self.display);
//         };
//
//         Ok(())
//     }
//
//     #[inline]
//     fn get_api(&self) -> Api {
//         self.opengl.get_api()
//     }
//
//     #[inline]
//     fn get_pixel_format(&self) -> PixelFormat {
//         self.opengl.get_pixel_format()
//     }
// }

// impl Drop for Window {
//     #[inline]
//     fn drop(&mut self) {
//         unsafe {
//             (self.libcaca.caca_free_dither)(self.dither);
//             (self.libcaca.caca_free_display)(self.display);
//         }
//     }
// }
<commit_msg>Remove old commented window code from caca module<commit_after>#![cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
#![allow(unused_variables, dead_code)]

use libc;
use api::osmesa::{OsMesaContext};

use {Api, ContextError, CreationError, GlAttributes, PixelFormat, PixelFormatRequirements};

use std::path::Path;
use std::ptr;

mod ffi;

pub struct Context {
    opengl: OsMesaContext,
    libcaca: ffi::LibCaca,
    display: *mut ffi::caca_display_t,
    dither: *mut ffi::caca_dither_t,
}

impl Context {

    pub fn new(
        window_outer_size: (u32, u32),
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Context>,
    ) -> Result<Self, CreationError>
    {
        let gl_attr = gl_attr.clone().map_sharing(|w| &w.opengl);
        let opengl = OsMesaContext::new(window_outer_size, pf_reqs, &gl_attr)?;

        let opengl_dimensions = opengl.get_dimensions();

        let libcaca = match ffi::LibCaca::open(&Path::new("libcaca.so.0")) {
            Err(_) => return Err(CreationError::NotSupported),
            Ok(l) => l
        };

        let display = unsafe { (libcaca.caca_create_display)(ptr::null_mut()) };

        if display.is_null() {
            return Err(CreationError::OsError("caca_create_display failed".to_string()));
        }

        let dither = unsafe {
            #[cfg(target_endian = "little")]
            fn get_masks() -> (u32, u32, u32, u32) { (0xff, 0xff00, 0xff0000, 0xff000000) }
            #[cfg(target_endian = "big")]
            fn get_masks() -> (u32, u32, u32, u32) { (0xff000000, 0xff0000, 0xff00, 0xff) }

            let masks = get_masks();
            (libcaca.caca_create_dither)(32, opengl_dimensions.0 as libc::c_int,
                                         opengl_dimensions.1 as libc::c_int,
                                         opengl_dimensions.0 as libc::c_int * 4,
                                         masks.0, masks.1, masks.2, masks.3)
        };

        if dither.is_null() {
            unsafe { (libcaca.caca_free_display)(display) };
            return Err(CreationError::OsError("caca_create_dither failed".to_string()));
        }

        Ok(Context {
            libcaca: libcaca,
            display: display,
            opengl: opengl,
            dither: dither,
        })
    }

    #[inline]
    unsafe fn make_current(&self) -> Result<(), ContextError> {
        self.opengl.make_current()
    }

    #[inline]
    pub fn is_current(&self) -> bool {
        self.opengl.is_current()
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const () {
        self.opengl.get_proc_address(addr)
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        unsafe {
            let canvas = (self.libcaca.caca_get_canvas)(self.display);
            let width = (self.libcaca.caca_get_canvas_width)(canvas);
            let height = (self.libcaca.caca_get_canvas_height)(canvas);

            let buffer = self.opengl.get_framebuffer().chunks(self.opengl.get_dimensions().0 as usize)
                                    .flat_map(|i| i.iter().cloned()).rev().collect::<Vec<u32>>();

            (self.libcaca.caca_dither_bitmap)(canvas, 0, 0, width as libc::c_int,
                                              height as libc::c_int, self.dither,
                                              buffer.as_ptr() as *const _);
            (self.libcaca.caca_refresh_display)(self.display);
        };

        Ok(())
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        self.opengl.get_api()
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        self.opengl.get_pixel_format()
    }

}

impl Drop for Context {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            (self.libcaca.caca_free_dither)(self.dither);
            (self.libcaca.caca_free_display)(self.display);
        }
    }
}
<|endoftext|>


<commit_before>use slack::{Event, RtmClient, EventHandler, Message};
use router::{Router,Rule};

pub struct TelescreenHandler {
    router: Router,
}

impl TelescreenHandler {
    pub fn new(router: Router) -> TelescreenHandler {
        TelescreenHandler { router: router }
    }
}

#[allow(unused_variables)]
impl EventHandler for TelescreenHandler {
    fn on_event(&mut self, cli: &RtmClient, event: Event) {
        match event {
            Event::Message(event) => {
                match *event {
                    Message::Standard(message) => {
                        let source_user_id = match message.user {
                            None => { println!("No user: {:?}", message.user); return },
                            Some(u) => u,
                        };
                        let source_channel_id = match message.channel {
                            None => { println!("No channel: {:?}", message.channel); return },
                            Some(c) => c,
                        };
                        let source_text = match message.text {
                            None => { println!("No text: {:?}", message.text); return },
                            Some(t) => t,
                        };

                        let source_user_name = cli.start_response()
                            .users
                            .as_ref()
                            .and_then(|users| {
                                users.iter().find(|user| match user.id {
                                    None => false,
                                    Some(ref name) => name.to_string() == source_user_id,
                                })
                            }).and_then(|user| user.name.as_ref());

                        let unwrapped_source_user_name = match source_user_name {
                            None => { println!("No user: {:?}", source_user_name); return },
                            Some(t) => t,
                        };

                        let channel_name = cli.start_response().channels.as_ref()
                            .and_then(|channels| {
                                channels.iter().find(|chan| match chan.id {
                                    None => false,
                                    Some(ref id) => { id == &source_channel_id },
                                })
                            })
                            .and_then(|chan| chan.name.as_ref());

                        let unwrapped_channel_name = match channel_name {
                            None => { println!("No channel: {:?}", source_channel_id); return },
                            Some(c) => c,
                        };

                        let rules: &Vec<Rule> = self.router.rules.as_ref();
                        for rule in rules {
                            if rule.regex.is_match(unwrapped_channel_name) {
                                let dest_channel_id = cli.start_response().channels.as_ref()
                                    .and_then(|channels| {
                                        channels.iter().find(|chan| match chan.name {
                                            None => false,
                                            Some(ref name) => name == &(rule.destination),
                                        })
                                    })
                                    .and_then(|chan| chan.id.as_ref());

                                let dest_channel_id_unwrap = match dest_channel_id {
                                    None => { println!("No channel: {:?}", dest_channel_id); return },
                                    Some(c) => c,
                                };

                                if unwrapped_channel_name != &(rule.destination) {
                                    let message = format!("{:} (#{}): {:}", unwrapped_source_user_name, unwrapped_channel_name, source_text);
                                    let _ = cli.sender().send_message(&dest_channel_id_unwrap, &message);
                                }
                            }
                        }
                    },
                    _ => { /* noop */ },
                }
            },
            _ => { /* noop */ },
        }
    }

    fn on_close(&mut self, cli: &RtmClient) {
        println!("Disconnected");
    }

    fn on_connect(&mut self, cli: &RtmClient) {
        println!("Connected");
    }
}
<commit_msg>Bring sending message logic out as a function<commit_after>use slack::{Event, RtmClient, EventHandler, Message};
use router::{Router,Rule};

pub struct TelescreenHandler {
    router: Router,
}

impl TelescreenHandler {
    pub fn new(router: Router) -> TelescreenHandler {
        TelescreenHandler { router: router }
    }

    pub fn send_message(&self, cli: &RtmClient, unwrapped_channel_name: &str, unwrapped_source_user_name: &str, source_text: &str) {
        let rules: &Vec<Rule> = self.router.rules.as_ref();
        for rule in rules {
            if rule.regex.is_match(unwrapped_channel_name) {
                let dest_channel_id = cli.start_response().channels.as_ref()
                    .and_then(|channels| {
                        channels.iter().find(|chan| match chan.name {
                            None => false,
                            Some(ref name) => name == &(rule.destination),
                        })
                    })
                    .and_then(|chan| chan.id.as_ref());

                let dest_channel_id_unwrap = match dest_channel_id {
                    None => { println!("No channel: {:?}", dest_channel_id); return },
                    Some(c) => c,
                };

                if unwrapped_channel_name != &(rule.destination) {
                    let message = format!("{:} [ #{} ]: {:}", unwrapped_source_user_name, unwrapped_channel_name, source_text);
                    let _ = cli.sender().send_message(&dest_channel_id_unwrap, &message);
                }
            }
        }
    }
}

#[allow(unused_variables)]
impl EventHandler for TelescreenHandler {
    fn on_event(&mut self, cli: &RtmClient, event: Event) {
        match event {
            Event::Message(event) => {
                match *event {
                    Message::Standard(message) => {
                        let source_user_id = match message.user {
                            None => { println!("No user: {:?}", message.user); return },
                            Some(u) => u,
                        };
                        let source_channel_id = match message.channel {
                            None => { println!("No channel: {:?}", message.channel); return },
                            Some(c) => c,
                        };
                        let source_text = match message.text {
                            None => { println!("No text: {:?}", message.text); return },
                            Some(t) => t,
                        };

                        let source_user_name = cli.start_response()
                            .users
                            .as_ref()
                            .and_then(|users| {
                                users.iter().find(|user| match user.id {
                                    None => false,
                                    Some(ref name) => name.to_string() == source_user_id,
                                })
                            }).and_then(|user| user.name.as_ref());

                        let unwrapped_source_user_name = match source_user_name {
                            None => { println!("No user: {:?}", source_user_name); return },
                            Some(t) => t,
                        };

                        let channel_name = cli.start_response().channels.as_ref()
                            .and_then(|channels| {
                                channels.iter().find(|chan| match chan.id {
                                    None => false,
                                    Some(ref id) => { id == &source_channel_id },
                                })
                            })
                            .and_then(|chan| chan.name.as_ref());

                        let unwrapped_channel_name = match channel_name {
                            None => { println!("No channel: {:?}", source_channel_id); return },
                            Some(c) => c,
                        };

                        self.send_message(cli, unwrapped_channel_name, unwrapped_source_user_name, &source_text);
                    },
                    _ => { /* noop */ },
                }
            },
            _ => { /* noop */ },
        }
    }

    fn on_close(&mut self, cli: &RtmClient) {
        println!("Disconnected");
    }

    fn on_connect(&mut self, cli: &RtmClient) {
        println!("Connected");
    }
}
<|endoftext|>