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

use std::marker::PhantomData;
use std::collections::HashMap;
use std::any::Any;
use std::cell::{RefCell, Ref};
use std::sync::{Arc, Mutex};
use std::fs;
use std::io::{BufWriter, Write, BufRead, BufReader};
use log;

use ui;
use render;
use format::{Component, TextComponent, Color};

const FILTERED_CRATES: &'static [&'static str] = &[
    "hyper",
    "mime",
];

pub struct CVar<T: Sized + Any + 'static> {
    pub name: &'static str,
    pub ty: PhantomData<T>,
    pub description: &'static str,
    pub mutable: bool,
    pub serializable: bool,
    pub default: &'static Fn() -> T,
}

impl Var for CVar<i64> {
    fn serialize(&self, val: &Box<Any>) -> String {
        val.downcast_ref::<i64>().unwrap().to_string()
    }

    fn deserialize(&self, input: &str) -> Box<Any> {
        Box::new(input.parse::<i64>().unwrap())
    }

    fn description(&self) -> &'static str {
        self.description
    }

    fn can_serialize(&self) -> bool {
        self.serializable
    }
}

impl Var for CVar<bool> {
    fn serialize(&self, val: &Box<Any>) -> String {
        val.downcast_ref::<bool>().unwrap().to_string()
    }

    fn deserialize(&self, input: &str) -> Box<Any> {
        Box::new(input.parse::<bool>().unwrap())
    }

    fn description(&self) -> &'static str {
        self.description
    }

    fn can_serialize(&self) -> bool {
        self.serializable
    }
}

impl Var for CVar<String> {
    fn serialize(&self, val: &Box<Any>) -> String {
        format!("\"{}\"", val.downcast_ref::<String>().unwrap())
    }

    fn deserialize(&self, input: &str) -> Box<Any> {
        Box::new((&input[1..input.len() - 1]).to_owned())
    }

    fn description(&self) -> &'static str {
        self.description
    }
    fn can_serialize(&self) -> bool {
        self.serializable
    }
}

pub trait Var {
    fn serialize(&self, val: &Box<Any>) -> String;
    fn deserialize(&self, input: &str) -> Box<Any>;
    fn description(&self) -> &'static str;
    fn can_serialize(&self) -> bool;
}

pub struct Vars {
    names: HashMap<String, &'static str>,
    vars: HashMap<&'static str, Box<Var>>,
    var_values: HashMap<&'static str, RefCell<Box<Any>>>,
}

impl Vars {
    pub fn new() -> Vars {
        Vars {
            names: HashMap::new(),
            vars: HashMap::new(),
            var_values: HashMap::new(),
        }
    }

    pub fn register<T: Sized + Any>(&mut self, var: CVar<T>)
        where CVar<T>: Var
    {
        if self.vars.contains_key(var.name) {
            panic!("Key registered twice {}", var.name);
        }
        self.names.insert(var.name.to_owned(), var.name);
        self.var_values.insert(var.name, RefCell::new(Box::new((var.default)())));
        self.vars.insert(var.name, Box::new(var));
    }

    pub fn get<'a, T: Sized + Any>(&'a self, var: CVar<T>) -> Ref<'a, T>
        where CVar<T>: Var
    {
        // Should never fail
        let var = self.var_values.get(var.name).unwrap().borrow();
        Ref::map(var, |v| v.downcast_ref::<T>().unwrap())
    }

    pub fn set<T: Sized + Any>(&self, var: CVar<T>, val: T)
        where CVar<T>: Var
    {
        // self.var_values.insert(var.name, Box::new(val));
        *self.var_values.get(var.name).unwrap().borrow_mut() = Box::new(val);
        self.save_config();
    }

    pub fn load_config(&mut self) {
        if let Ok(file) = fs::File::open("conf.cfg") {
            let reader = BufReader::new(file);
            for line in reader.lines() {
                let line = line.unwrap();
                if line.starts_with('#') || line.is_empty() {
                    continue;
                }
                let parts = line.splitn(2, ' ').map(|v| v.to_owned()).collect::<Vec<String>>();
                let (name, arg) = (&parts[0], &parts[1]);
                if let Some(var_name) = self.names.get(name) {
                    let var = self.vars.get(var_name).unwrap();
                    let val = var.deserialize(&arg);
                    if var.can_serialize() {
                        self.var_values.insert(var_name, RefCell::new(val));
                    }
                }
            }
        }
    }

    pub fn save_config(&self) {
        let mut file = BufWriter::new(fs::File::create("conf.cfg").unwrap());
        for (name, var) in &self.vars {
            if !var.can_serialize() {
                continue;
            }
            for line in var.description().lines() {
                write!(file, "# {}\n", line).unwrap();
            }
            write!(file,
                   "{} {}\n\n",
                   name,
                   var.serialize(&self.var_values.get(name).unwrap().borrow()))
                .unwrap();
        }
    }
}

pub struct Console {
    history: Vec<Component>,

    collection: ui::Collection,
    active: bool,
    position: f64,
}

impl Console {
    pub fn new() -> Console {
        Console {
            history: vec![Component::Text(TextComponent::new("")); 200],

            collection: ui::Collection::new(),
            active: false,
            position: -220.0,
        }
    }

    pub fn is_active(&self) -> bool {
        self.active
    }

    pub fn toggle(&mut self) {
        self.active = !self.active;
    }

    pub fn tick(&mut self,
                ui_container: &mut ui::Container,
                renderer: &mut render::Renderer,
                delta: f64,
                width: f64) {
        // To make sure the console is always on top it constant removes and readds itself.
        // Its hacky but the console should never appear for normal users so its not really
        // a major issue.
        self.collection.remove_all(ui_container);
        if !self.active && self.position <= -220.0 {
            return;
        }
        if self.active {
            if self.position < 0.0 {
                self.position += delta * 4.0;
            } else {
                self.position = 0.0;
            }
        } else if self.position > -220.0 {
            self.position -= delta * 4.0;
        } else {
            self.position = -220.0;
        }
        let w = match ui_container.mode {
            ui::Mode::Scaled => width,
            ui::Mode::Unscaled(scale) => 854.0 / scale,
        };

        let mut background = ui::Image::new(
            render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"),
            0.0, self.position, w, 220.0,
            0.0, 0.0, 1.0, 1.0,
            0, 0, 0
        );
        background.set_a(180);
        let background = self.collection.add(ui_container.add(background));

        let mut lines = Vec::new();
        let mut offset = 0.0;
        for line in self.history.iter().rev() {
            if offset >= 210.0 {
                break;
            }
            let mut fmt = ui::Formatted::with_width_limit(
                renderer,
                line.clone(),
                5.0, 5.0 + offset,
                w - 1.0
            );
            fmt.set_parent(&background);
            fmt.set_v_attach(ui::VAttach::Bottom);
            offset += fmt.get_height();
            lines.push(ui_container.add(fmt));
        }
        for fmt in lines {
            self.collection.add(fmt);
        }
    }

    fn log(&mut self, record: &log::LogRecord) {
        for filtered in FILTERED_CRATES {
            if record.location().module_path().starts_with(filtered) {
                return;
            }
        }

        let mut file = &record.location().file().replace("\\", "/")[..];
        if let Some(pos) = file.rfind("src/") {
            file = &file[pos + 4..];
        }

        println!("[{}:{}][{}] {}",
                 file,
                 record.location().line(),
                 record.level(),
                 record.args());
        self.history.remove(0);
        let mut msg = TextComponent::new("");
        msg.modifier.extra = Some(vec![
            Component::Text(TextComponent::new("[")),
            {
                let mut msg = TextComponent::new(file);
                msg.modifier.color = Some(Color::Green);
                Component::Text(msg)
            },
            Component::Text(TextComponent::new(":")),
            {
                let mut msg = TextComponent::new(&format!("{}", record.location().line()));
                msg.modifier.color = Some(Color::Aqua);
                Component::Text(msg)
            },
            Component::Text(TextComponent::new("]")),
            Component::Text(TextComponent::new("[")),
            {
                let mut msg = TextComponent::new(&format!("{}", record.level()));
                msg.modifier.color = Some(match record.level() {
                    log::LogLevel::Debug => Color::Green,
                    log::LogLevel::Error => Color::Red,
                    log::LogLevel::Warn => Color::Yellow,
                    log::LogLevel::Info => Color::Aqua,
                    log::LogLevel::Trace => Color::Blue,
                });
                Component::Text(msg)
            },
            Component::Text(TextComponent::new("] ")),
            Component::Text(TextComponent::new(&format!("{}", record.args())))
        ]);
        self.history.push(Component::Text(msg));
    }
}

pub struct ConsoleProxy {
    console: Arc<Mutex<Console>>,
}

impl ConsoleProxy {
    pub fn new(con: Arc<Mutex<Console>>) -> ConsoleProxy {
        ConsoleProxy { console: con }
    }
}

impl log::Log for ConsoleProxy {
    fn enabled(&self, metadata: &log::LogMetadata) -> bool {
        metadata.level() <= log::LogLevel::Trace
    }

    fn log(&self, record: &log::LogRecord) {
        if self.enabled(record.metadata()) {
            self.console.lock().unwrap().log(record);
        }
    }
}

unsafe impl Send for ConsoleProxy {}
unsafe impl Sync for ConsoleProxy {}
<commit_msg>Remove a leftover comment<commit_after>// Copyright 2016 Matthew Collins
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::marker::PhantomData;
use std::collections::HashMap;
use std::any::Any;
use std::cell::{RefCell, Ref};
use std::sync::{Arc, Mutex};
use std::fs;
use std::io::{BufWriter, Write, BufRead, BufReader};
use log;

use ui;
use render;
use format::{Component, TextComponent, Color};

const FILTERED_CRATES: &'static [&'static str] = &[
    "hyper",
    "mime",
];

pub struct CVar<T: Sized + Any + 'static> {
    pub name: &'static str,
    pub ty: PhantomData<T>,
    pub description: &'static str,
    pub mutable: bool,
    pub serializable: bool,
    pub default: &'static Fn() -> T,
}

impl Var for CVar<i64> {
    fn serialize(&self, val: &Box<Any>) -> String {
        val.downcast_ref::<i64>().unwrap().to_string()
    }

    fn deserialize(&self, input: &str) -> Box<Any> {
        Box::new(input.parse::<i64>().unwrap())
    }

    fn description(&self) -> &'static str {
        self.description
    }

    fn can_serialize(&self) -> bool {
        self.serializable
    }
}

impl Var for CVar<bool> {
    fn serialize(&self, val: &Box<Any>) -> String {
        val.downcast_ref::<bool>().unwrap().to_string()
    }

    fn deserialize(&self, input: &str) -> Box<Any> {
        Box::new(input.parse::<bool>().unwrap())
    }

    fn description(&self) -> &'static str {
        self.description
    }

    fn can_serialize(&self) -> bool {
        self.serializable
    }
}

impl Var for CVar<String> {
    fn serialize(&self, val: &Box<Any>) -> String {
        format!("\"{}\"", val.downcast_ref::<String>().unwrap())
    }

    fn deserialize(&self, input: &str) -> Box<Any> {
        Box::new((&input[1..input.len() - 1]).to_owned())
    }

    fn description(&self) -> &'static str {
        self.description
    }
    fn can_serialize(&self) -> bool {
        self.serializable
    }
}

pub trait Var {
    fn serialize(&self, val: &Box<Any>) -> String;
    fn deserialize(&self, input: &str) -> Box<Any>;
    fn description(&self) -> &'static str;
    fn can_serialize(&self) -> bool;
}

pub struct Vars {
    names: HashMap<String, &'static str>,
    vars: HashMap<&'static str, Box<Var>>,
    var_values: HashMap<&'static str, RefCell<Box<Any>>>,
}

impl Vars {
    pub fn new() -> Vars {
        Vars {
            names: HashMap::new(),
            vars: HashMap::new(),
            var_values: HashMap::new(),
        }
    }

    pub fn register<T: Sized + Any>(&mut self, var: CVar<T>)
        where CVar<T>: Var
    {
        if self.vars.contains_key(var.name) {
            panic!("Key registered twice {}", var.name);
        }
        self.names.insert(var.name.to_owned(), var.name);
        self.var_values.insert(var.name, RefCell::new(Box::new((var.default)())));
        self.vars.insert(var.name, Box::new(var));
    }

    pub fn get<'a, T: Sized + Any>(&'a self, var: CVar<T>) -> Ref<'a, T>
        where CVar<T>: Var
    {
        // Should never fail
        let var = self.var_values.get(var.name).unwrap().borrow();
        Ref::map(var, |v| v.downcast_ref::<T>().unwrap())
    }

    pub fn set<T: Sized + Any>(&self, var: CVar<T>, val: T)
        where CVar<T>: Var
    {
        *self.var_values.get(var.name).unwrap().borrow_mut() = Box::new(val);
        self.save_config();
    }

    pub fn load_config(&mut self) {
        if let Ok(file) = fs::File::open("conf.cfg") {
            let reader = BufReader::new(file);
            for line in reader.lines() {
                let line = line.unwrap();
                if line.starts_with('#') || line.is_empty() {
                    continue;
                }
                let parts = line.splitn(2, ' ').map(|v| v.to_owned()).collect::<Vec<String>>();
                let (name, arg) = (&parts[0], &parts[1]);
                if let Some(var_name) = self.names.get(name) {
                    let var = self.vars.get(var_name).unwrap();
                    let val = var.deserialize(&arg);
                    if var.can_serialize() {
                        self.var_values.insert(var_name, RefCell::new(val));
                    }
                }
            }
        }
    }

    pub fn save_config(&self) {
        let mut file = BufWriter::new(fs::File::create("conf.cfg").unwrap());
        for (name, var) in &self.vars {
            if !var.can_serialize() {
                continue;
            }
            for line in var.description().lines() {
                write!(file, "# {}\n", line).unwrap();
            }
            write!(file,
                   "{} {}\n\n",
                   name,
                   var.serialize(&self.var_values.get(name).unwrap().borrow()))
                .unwrap();
        }
    }
}

pub struct Console {
    history: Vec<Component>,

    collection: ui::Collection,
    active: bool,
    position: f64,
}

impl Console {
    pub fn new() -> Console {
        Console {
            history: vec![Component::Text(TextComponent::new("")); 200],

            collection: ui::Collection::new(),
            active: false,
            position: -220.0,
        }
    }

    pub fn is_active(&self) -> bool {
        self.active
    }

    pub fn toggle(&mut self) {
        self.active = !self.active;
    }

    pub fn tick(&mut self,
                ui_container: &mut ui::Container,
                renderer: &mut render::Renderer,
                delta: f64,
                width: f64) {
        // To make sure the console is always on top it constant removes and readds itself.
        // Its hacky but the console should never appear for normal users so its not really
        // a major issue.
        self.collection.remove_all(ui_container);
        if !self.active && self.position <= -220.0 {
            return;
        }
        if self.active {
            if self.position < 0.0 {
                self.position += delta * 4.0;
            } else {
                self.position = 0.0;
            }
        } else if self.position > -220.0 {
            self.position -= delta * 4.0;
        } else {
            self.position = -220.0;
        }
        let w = match ui_container.mode {
            ui::Mode::Scaled => width,
            ui::Mode::Unscaled(scale) => 854.0 / scale,
        };

        let mut background = ui::Image::new(
            render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"),
            0.0, self.position, w, 220.0,
            0.0, 0.0, 1.0, 1.0,
            0, 0, 0
        );
        background.set_a(180);
        let background = self.collection.add(ui_container.add(background));

        let mut lines = Vec::new();
        let mut offset = 0.0;
        for line in self.history.iter().rev() {
            if offset >= 210.0 {
                break;
            }
            let mut fmt = ui::Formatted::with_width_limit(
                renderer,
                line.clone(),
                5.0, 5.0 + offset,
                w - 1.0
            );
            fmt.set_parent(&background);
            fmt.set_v_attach(ui::VAttach::Bottom);
            offset += fmt.get_height();
            lines.push(ui_container.add(fmt));
        }
        for fmt in lines {
            self.collection.add(fmt);
        }
    }

    fn log(&mut self, record: &log::LogRecord) {
        for filtered in FILTERED_CRATES {
            if record.location().module_path().starts_with(filtered) {
                return;
            }
        }

        let mut file = &record.location().file().replace("\\", "/")[..];
        if let Some(pos) = file.rfind("src/") {
            file = &file[pos + 4..];
        }

        println!("[{}:{}][{}] {}",
                 file,
                 record.location().line(),
                 record.level(),
                 record.args());
        self.history.remove(0);
        let mut msg = TextComponent::new("");
        msg.modifier.extra = Some(vec![
            Component::Text(TextComponent::new("[")),
            {
                let mut msg = TextComponent::new(file);
                msg.modifier.color = Some(Color::Green);
                Component::Text(msg)
            },
            Component::Text(TextComponent::new(":")),
            {
                let mut msg = TextComponent::new(&format!("{}", record.location().line()));
                msg.modifier.color = Some(Color::Aqua);
                Component::Text(msg)
            },
            Component::Text(TextComponent::new("]")),
            Component::Text(TextComponent::new("[")),
            {
                let mut msg = TextComponent::new(&format!("{}", record.level()));
                msg.modifier.color = Some(match record.level() {
                    log::LogLevel::Debug => Color::Green,
                    log::LogLevel::Error => Color::Red,
                    log::LogLevel::Warn => Color::Yellow,
                    log::LogLevel::Info => Color::Aqua,
                    log::LogLevel::Trace => Color::Blue,
                });
                Component::Text(msg)
            },
            Component::Text(TextComponent::new("] ")),
            Component::Text(TextComponent::new(&format!("{}", record.args())))
        ]);
        self.history.push(Component::Text(msg));
    }
}

pub struct ConsoleProxy {
    console: Arc<Mutex<Console>>,
}

impl ConsoleProxy {
    pub fn new(con: Arc<Mutex<Console>>) -> ConsoleProxy {
        ConsoleProxy { console: con }
    }
}

impl log::Log for ConsoleProxy {
    fn enabled(&self, metadata: &log::LogMetadata) -> bool {
        metadata.level() <= log::LogLevel::Trace
    }

    fn log(&self, record: &log::LogRecord) {
        if self.enabled(record.metadata()) {
            self.console.lock().unwrap().log(record);
        }
    }
}

unsafe impl Send for ConsoleProxy {}
unsafe impl Sync for ConsoleProxy {}
<|endoftext|>


<commit_before>// load, store, set, clear, wait_for

extern mod core;

use core::ops::{BitOr, BitAnd, Not};
use core::cmp::Eq;
use core::mem::{volatile_load, volatile_store};

pub enum Sync_Method {
    Memory,
    Memory_Flush,
    Instruction_Flush
}

// Note: Probably going to have to inline this stuff properly.
// Not really synchronising if there is another function call involved.
#[inline]
pub fn sync(sync_method: Sync_Method) {
    unsafe {
        match sync_method {
            Memory            => asm!("dmb"),
            Memory_Flush      => asm!("dsb"),
            Instruction_Flush => asm!("isb")
        }
    }
}

#[inline]
pub unsafe fn store<T>(dst: *mut T, val: T) {
    volatile_store(dst, val);
}

#[inline]
pub unsafe fn store_sync<T>(dst: *mut T, val: T, sync_method: Sync_Method) {
    volatile_store(dst, val);
    sync(sync_method);
}

#[inline]
pub unsafe fn load<T>(src: *T) -> T {
    volatile_load(src)
}

#[inline]
pub unsafe fn set<T: BitOr<T,T>>(dst: *mut T, mask: T) {
    let val = volatile_load(dst as *T);
    volatile_store(dst, val | mask);
}

#[inline]
pub unsafe fn clear<T: BitAnd<T,T>+Not<T>>(dst: *mut T , mask: T) {
    let val = volatile_load(dst as *T);
    volatile_store(dst, val & !mask);
}

#[inline]
pub unsafe fn wait_for<T: BitAnd<T,T>+Eq>(src: *T, mask: T, val: T) {
    while volatile_load(src) & mask != val {}
}

// #[inline]
// pub unsafe fn wait_for_zero<T: BitAnd<T,T>+Eq>(src: *T, mask: T) {
//     while volatile_load(src) & mask {}
// }
<commit_msg>Take a *mut for volatile load\nSimplifies things a little<commit_after>// load, store, set, clear, wait_for

extern mod core;

use core::ops::{BitOr, BitAnd, Not};
use core::cmp::Eq;
use core::mem::{volatile_load, volatile_store};

pub enum Sync_Method {
    Memory,
    Memory_Flush,
    Instruction_Flush
}

// Note: Probably going to have to inline this stuff properly.
// Not really synchronising if there is another function call involved.
#[inline]
pub fn sync(sync_method: Sync_Method) {
    unsafe {
        match sync_method {
            Memory            => asm!("dmb"),
            Memory_Flush      => asm!("dsb"),
            Instruction_Flush => asm!("isb")
        }
    }
}

#[inline]
pub unsafe fn store<T>(dst: *mut T, val: T) {
    volatile_store(dst, val);
}

#[inline]
pub unsafe fn store_sync<T>(dst: *mut T, val: T, sync_method: Sync_Method) {
    volatile_store(dst, val);
    sync(sync_method);
}

#[inline]
pub unsafe fn load<T>(src: *mut T) -> T {
    volatile_load(src as *T)
}

#[inline]
pub unsafe fn set<T: BitOr<T,T>>(dst: *mut T, mask: T) {
    let val = volatile_load(dst as *T);
    volatile_store(dst, val | mask);
}

#[inline]
pub unsafe fn clear<T: BitAnd<T,T>+Not<T>>(dst: *mut T , mask: T) {
    let val = volatile_load(dst as *T);
    volatile_store(dst, val & !mask);
}

#[inline]
pub unsafe fn wait_for<T: BitAnd<T,T>+Eq>(src: *T, mask: T, val: T) {
    while volatile_load(src) & mask != val {}
}

// #[inline]
// pub unsafe fn wait_for_zero<T: BitAnd<T,T>+Eq>(src: *T, mask: T) {
//     while volatile_load(src) & mask {}
// }
<|endoftext|>


<commit_before>mod data;

use self::data::{Digraph, TABLE};

fn get_char(digraph: &str) -> Option<char> {
    let mut chars_it = digraph.chars();
    let chars: [char; 2] = [chars_it.next().unwrap(), chars_it.next().unwrap()];
    let res = TABLE.into_iter().find(|&x| x.sequence == chars);
    match res {
        Some(digr) => Some(digr.character),
        None => None,
    }
}

fn get_digraph(c: &char) -> Option<String> {
    let res = TABLE.into_iter().find(|&x| x.character == *c);
    match res {
        Some(digr) => Some(digr.sequence.iter().cloned().collect::<String>()),
        None => None,
    }
}

pub fn convert(pattern: &str) -> Option<String> {
    match pattern.chars().count() {
        1usize => get_digraph(&pattern.chars().next().unwrap()),
        2usize => {
            match get_char(pattern) {
                Some(c) => Some(c.to_string()),
                None => None,
            }
        }
        _ => None,
    }
}

pub fn filter(pattern: &str) -> Vec<&Digraph> {
    match pattern.chars().count() {
        0usize => TABLE.iter().collect(),
        1usize => {
            let c = pattern.chars().next().unwrap();
            TABLE.into_iter().filter(|&x| x.sequence[0] == c).collect()
        }
        2usize => {
            let mut chars_it = pattern.chars();
            let chars: [char; 2] = [chars_it.next().unwrap(), chars_it.next().unwrap()];
            if chars[0] == '_' {
                TABLE.into_iter().filter(|&x| x.sequence[1] == chars[1]).collect()
            } else {
                TABLE.into_iter().filter(|&x| x.sequence == chars).collect()
            }
        }
        _ => TABLE.iter().collect(),
    }
}
<commit_msg>cleanup match<commit_after>mod data;

use self::data::{Digraph, TABLE};

fn get_char(digraph: &str) -> Option<char> {
    let mut chars_it = digraph.chars();
    let chars: [char; 2] = [chars_it.next().unwrap(), chars_it.next().unwrap()];
    let res = TABLE.into_iter().find(|&x| x.sequence == chars);
    match res {
        Some(digr) => Some(digr.character),
        None => None,
    }
}

fn get_digraph(c: &char) -> Option<String> {
    let res = TABLE.into_iter().find(|&x| x.character == *c);
    match res {
        Some(digr) => Some(digr.sequence.iter().cloned().collect::<String>()),
        None => None,
    }
}

pub fn convert(pattern: &str) -> Option<String> {
    match pattern.chars().count() {
        1usize => get_digraph(&pattern.chars().next().unwrap()),
        2usize => {
            match get_char(pattern) {
                Some(c) => Some(c.to_string()),
                None => None,
            }
        }
        _ => None,
    }
}

pub fn filter(pattern: &str) -> Vec<&Digraph> {
    match pattern.chars().count() {
        1usize => {
            let c = pattern.chars().next().unwrap();
            TABLE.into_iter().filter(|&x| x.sequence[0] == c).collect()
        }
        2usize => {
            let mut chars_it = pattern.chars();
            let chars: [char; 2] = [chars_it.next().unwrap(), chars_it.next().unwrap()];
            if chars[0] == '_' {
                TABLE.into_iter().filter(|&x| x.sequence[1] == chars[1]).collect()
            } else {
                TABLE.into_iter().filter(|&x| x.sequence == chars).collect()
            }
        }
        _ => TABLE.iter().collect(),
    }
}
<|endoftext|>


<commit_before>/// Modules to help creating a problem.
///
/// TODO

pub mod autoio;
pub mod batch;
pub mod bios;
pub mod dce;
pub mod diff;
pub mod make;
<commit_msg>Fix wrong inner comment in evallib<commit_after>//! Modules to help creating a problem.
//!
//! TODO

pub mod autoio;
pub mod batch;
pub mod bios;
pub mod dce;
pub mod diff;
pub mod make;
<|endoftext|>


<commit_before>/// A type for which the layout is determined by its C++ definition.
///
/// This trait serves the following two related purposes.
///
///

///
/// ## Safely unifying occurrences of the same extern type
///
/// `ExternType` makes it possible for CXX to safely share a consistent Rust
/// type across multiple #\[cxx::bridge\] invocations that refer to a common
/// extern C++ type.
///
/// In the following snippet, two #\[cxx::bridge\] invocations in different
/// files (possibly different crates) both contain function signatures involving
/// the same C++ type `example::Demo`. If both were written just containing
/// `type Demo;`, then both macro expansions would produce their own separate
/// Rust type called `Demo` and thus the compiler wouldn't allow us to take the
/// `Demo` returned by `file1::ffi::create_demo` and pass it as the `Demo`
/// argument accepted by `file2::ffi::take_ref_demo`. Instead, one of the two
/// `Demo`s has been defined as an extern type alias of the other, making them
/// the same type in Rust. The CXX code generator will use an automatically
/// generated `ExternType` impl emitted in file1 to statically verify that in
/// file2 `crate::file1::ffi::Demo` really does refer to the C++ type
/// `example::Demo` as expected in file2.
///
/// ```no_run
/// // file1.rs
/// # mod file1 {
/// #[cxx::bridge(namespace = example)]
/// pub mod ffi {
///     extern "C" {
///         type Demo;
///
///         fn create_demo() -> UniquePtr<Demo>;
///     }
/// }
/// # }
///
/// // file2.rs
/// #[cxx::bridge(namespace = example)]
/// pub mod ffi {
///     extern "C" {
///         type Demo = crate::file1::ffi::Demo;
///
///         fn take_ref_demo(demo: &Demo);
///     }
/// }
/// #
/// # fn main() {}
/// ```
///
///

///
/// ## Integrating with bindgen-generated types
///
/// Handwritten `ExternType` impls make it possible to plug in a data structure
/// emitted by bindgen as the definition of a C++ type emitted by CXX.
///
/// By writing the unsafe `ExternType` impl, the programmer asserts that the C++
/// namespace and type name given in the type id refers to a C++ type that is
/// equivalent to Rust type that is the `Self` type of the impl.
///
/// ```no_run
/// # const _: &str = stringify! {
/// mod folly_sys;  // the bindgen-generated bindings
/// # };
/// # mod folly_sys {
/// #     #[repr(transparent)]
/// #     pub struct StringPiece([usize; 2]);
/// # }
///
/// use cxx::{type_id, ExternType};
///
/// unsafe impl ExternType for folly_sys::StringPiece {
///     type Id = type_id!("folly::StringPiece");
///     type Kind = cxx::kind::Opaque;
/// }
///
/// #[cxx::bridge(namespace = folly)]
/// pub mod ffi {
///     extern "C" {
///         include!("rust_cxx_bindings.h");
///
///         type StringPiece = crate::folly_sys::StringPiece;
///
///         fn print_string_piece(s: &StringPiece);
///     }
/// }
///
/// // Now if we construct a StringPiece or obtain one through one
/// // of the bindgen-generated signatures, we are able to pass it
/// // along to ffi::print_string_piece.
/// #
/// # fn main() {}
/// ```
pub unsafe trait ExternType {
    /// A type-level representation of the type's C++ namespace and type name.
    ///
    /// This will always be defined using `type_id!` in the following form:
    ///
    /// ```
    /// # struct TypeName;
    /// # unsafe impl cxx::ExternType for TypeName {
    /// type Id = cxx::type_id!("name::space::of::TypeName");
    /// #     type Kind = cxx::kind::Opaque;
    /// # }
    /// ```
    type Id;

    /// Either `cxx::kind::Opaque` or `cxx::kind::Trivial`. If in doubt, use
    /// `cxx::kind::Opaque`.
    ///
    /// Some C++ types are safe to hold and pass around in Rust, by value.
    /// Those C++ types must have a trivial move constructor, and must
    /// have no destructor.
    ///
    /// If you believe your C++ type is indeed trivial, you can specify
    /// ```
    /// # struct TypeName;
    /// # unsafe impl cxx::ExternType for TypeName {
    /// #     type Id = cxx::type_id!("name::space::of::TypeName");
    /// type Kind = cxx::kind::Trivial;
    /// # }
    /// ```
    /// which will enable you to pass it into C++ functions by value,
    /// return it by value from such functions, and include it in
    /// `struct`s that you have declared to `cxx::bridge`. Your promises
    /// about the triviality of the C++ type will be checked using
    /// `static_assert`s in the generated C++.
    ///
    /// Opaque types can't be passed by value, but can still be held
    /// in `UniquePtr`.
    type Kind;
}

/// Marker types identifying Rust's knowledge about an extern C++ type.
///
/// These markers are used in the [`Kind`][ExternType::Kind] associated type in
/// impls of the `ExternType` trait. Refer to the documentation of `Kind` for an
/// overview of their purpose.
pub mod kind {
    /// An opaque type which cannot be passed or held by value within Rust.
    ///
    /// Rust's move semantics are such that every move is equivalent to a
    /// memcpy. This is incompatible in general with C++'s constructor-based
    /// move semantics, so a C++ type which has a destructor or nontrivial move
    /// constructor must never exist by value in Rust. In CXX, such types are
    /// called opaque C++ types.
    ///
    /// When passed across an FFI boundary, an opaque C++ type must be behind an
    /// indirection such as a reference or UniquePtr.
    pub struct Opaque;

    /// A type with trivial move constructor and no destructor, which can
    /// therefore be owned and moved around in Rust code without requiring
    /// indirection.
    pub struct Trivial;
}

#[doc(hidden)]
pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}

#[doc(hidden)]
pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind>() {}
<commit_msg>Update documentation of ExternType::Kind<commit_after>/// A type for which the layout is determined by its C++ definition.
///
/// This trait serves the following two related purposes.
///
///

///
/// ## Safely unifying occurrences of the same extern type
///
/// `ExternType` makes it possible for CXX to safely share a consistent Rust
/// type across multiple #\[cxx::bridge\] invocations that refer to a common
/// extern C++ type.
///
/// In the following snippet, two #\[cxx::bridge\] invocations in different
/// files (possibly different crates) both contain function signatures involving
/// the same C++ type `example::Demo`. If both were written just containing
/// `type Demo;`, then both macro expansions would produce their own separate
/// Rust type called `Demo` and thus the compiler wouldn't allow us to take the
/// `Demo` returned by `file1::ffi::create_demo` and pass it as the `Demo`
/// argument accepted by `file2::ffi::take_ref_demo`. Instead, one of the two
/// `Demo`s has been defined as an extern type alias of the other, making them
/// the same type in Rust. The CXX code generator will use an automatically
/// generated `ExternType` impl emitted in file1 to statically verify that in
/// file2 `crate::file1::ffi::Demo` really does refer to the C++ type
/// `example::Demo` as expected in file2.
///
/// ```no_run
/// // file1.rs
/// # mod file1 {
/// #[cxx::bridge(namespace = example)]
/// pub mod ffi {
///     extern "C" {
///         type Demo;
///
///         fn create_demo() -> UniquePtr<Demo>;
///     }
/// }
/// # }
///
/// // file2.rs
/// #[cxx::bridge(namespace = example)]
/// pub mod ffi {
///     extern "C" {
///         type Demo = crate::file1::ffi::Demo;
///
///         fn take_ref_demo(demo: &Demo);
///     }
/// }
/// #
/// # fn main() {}
/// ```
///
///

///
/// ## Integrating with bindgen-generated types
///
/// Handwritten `ExternType` impls make it possible to plug in a data structure
/// emitted by bindgen as the definition of a C++ type emitted by CXX.
///
/// By writing the unsafe `ExternType` impl, the programmer asserts that the C++
/// namespace and type name given in the type id refers to a C++ type that is
/// equivalent to Rust type that is the `Self` type of the impl.
///
/// ```no_run
/// # const _: &str = stringify! {
/// mod folly_sys;  // the bindgen-generated bindings
/// # };
/// # mod folly_sys {
/// #     #[repr(transparent)]
/// #     pub struct StringPiece([usize; 2]);
/// # }
///
/// use cxx::{type_id, ExternType};
///
/// unsafe impl ExternType for folly_sys::StringPiece {
///     type Id = type_id!("folly::StringPiece");
///     type Kind = cxx::kind::Opaque;
/// }
///
/// #[cxx::bridge(namespace = folly)]
/// pub mod ffi {
///     extern "C" {
///         include!("rust_cxx_bindings.h");
///
///         type StringPiece = crate::folly_sys::StringPiece;
///
///         fn print_string_piece(s: &StringPiece);
///     }
/// }
///
/// // Now if we construct a StringPiece or obtain one through one
/// // of the bindgen-generated signatures, we are able to pass it
/// // along to ffi::print_string_piece.
/// #
/// # fn main() {}
/// ```
pub unsafe trait ExternType {
    /// A type-level representation of the type's C++ namespace and type name.
    ///
    /// This will always be defined using `type_id!` in the following form:
    ///
    /// ```
    /// # struct TypeName;
    /// # unsafe impl cxx::ExternType for TypeName {
    /// type Id = cxx::type_id!("name::space::of::TypeName");
    /// #     type Kind = cxx::kind::Opaque;
    /// # }
    /// ```
    type Id;

    /// Either [`cxx::kind::Opaque`] or [`cxx::kind::Trivial`].
    ///
    /// [`cxx::kind::Opaque`]: kind::Opaque
    /// [`cxx::kind::Trivial`]: kind::Trivial
    ///
    /// A C++ type is only okay to hold and pass around by value in Rust if its
    /// [move constructor is trivial] and it has no destructor. In CXX, these
    /// are called Trivial extern C++ types, while types with nontrivial move
    /// behavior or a destructor must be considered Opaque and handled by Rust
    /// only behind an indirection, such as a reference or UniquePtr.
    ///
    /// [move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible
    ///
    /// If you believe your C++ type reflected by this ExternType impl is indeed
    /// trivial, you can specify:
    ///
    /// ```
    /// # struct TypeName;
    /// # unsafe impl cxx::ExternType for TypeName {
    /// #     type Id = cxx::type_id!("name::space::of::TypeName");
    /// type Kind = cxx::kind::Trivial;
    /// # }
    /// ```
    ///
    /// which will enable you to pass it into C++ functions by value, return it
    /// by value, and include it in `struct`s that you have declared to
    /// `cxx::bridge`. Your claim about the triviality of the C++ type will be
    /// checked by a `static_assert` in the generated C++ side of the binding.
    type Kind;
}

/// Marker types identifying Rust's knowledge about an extern C++ type.
///
/// These markers are used in the [`Kind`][ExternType::Kind] associated type in
/// impls of the `ExternType` trait. Refer to the documentation of `Kind` for an
/// overview of their purpose.
pub mod kind {
    /// An opaque type which cannot be passed or held by value within Rust.
    ///
    /// Rust's move semantics are such that every move is equivalent to a
    /// memcpy. This is incompatible in general with C++'s constructor-based
    /// move semantics, so a C++ type which has a destructor or nontrivial move
    /// constructor must never exist by value in Rust. In CXX, such types are
    /// called opaque C++ types.
    ///
    /// When passed across an FFI boundary, an opaque C++ type must be behind an
    /// indirection such as a reference or UniquePtr.
    pub struct Opaque;

    /// A type with trivial move constructor and no destructor, which can
    /// therefore be owned and moved around in Rust code without requiring
    /// indirection.
    pub struct Trivial;
}

#[doc(hidden)]
pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}

#[doc(hidden)]
pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind>() {}
<|endoftext|>


<commit_before>use gl::types::*;

pub struct Framebuffer {
    gl_id: GLuint
}
<commit_msg>Add `Framebuffer.gl_id()`<commit_after>use gl::types::*;

pub struct Framebuffer {
    gl_id: GLuint
}

impl Framebuffer {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}
<|endoftext|>


<commit_before>
use std::io::Cursor;

use byteorder::{ByteOrder, LittleEndian};

use gameboy::registers;

pub struct Cpu {
    rom: Vec<u8>,
    pub registers: registers::Registers,
}

impl Cpu {
    pub fn new(gameboy_color: bool, rom: Vec<u8>) -> Cpu {
        Cpu {
            rom: rom,
            registers: registers::Registers::new(gameboy_color),
        }
    }

    pub fn step(&mut self) {
        let opcode = self.rom[self.registers.pc];
        self.registers.pc += 1;

        match opcode {
            0b00110001 => {
                // LD SP, <u16>
                let val = LittleEndian::read_u16(&self.rom[self.registers.pc..]);
                self.registers.sp = val as usize;
                self.registers.pc += 0x03;
                println!("Stack pointer: {:#X}", self.registers.sp);
            }
            0b10101111 => {
                // XOR A
                self.registers.a = self.registers.a ^ self.registers.a;
            }
            _ => panic!("Unknown opcode: {:#X}", opcode),
        }
    }
}

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

    #[test]
    pub fn xor_a_zeros_a_and_sets_zero_flag() {
        let xor_a = vec![0xAF];
        let mut cpu = Cpu::new(true, xor_a);

        cpu.step();

        assert_eq!(true, cpu.registers.flags.zero);
        assert_eq!(0, cpu.registers.a);
    }
}
<commit_msg>Added a TODO to the test<commit_after>
use std::io::Cursor;

use byteorder::{ByteOrder, LittleEndian};

use gameboy::registers;

pub struct Cpu {
    rom: Vec<u8>,
    pub registers: registers::Registers,
}

impl Cpu {
    pub fn new(gameboy_color: bool, rom: Vec<u8>) -> Cpu {
        Cpu {
            rom: rom,
            registers: registers::Registers::new(gameboy_color),
        }
    }

    pub fn step(&mut self) {
        let opcode = self.rom[self.registers.pc];
        self.registers.pc += 1;

        match opcode {
            0b00110001 => {
                // LD SP, <u16>
                let val = LittleEndian::read_u16(&self.rom[self.registers.pc..]);
                self.registers.sp = val as usize;
                self.registers.pc += 0x03;
                println!("Stack pointer: {:#X}", self.registers.sp);
            }
            0b10101111 => {
                // XOR A
                self.registers.a = self.registers.a ^ self.registers.a;
            }
            _ => panic!("Unknown opcode: {:#X}", opcode),
        }
    }
}

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

    #[test]
    pub fn xor_a_zeros_a_and_sets_zero_flag() {
        let xor_a = vec![0xAF];
        let mut cpu = Cpu::new(true, xor_a);

        cpu.step();

        // TODO: Check FLAGS are set properly
        assert_eq!(true, cpu.registers.flags.zero);
        assert_eq!(0, cpu.registers.a);
    }
}
<|endoftext|>


<commit_before>//! OpenGL back-end for Rust-Graphics.

// External crates.
use graphics::BackEnd;
use gl;
use gl::types::{
    GLfloat,
    GLint,
    GLsizei,
    GLsizeiptr,
    GLuint,
};
use std::ptr;
use std::mem;
use shader_utils::{compile_shader};

// Local crate.
use Texture;

static VERTEX_SHADER_TRI_LIST_XY_RGBA: &'static str = "
#version 330
in vec4 a_v4Position;
in vec4 a_v4FillColor;

out vec4 v_v4FillColor;

void main()
{
    v_v4FillColor = a_v4FillColor;
    gl_Position = a_v4Position;
}
";

static FRAGMENT_SHADER_TRI_LIST_XY_RGBA: &'static str = "
#version 330
out vec4 out_color;
in vec4 v_v4FillColor;

void main()
{
    out_color = v_v4FillColor;
}
";

static VERTEX_SHADER_TRI_LIST_XY_RGBA_UV: &'static str = "
#version 330
in vec4 a_v4Position;
in vec4 a_v4FillColor;
in vec2 a_v2TexCoord;

uniform sampler2D s_texture;

out vec2 v_v2TexCoord;
out vec4 v_v4FillColor;

void main()
{
    v_v2TexCoord = a_v2TexCoord;
    v_v4FillColor = a_v4FillColor;
    gl_Position = a_v4Position;
}
";

static FRAGMENT_SHADER_TRI_LIST_XY_RGBA_UV: &'static str = "
#version 330
out vec4 out_color;

uniform sampler2D s_texture;

in vec2 v_v2TexCoord;
in vec4 v_v4FillColor;

void main()
{
    out_color = texture(s_texture, v_v2TexCoord) * v_v4FillColor;
}
";

struct TriListXYRGBA {
    vertex_shader: GLuint,
    fragment_shader: GLuint,
    program: GLuint,
    a_v4Position: GLuint,
    a_v4FillColor: GLuint,
}

impl Drop for TriListXYRGBA {
    fn drop(&mut self) {
        gl::DeleteProgram(self.program);
        gl::DeleteShader(self.vertex_shader);
        gl::DeleteShader(self.fragment_shader);
    }
}

impl TriListXYRGBA {
    fn new() -> TriListXYRGBA {
        let vertex_shader = match compile_shader(
            gl::VERTEX_SHADER,                  // shader type
            VERTEX_SHADER_TRI_LIST_XY_RGBA      // shader source
        ) {
            Ok(id) => id,
            Err(s) => fail!("compile_shader: {}", s)
        };
        let fragment_shader = match compile_shader(
            gl::FRAGMENT_SHADER,                // shader type
            FRAGMENT_SHADER_TRI_LIST_XY_RGBA    // shader source
        ) {
            Ok(id) => id,
            Err(s) => fail!("compile_shader: {}", s)
        };
        let program = gl::CreateProgram();

        gl::AttachShader(program, vertex_shader);
        gl::AttachShader(program, fragment_shader);
        gl::LinkProgram(program);
        unsafe {
            let a_v4Position = "a_v4Position".with_c_str(
                |ptr| gl::GetAttribLocation(program, ptr)
            );
            let a_v4FillColor = "a_v4FillColor".with_c_str(
                |ptr| gl::GetAttribLocation(program, ptr)
            );

            "out_color".with_c_str(
                |ptr| gl::BindFragDataLocation(program, 0, ptr)
            );
            TriListXYRGBA {
                vertex_shader: vertex_shader,
                fragment_shader: fragment_shader,
                program: program,
                a_v4Position: a_v4Position as GLuint,
                a_v4FillColor: a_v4FillColor as GLuint,
            }
        }
    }

    fn enable_attributes(&self) {
        gl::EnableVertexAttribArray(self.a_v4Position as GLuint);
        gl::EnableVertexAttribArray(self.a_v4FillColor as GLuint);
    }

    fn disable_attributes(&self) {
        gl::DisableVertexAttribArray(self.a_v4Position as GLuint);
        gl::DisableVertexAttribArray(self.a_v4FillColor as GLuint);
    }
}

struct TriListXYRGBAUV {
    vertex_shader: GLuint,
    fragment_shader: GLuint,
    program: GLuint,
    a_v4Position: GLuint,
    a_v4FillColor: GLuint,
    a_v2TexCoord: GLuint,
}

impl Drop for TriListXYRGBAUV {
    fn drop(&mut self) {
        gl::DeleteProgram(self.program);
        gl::DeleteShader(self.vertex_shader);
        gl::DeleteShader(self.fragment_shader);
    }
}

impl TriListXYRGBAUV {
    fn new() -> TriListXYRGBAUV {
        let vertex_shader = match compile_shader(
            gl::VERTEX_SHADER,                  // shader type
            VERTEX_SHADER_TRI_LIST_XY_RGBA_UV   // shader type
        ) {
            Ok(id) => id,
            Err(s) => fail!("compile_shader: {}", s)
        };
        let fragment_shader = match compile_shader(
            gl::FRAGMENT_SHADER,                // shader type
            FRAGMENT_SHADER_TRI_LIST_XY_RGBA_UV // shader source
        ) {
            Ok(id) => id,
            Err(s) => fail!("compile_shader: {}", s)
        };

        let program = gl::CreateProgram();
        gl::AttachShader(program, vertex_shader);
        gl::AttachShader(program, fragment_shader);
        gl::LinkProgram(program);
        unsafe {
            let a_v4Position = "a_v4Position".with_c_str(
                |ptr| gl::GetAttribLocation(program, ptr)
            );
            let a_v4FillColor = "a_v4FillColor".with_c_str(
                |ptr| gl::GetAttribLocation(program, ptr)
            );
            let a_v2TexCoord = "a_v2TexCoord".with_c_str(
                |ptr| gl::GetAttribLocation(program, ptr)
            );

            "out_color".with_c_str(
                |ptr| gl::BindFragDataLocation(program, 0, ptr)
            );

            TriListXYRGBAUV {
                vertex_shader: vertex_shader,
                fragment_shader: fragment_shader,
                program: program,
                a_v4Position: a_v4Position as GLuint,
                a_v4FillColor: a_v4FillColor as GLuint,
                a_v2TexCoord: a_v2TexCoord as GLuint,
            }
        }
    }

    fn enable_attributes(&self) {
        gl::EnableVertexAttribArray(self.a_v4Position as GLuint);
        gl::EnableVertexAttribArray(self.a_v4FillColor as GLuint);
        gl::EnableVertexAttribArray(self.a_v2TexCoord as GLuint);
    }

    fn disable_attributes(&self) {
        gl::DisableVertexAttribArray(self.a_v4Position as GLuint);
        gl::DisableVertexAttribArray(self.a_v4FillColor as GLuint);
        gl::DisableVertexAttribArray(self.a_v2TexCoord as GLuint);
    }
}

/// Contains OpenGL data.
pub struct Gl {
    tri_list_xy_rgba: TriListXYRGBA,
    tri_list_xy_rgba_uv: TriListXYRGBAUV,
    // id of buffer for xy positions.
    position_id: GLuint,
    // id of buffer for rgba colors.
    fill_color_id: GLuint,
    // id of buffer for uv texture coords.
    tex_coord_id: GLuint,
    // Keeps track of the current shader program.
    current_program: Option<GLuint>,
}

impl<'a> Gl {
    /// Creates a new OpenGl back-end.
    pub fn new() -> Gl {
        // Load the vertices, color and texture coord buffers.
        unsafe {
            let mut vbo : [GLuint, ..3] = [0, ..3];
            gl::GenBuffers(3, vbo.as_mut_ptr());
            let position_id = vbo[0];
            let fill_color_id = vbo[1];
            let tex_coord_id = vbo[2];

            Gl {
                tri_list_xy_rgba: TriListXYRGBA::new(),
                tri_list_xy_rgba_uv: TriListXYRGBAUV::new(),
                position_id: position_id,
                fill_color_id: fill_color_id,
                tex_coord_id: tex_coord_id,
                current_program: None,
            }
        }
    }

    /// Sets viewport with normalized coordinates and center as origin.
    pub fn viewport(
        &mut self,
        x: i32,
        y: i32,
        w: i32,
        h: i32
    ) {
        gl::Viewport(x as GLint, y as GLint, w as GLsizei, h as GLsizei);
    }

    /// Sets the current program only if the program is not in use.
    pub fn use_program(&mut self, program: GLuint) {
        match self.current_program {
            None => {},
            Some(current_program) => {
                if program == current_program { return; }
            },
        }

        gl::UseProgram(program);
        self.current_program = Some(program);
    }
}

impl BackEnd<Texture> for Gl {
    fn supports_clear_rgba(&self) -> bool { true }

    fn clear_rgba(&mut self, r: f32, g: f32, b: f32, a: f32) {
        gl::ClearColor(r, g, b, a);
        gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
    }

    fn enable_alpha_blend(&mut self) {
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
    }

    fn disable_alpha_blend(&mut self) {
        gl::Disable(gl::BLEND);
    }

    fn supports_single_texture(&self) -> bool { true }

    fn enable_single_texture(&mut self, texture: &Texture) {
        let texture = texture.get_id();
        gl::BindTexture(gl::TEXTURE_2D, texture);
    }

    fn disable_single_texture(&mut self) {}

    // Assume all textures has alpha channel for now.
    fn has_texture_alpha(&self, _texture: &Texture) -> bool { true }

    fn supports_tri_list_xy_f32_rgba_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32]
    ) {
        {
            // Set shader program.
            let shader_program = self.tri_list_xy_rgba.program;
            self.use_program(shader_program);
        }
        let shader = &self.tri_list_xy_rgba;
        shader.enable_attributes();

        // xy makes two floats.
        let size_vertices: i32 = 2;
        let vertices_byte_len = (
                vertices.len() * mem::size_of::<GLfloat>()
            ) as GLsizeiptr;
        let normalize_vertices = gl::FALSE;
        // The data is tightly packed.
        let stride_vertices = 0;
        gl::BindBuffer(
            gl::ARRAY_BUFFER,   // buffer type
            self.position_id    // position buffer for xy coordinates
        );
        unsafe {
            gl::BufferData(
                gl::ARRAY_BUFFER,
                vertices_byte_len,
                mem::transmute(&vertices[0]),
                gl::DYNAMIC_DRAW
            );
            gl::VertexAttribPointer(
                shader.a_v4Position as GLuint,
                size_vertices,
                gl::FLOAT,
                normalize_vertices,
                stride_vertices,
                ptr::null()
            );
        }

        // rgba makes 4 floats.
        let size_fill_colors = 4;
        let normalize_colors = gl::FALSE;
        let fill_colors_byte_len = (
                colors.len() * mem::size_of::<GLfloat>()
            ) as GLsizeiptr;
        // The data is tightly packed.
        let stride_fill_colors = 0;
        unsafe {
            gl::BindBuffer(
                gl::ARRAY_BUFFER,
                self.fill_color_id
            );
            gl::BufferData(
                gl::ARRAY_BUFFER,
                fill_colors_byte_len,
                mem::transmute(&colors[0]),
                gl::DYNAMIC_DRAW
            );
            gl::VertexAttribPointer(
                shader.a_v4FillColor as GLuint,
                size_fill_colors,
                gl::FLOAT,
                normalize_colors,
                stride_fill_colors,
                ptr::null()
            );
        }

        // Render triangles whether they are facing
        // clockwise or counter clockwise.
        gl::CullFace(gl::FRONT_AND_BACK);

        let items: i32 = vertices.len() as i32 / size_vertices;
        gl::DrawArrays(gl::TRIANGLES, 0, items);
        shader.disable_attributes();
    }

    fn supports_tri_list_xy_f32_rgba_f32_uv_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32_uv_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32],
        texture_coords: &[f32]
    ) {
        {
            // Set shader program.
            let shader_program = self.tri_list_xy_rgba_uv.program;
            self.use_program(shader_program);
        }
        let shader = &self.tri_list_xy_rgba_uv;
        shader.enable_attributes();

        let size_vertices: i32 = 2;
        let normalize_vertices = gl::FALSE;
        let vertices_byte_len = (
                vertices.len() * mem::size_of::<GLfloat>()
            ) as GLsizeiptr;
        // The data is tightly packed.
        let stride_vertices = 0;
        unsafe {
            gl::BindBuffer(
                gl::ARRAY_BUFFER, self.position_id);
            gl::BufferData(
                gl::ARRAY_BUFFER,
                vertices_byte_len,
                mem::transmute(&vertices[0]),
                gl::DYNAMIC_DRAW
            );
            gl::VertexAttribPointer(
                shader.a_v4Position as GLuint,
                size_vertices,
                gl::FLOAT,
                normalize_vertices,
                stride_vertices,
                ptr::null()
            );
        }

        // rgba makes 4 floats.
        let size_fill_color = 4;
        let normalize_fill_color = gl::FALSE;
        let fill_colors_byte_len = (
                colors.len() * mem::size_of::<GLfloat>()
            ) as GLsizeiptr;
        // The data is tightly packed.
        let stride_fill_colors = 0;
        unsafe {
            gl::BindBuffer(
                gl::ARRAY_BUFFER,
                self.fill_color_id
            );
            gl::BufferData(
                gl::ARRAY_BUFFER,
                fill_colors_byte_len,
                mem::transmute(&colors[0]),
                gl::DYNAMIC_DRAW
            );
            gl::VertexAttribPointer(
                shader.a_v4FillColor as GLuint,
                size_fill_color,
                gl::FLOAT,
                normalize_fill_color,
                stride_fill_colors,
                ptr::null()
            );
        }

        // uv makes two floats.
        let size_tex_coord = 2;
        let texture_coords_byte_len = (
                texture_coords.len() * mem::size_of::<GLfloat>()
            ) as GLsizeiptr;
        let normalize_texture_coords = gl::FALSE;
        // The data is tightly packed.
        let stride_texture_coords = 0;
        unsafe {
            gl::BindBuffer(
                gl::ARRAY_BUFFER,
                self.tex_coord_id
            );
            gl::BufferData(
                gl::ARRAY_BUFFER,
                texture_coords_byte_len,
                mem::transmute(&texture_coords[0]),
                gl::DYNAMIC_DRAW
            );
            gl::VertexAttribPointer(
                shader.a_v2TexCoord as GLuint,
                size_tex_coord,
                gl::FLOAT,
                normalize_texture_coords,
                stride_texture_coords,
                ptr::null()
            );
        }

        // Render triangles whether they are facing
        // clockwise or counter clockwise.
        gl::CullFace(gl::FRONT_AND_BACK);

        let items: i32 = vertices.len() as i32 / size_vertices;
        gl::DrawArrays(gl::TRIANGLES, 0, items);

        // TEST
        // println!("{}", gl::GetError());

        shader.disable_attributes();
    }
}

<commit_msg>Fixed problems with shaders<commit_after>//! OpenGL back-end for Rust-Graphics.

// External crates.
use graphics::BackEnd;
use gl;
use gl::types::{
    GLfloat,
    GLint,
    GLsizei,
    GLsizeiptr,
    GLuint,
};
use std::ptr;
use std::mem;
use shader_utils::{compile_shader};

// Local crate.
use Texture;

static VERTEX_SHADER_TRI_LIST_XY_RGBA: &'static str = "
#version 330
in vec4 a_v4Position;
in vec4 a_v4FillColor;

out vec4 v_v4FillColor;

void main()
{
    v_v4FillColor = a_v4FillColor;
    gl_Position = a_v4Position;
}
";

static FRAGMENT_SHADER_TRI_LIST_XY_RGBA: &'static str = "
#version 330
out vec4 out_color;
in vec4 v_v4FillColor;

void main()
{
    out_color = v_v4FillColor;
}
";

static VERTEX_SHADER_TRI_LIST_XY_RGBA_UV: &'static str = "
#version 330
in vec4 a_v4Position;
in vec4 a_v4FillColor;
in vec2 a_v2TexCoord;

uniform sampler2D s_texture;

out vec2 v_v2TexCoord;
out vec4 v_v4FillColor;

void main()
{
    v_v2TexCoord = a_v2TexCoord;
    v_v4FillColor = a_v4FillColor;
    gl_Position = a_v4Position;
}
";

static FRAGMENT_SHADER_TRI_LIST_XY_RGBA_UV: &'static str = "
#version 330
out vec4 out_color;

uniform sampler2D s_texture;

in vec2 v_v2TexCoord;
in vec4 v_v4FillColor;

void main()
{
    out_color = texture(s_texture, v_v2TexCoord) * v_v4FillColor;
}
";

struct TriListXYRGBA {
    vertex_shader: GLuint,
    fragment_shader: GLuint,
    program: GLuint,
    a_v4Position: GLuint,
    a_v4FillColor: GLuint,
}

impl Drop for TriListXYRGBA {
    fn drop(&mut self) {
        gl::DeleteProgram(self.program);
        gl::DeleteShader(self.vertex_shader);
        gl::DeleteShader(self.fragment_shader);
    }
}

impl TriListXYRGBA {
    fn new() -> TriListXYRGBA {
        let vertex_shader = match compile_shader(
            gl::VERTEX_SHADER,                  // shader type
            VERTEX_SHADER_TRI_LIST_XY_RGBA      // shader source
        ) {
            Ok(id) => id,
            Err(s) => fail!("compile_shader: {}", s)
        };
        let fragment_shader = match compile_shader(
            gl::FRAGMENT_SHADER,                // shader type
            FRAGMENT_SHADER_TRI_LIST_XY_RGBA    // shader source
        ) {
            Ok(id) => id,
            Err(s) => fail!("compile_shader: {}", s)
        };
        let program = gl::CreateProgram();

        gl::AttachShader(program, vertex_shader);
        gl::AttachShader(program, fragment_shader);

        unsafe {
            "out_color".with_c_str(
                |ptr| gl::BindFragDataLocation(program, 0, ptr)
            );
        }

        gl::LinkProgram(program);
        unsafe {
            let a_v4Position = "a_v4Position".with_c_str(
                |ptr| gl::GetAttribLocation(program, ptr)
            );
            let a_v4FillColor = "a_v4FillColor".with_c_str(
                |ptr| gl::GetAttribLocation(program, ptr)
            );

            TriListXYRGBA {
                vertex_shader: vertex_shader,
                fragment_shader: fragment_shader,
                program: program,
                a_v4Position: a_v4Position as GLuint,
                a_v4FillColor: a_v4FillColor as GLuint,
            }
        }
    }

    fn enable_attributes(&self) {
        gl::EnableVertexAttribArray(self.a_v4Position as GLuint);
        gl::EnableVertexAttribArray(self.a_v4FillColor as GLuint);
    }

    fn disable_attributes(&self) {
        gl::DisableVertexAttribArray(self.a_v4Position as GLuint);
        gl::DisableVertexAttribArray(self.a_v4FillColor as GLuint);
    }
}

struct TriListXYRGBAUV {
    vertex_shader: GLuint,
    fragment_shader: GLuint,
    program: GLuint,
    a_v4Position: GLuint,
    a_v4FillColor: GLuint,
    a_v2TexCoord: GLuint,
}

impl Drop for TriListXYRGBAUV {
    fn drop(&mut self) {
        gl::DeleteProgram(self.program);
        gl::DeleteShader(self.vertex_shader);
        gl::DeleteShader(self.fragment_shader);
    }
}

impl TriListXYRGBAUV {
    fn new() -> TriListXYRGBAUV {
        let vertex_shader = match compile_shader(
            gl::VERTEX_SHADER,                  // shader type
            VERTEX_SHADER_TRI_LIST_XY_RGBA_UV   // shader type
        ) {
            Ok(id) => id,
            Err(s) => fail!("compile_shader: {}", s)
        };
        let fragment_shader = match compile_shader(
            gl::FRAGMENT_SHADER,                // shader type
            FRAGMENT_SHADER_TRI_LIST_XY_RGBA_UV // shader source
        ) {
            Ok(id) => id,
            Err(s) => fail!("compile_shader: {}", s)
        };

        let program = gl::CreateProgram();
        gl::AttachShader(program, vertex_shader);
        gl::AttachShader(program, fragment_shader);

        unsafe {
            "out_color".with_c_str(
                |ptr| gl::BindFragDataLocation(program, 0, ptr)
            );
        }

        gl::LinkProgram(program);
        unsafe {
            let a_v4Position = "a_v4Position".with_c_str(
                |ptr| gl::GetAttribLocation(program, ptr)
            );
            let a_v4FillColor = "a_v4FillColor".with_c_str(
                |ptr| gl::GetAttribLocation(program, ptr)
            );
            let a_v2TexCoord = "a_v2TexCoord".with_c_str(
                |ptr| gl::GetAttribLocation(program, ptr)
            );

            TriListXYRGBAUV {
                vertex_shader: vertex_shader,
                fragment_shader: fragment_shader,
                program: program,
                a_v4Position: a_v4Position as GLuint,
                a_v4FillColor: a_v4FillColor as GLuint,
                a_v2TexCoord: a_v2TexCoord as GLuint,
            }
        }
    }

    fn enable_attributes(&self) {
        gl::EnableVertexAttribArray(self.a_v4Position as GLuint);
        gl::EnableVertexAttribArray(self.a_v4FillColor as GLuint);
        gl::EnableVertexAttribArray(self.a_v2TexCoord as GLuint);
    }

    fn disable_attributes(&self) {
        gl::DisableVertexAttribArray(self.a_v4Position as GLuint);
        gl::DisableVertexAttribArray(self.a_v4FillColor as GLuint);
        gl::DisableVertexAttribArray(self.a_v2TexCoord as GLuint);
    }
}

/// Contains OpenGL data.
pub struct Gl {
    tri_list_xy_rgba: TriListXYRGBA,
    tri_list_xy_rgba_uv: TriListXYRGBAUV,
    // id of buffer for xy positions.
    position_id: GLuint,
    // id of buffer for rgba colors.
    fill_color_id: GLuint,
    // id of buffer for uv texture coords.
    tex_coord_id: GLuint,
    // Keeps track of the current shader program.
    current_program: Option<GLuint>,
}

impl<'a> Gl {
    /// Creates a new OpenGl back-end.
    pub fn new() -> Gl {
        // Load the vertices, color and texture coord buffers.
        unsafe {
            let mut vbo : [GLuint, ..3] = [0, ..3];
            gl::GenBuffers(3, vbo.as_mut_ptr());
            gl::GenVertexArrays(3, vbo.as_mut_ptr());
            let position_id = vbo[0];
            let fill_color_id = vbo[1];
            let tex_coord_id = vbo[2];

            Gl {
                tri_list_xy_rgba: TriListXYRGBA::new(),
                tri_list_xy_rgba_uv: TriListXYRGBAUV::new(),
                position_id: position_id,
                fill_color_id: fill_color_id,
                tex_coord_id: tex_coord_id,
                current_program: None,
            }
        }
    }

    /// Sets viewport with normalized coordinates and center as origin.
    pub fn viewport(
        &mut self,
        x: i32,
        y: i32,
        w: i32,
        h: i32
    ) {
        gl::Viewport(x as GLint, y as GLint, w as GLsizei, h as GLsizei);
    }

    /// Sets the current program only if the program is not in use.
    pub fn use_program(&mut self, program: GLuint) {
        match self.current_program {
            None => {},
            Some(current_program) => {
                if program == current_program { return; }
            },
        }

        gl::UseProgram(program);
        self.current_program = Some(program);
    }
}

impl BackEnd<Texture> for Gl {
    fn supports_clear_rgba(&self) -> bool { true }

    fn clear_rgba(&mut self, r: f32, g: f32, b: f32, a: f32) {
        gl::ClearColor(r, g, b, a);
        gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
    }

    fn enable_alpha_blend(&mut self) {
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
    }

    fn disable_alpha_blend(&mut self) {
        gl::Disable(gl::BLEND);
    }

    fn supports_single_texture(&self) -> bool { true }

    fn enable_single_texture(&mut self, texture: &Texture) {
        let texture = texture.get_id();
        gl::BindTexture(gl::TEXTURE_2D, texture);
    }

    fn disable_single_texture(&mut self) {}

    // Assume all textures has alpha channel for now.
    fn has_texture_alpha(&self, _texture: &Texture) -> bool { true }

    fn supports_tri_list_xy_f32_rgba_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32]
    ) {
        {
            // Set shader program.
            let shader_program = self.tri_list_xy_rgba.program;
            self.use_program(shader_program);
        }
        let shader = &self.tri_list_xy_rgba;

        gl::BindVertexArray(self.position_id);
        gl::BindVertexArray(self.fill_color_id);

        shader.enable_attributes();

        // xy makes two floats.
        let size_vertices: i32 = 2;
        let vertices_byte_len = (
                vertices.len() * mem::size_of::<GLfloat>()
            ) as GLsizeiptr;
        let normalize_vertices = gl::FALSE;
        // The data is tightly packed.
        let stride_vertices = 0;
        gl::BindBuffer(
            gl::ARRAY_BUFFER,   // buffer type
            self.position_id    // position buffer for xy coordinates
        );
        unsafe {
            gl::BufferData(
                gl::ARRAY_BUFFER,
                vertices_byte_len,
                mem::transmute(&vertices[0]),
                gl::DYNAMIC_DRAW
            );
            gl::VertexAttribPointer(
                shader.a_v4Position as GLuint,
                size_vertices,
                gl::FLOAT,
                normalize_vertices,
                stride_vertices,
                ptr::null()
            );
        }

        // rgba makes 4 floats.
        let size_fill_colors = 4;
        let normalize_colors = gl::FALSE;
        let fill_colors_byte_len = (
                colors.len() * mem::size_of::<GLfloat>()
            ) as GLsizeiptr;
        // The data is tightly packed.
        let stride_fill_colors = 0;
        unsafe {
            gl::BindBuffer(
                gl::ARRAY_BUFFER,
                self.fill_color_id
            );
            gl::BufferData(
                gl::ARRAY_BUFFER,
                fill_colors_byte_len,
                mem::transmute(&colors[0]),
                gl::DYNAMIC_DRAW
            );
            gl::VertexAttribPointer(
                shader.a_v4FillColor as GLuint,
                size_fill_colors,
                gl::FLOAT,
                normalize_colors,
                stride_fill_colors,
                ptr::null()
            );
        }

        // Render triangles whether they are facing
        // clockwise or counter clockwise.
        gl::CullFace(gl::FRONT_AND_BACK);

        let items: i32 = vertices.len() as i32 / size_vertices;
        gl::DrawArrays(gl::TRIANGLES, 0, items);
        shader.disable_attributes();
    }

    fn supports_tri_list_xy_f32_rgba_f32_uv_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32_uv_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32],
        texture_coords: &[f32]
    ) {
        {
            // Set shader program.
            let shader_program = self.tri_list_xy_rgba_uv.program;
            self.use_program(shader_program);
        }
        let shader = &self.tri_list_xy_rgba_uv;

        gl::BindVertexArray(self.position_id);
        gl::BindVertexArray(self.fill_color_id);
        gl::BindVertexArray(self.tex_coord_id);

        shader.enable_attributes();

        let size_vertices: i32 = 2;
        let normalize_vertices = gl::FALSE;
        let vertices_byte_len = (
                vertices.len() * mem::size_of::<GLfloat>()
            ) as GLsizeiptr;
        // The data is tightly packed.
        let stride_vertices = 0;
        unsafe {
            gl::BindBuffer(
                gl::ARRAY_BUFFER, self.position_id);
            gl::BufferData(
                gl::ARRAY_BUFFER,
                vertices_byte_len,
                mem::transmute(&vertices[0]),
                gl::DYNAMIC_DRAW
            );
            gl::VertexAttribPointer(
                shader.a_v4Position as GLuint,
                size_vertices,
                gl::FLOAT,
                normalize_vertices,
                stride_vertices,
                ptr::null()
            );
        }

        // rgba makes 4 floats.
        let size_fill_color = 4;
        let normalize_fill_color = gl::FALSE;
        let fill_colors_byte_len = (
                colors.len() * mem::size_of::<GLfloat>()
            ) as GLsizeiptr;
        // The data is tightly packed.
        let stride_fill_colors = 0;
        unsafe {
            gl::BindBuffer(
                gl::ARRAY_BUFFER,
                self.fill_color_id
            );
            gl::BufferData(
                gl::ARRAY_BUFFER,
                fill_colors_byte_len,
                mem::transmute(&colors[0]),
                gl::DYNAMIC_DRAW
            );
            gl::VertexAttribPointer(
                shader.a_v4FillColor as GLuint,
                size_fill_color,
                gl::FLOAT,
                normalize_fill_color,
                stride_fill_colors,
                ptr::null()
            );
        }

        // uv makes two floats.
        let size_tex_coord = 2;
        let texture_coords_byte_len = (
                texture_coords.len() * mem::size_of::<GLfloat>()
            ) as GLsizeiptr;
        let normalize_texture_coords = gl::FALSE;
        // The data is tightly packed.
        let stride_texture_coords = 0;
        unsafe {
            gl::BindBuffer(
                gl::ARRAY_BUFFER,
                self.tex_coord_id
            );
            gl::BufferData(
                gl::ARRAY_BUFFER,
                texture_coords_byte_len,
                mem::transmute(&texture_coords[0]),
                gl::DYNAMIC_DRAW
            );
            gl::VertexAttribPointer(
                shader.a_v2TexCoord as GLuint,
                size_tex_coord,
                gl::FLOAT,
                normalize_texture_coords,
                stride_texture_coords,
                ptr::null()
            );
        }

        // Render triangles whether they are facing
        // clockwise or counter clockwise.
        gl::CullFace(gl::FRONT_AND_BACK);

        let items: i32 = vertices.len() as i32 / size_vertices;
        gl::DrawArrays(gl::TRIANGLES, 0, items);

        shader.disable_attributes();
    }
}

<|endoftext|>


<commit_before>extern crate hyper;
extern crate tokio_core;
extern crate futures;

use std::sync::{Arc};
use std::thread;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use self::tokio_core::reactor::Core;
use self::tokio_core::net::TcpListener;
use self::hyper::server::Http;
use self::futures::stream::Stream;

use error::Error;
use config::Config;
use http::dispatcher::Dispatcher;
use http::app_manager::AppManager;

pub struct Server {
    pub thread: thread::JoinHandle<()>,
}

impl Server {
    pub fn create(config: &Config) -> Result<Server, Error> {
        let app_manager = Arc::new(AppManager::new()?);

        let thread = Server::create_thread(app_manager, config.http_port);

        Ok(Server {
            thread: thread,
        })
    }

    fn create_thread(app_manager: Arc<AppManager>, port: u16) -> thread::JoinHandle<()> {
        thread::spawn(move || {
            let http = Http::new();
            let mut core = Core::new().unwrap();
            let handle = core.handle();

            let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port);

            let listener = TcpListener::bind(&address, &handle).unwrap();
            let server = listener.incoming()
                .for_each(|(sock, addr)| {
                    let service = Dispatcher::new(app_manager.clone(), handle.clone());
                    http.bind_connection(&handle, sock, addr, service);
                    Ok(())
                });

            core.run(server).unwrap();
        })
    }
}

<commit_msg>feature: Update to latest hyper<commit_after>extern crate hyper;
extern crate tokio_core;
extern crate futures;

use std::sync::{Arc};
use std::thread;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use self::tokio_core::reactor::Core;
use self::tokio_core::net::TcpListener;
use self::hyper::server::Http;
use self::futures::stream::Stream;
use self::futures::Future;

use error::Error;
use config::Config;
use http::server::hyper::Chunk;
use http::dispatcher::Dispatcher;
use http::app_manager::AppManager;

pub struct Server {
    pub thread: thread::JoinHandle<()>,
}

impl Server {
    pub fn create(config: &Config) -> Result<Server, Error> {
        let app_manager = Arc::new(AppManager::new()?);

        let thread = Server::create_thread(app_manager, config.http_port);

        Ok(Server {
            thread: thread,
        })
    }

    fn create_thread(app_manager: Arc<AppManager>, port: u16) -> thread::JoinHandle<()> {
        thread::spawn(move || {
            let http = Http::<Chunk>::new();
            let mut core = Core::new().unwrap();
            let handle = core.handle();

            let address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port);

            let listener = TcpListener::bind(&address, &handle).unwrap();

            let server = listener.incoming().for_each(|(sock, _)| {
                let service = Dispatcher::new(app_manager.clone(), handle.clone());
                let conn = http.serve_connection(sock, service);
                let fut = conn
                    .map(|_| ())
                    .map_err(|e| eprintln!("server connection error: {}", e));
                handle.spawn(fut);
                Ok(())
            });

            core.run(server).unwrap();
        })
    }
}

<|endoftext|>


<commit_before>extern crate openssl;
extern crate openssl_verify;

use std::io;
use std::fmt;
use std::error;
use self::openssl::ssl::{self, SslContext, SslMethod, SSL_VERIFY_PEER, IntoSsl};
use self::openssl::ssl::error::SslError;
use self::openssl_verify::verify_callback;

pub struct Error(SslError);

impl error::Error for Error {
    fn description(&self) -> &str {
        error::Error::description(&self.0)
    }

    fn cause(&self) -> Option<&error::Error> {
        error::Error::cause(&self.0)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, fmt)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<SslError> for Error {
    fn from(err: SslError) -> Error {
        Error(err)
    }
}

pub struct ClientBuilder(SslContext);

impl ClientBuilder {
    pub fn new() -> Result<ClientBuilder, Error> {
        let mut ctx = try!(SslContext::new(SslMethod::Sslv23));
        try!(ctx.set_default_verify_paths());
        Ok(ClientBuilder(ctx))
    }

    pub fn handshake<S>(&mut self, domain: &str, stream: S) -> Result<TlsStream<S>, Error>
        where S: io::Read + io::Write
    {
        let mut ssl = try!(self.0.into_ssl());
        try!(ssl.set_hostname(domain));
        let domain = domain.to_owned();
        ssl.set_verify_callback(SSL_VERIFY_PEER, move |p, x| verify_callback(&domain, p, x));

        let s = try!(ssl::SslStream::connect(ssl, stream));
        Ok(TlsStream(s))
    }
}

pub struct TlsStream<S>(ssl::SslStream<S>);

impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S: io::Read + io::Write> TlsStream<S> {
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }
}

impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}
<commit_msg>Add some better configs for openssl<commit_after>extern crate openssl;
extern crate openssl_verify;

use std::io;
use std::fmt;
use std::error;
use self::openssl::ssl::{self, SslContext, SslMethod, SSL_VERIFY_PEER, IntoSsl, SSL_OP_NO_SSLV2,
                         SSL_OP_NO_SSLV3, SSL_OP_NO_COMPRESSION};
use self::openssl::ssl::error::SslError;
use self::openssl_verify::verify_callback;

pub struct Error(SslError);

impl error::Error for Error {
    fn description(&self) -> &str {
        error::Error::description(&self.0)
    }

    fn cause(&self) -> Option<&error::Error> {
        error::Error::cause(&self.0)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, fmt)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<SslError> for Error {
    fn from(err: SslError) -> Error {
        Error(err)
    }
}

pub struct ClientBuilder(SslContext);

impl ClientBuilder {
    pub fn new() -> Result<ClientBuilder, Error> {
        let mut ctx = try!(SslContext::new(SslMethod::Sslv23));
        ctx.set_options(SSL_OP_NO_SSLV2 | SSL_OP_NO_SSLV3 | SSL_OP_NO_COMPRESSION);
        try!(ctx.set_default_verify_paths());
        try!(ctx.set_cipher_list("ALL!EXPORT!EXPORT40!EXPORT56!aNULL!LOW!RC4@STRENGTH"));
        Ok(ClientBuilder(ctx))
    }

    pub fn handshake<S>(&mut self, domain: &str, stream: S) -> Result<TlsStream<S>, Error>
        where S: io::Read + io::Write
    {
        let mut ssl = try!(self.0.into_ssl());
        try!(ssl.set_hostname(domain));
        let domain = domain.to_owned();
        ssl.set_verify_callback(SSL_VERIFY_PEER, move |p, x| verify_callback(&domain, p, x));

        let s = try!(ssl::SslStream::connect(ssl, stream));
        Ok(TlsStream(s))
    }
}

pub struct TlsStream<S>(ssl::SslStream<S>);

impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S: io::Read + io::Write> TlsStream<S> {
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }
}

impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}
<|endoftext|>