<commit_before>// Copyright 2018 Google Inc.
//
// 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
//
//     https://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 dirs;
use evcxr;

use colored::*;
use evcxr::{CommandContext, CompilationError, Error};
use rustyline::{error::ReadlineError, Editor};
use std::fs;
use std::io;
use std::sync::mpsc;

const PROMPT: &str = ">> ";

struct Repl {
    command_context: CommandContext,
}

fn send_output<T: io::Write + Send + 'static>(channel: mpsc::Receiver<String>, mut output: T) {
    std::thread::spawn(move || {
        while let Ok(line) = channel.recv() {
            if writeln!(output, "{}", line).is_err() {
                break;
            }
        }
    });
}

impl Repl {
    fn new() -> Result<Repl, Error> {
        let (command_context, outputs) = CommandContext::new()?;
        send_output(outputs.stdout, io::stdout());
        send_output(outputs.stderr, io::stderr());
        let mut repl = Repl { command_context };
        repl.execute(":load_config");
        Ok(repl)
    }

    fn execute(&mut self, to_run: &str) {
        match self.command_context.execute(to_run) {
            Ok(output) => {
                if let Some(text) = output.get("text/plain") {
                    println!("{}", text);
                }
                if let Some(duration) = output.timing {
                    println!("{}", format!("Took {}ms", duration.as_millis()).blue());

                    for phase in output.phases {
                        println!(
                            "{}",
                            format!("  {}: {}ms", phase.name, phase.duration.as_millis()).blue()
                        );
                    }
                }
            }
            Err(evcxr::Error::CompilationErrors(errors)) => {
                self.display_errors(errors);
            }
            Err(err) => eprintln!("{}", format!("{}", err).bright_red()),
        }
    }

    fn display_errors(&mut self, errors: Vec<CompilationError>) {
        for error in errors {
            if error.is_from_user_code() {
                for spanned_message in error.spanned_messages() {
                    if let Some(span) = &spanned_message.span {
                        for _ in 1..span.start_column + PROMPT.len() {
                            print!(" ");
                        }
                        let mut carrots = String::new();
                        for _ in span.start_column..span.end_column {
                            carrots.push('^');
                        }
                        print!("{}", carrots.bright_red());
                        println!(" {}", spanned_message.label.bright_blue());
                    } else {
                        // Our error originates from both user-code and generated
                        // code.
                        println!("{}", spanned_message.label.bright_blue());
                    }
                }
                println!("{}", error.message().bright_red());
                for help in error.help() {
                    println!("{} {}", "help:".bold(), help);
                }
                if let Some(extra_hint) = error.evcxr_extra_hint() {
                    println!("{}", extra_hint);
                }
            } else {
                println!(
                    "A compilation error was found in code we generated.\n\
                     Ideally this should't happen. Type :last_error_json to see details.\n{}",
                    error.rendered()
                );
            }
        }
    }
}

fn main() {
    evcxr::runtime_hook();
    println!("Welcome to evcxr. For help, type :help");
    let mut repl = match Repl::new() {
        Ok(c) => c,
        Err(error) => {
            eprintln!("{}", error);
            return;
        }
    };

    let mut editor = Editor::<()>::new();
    let mut opt_history_file = None;
    let config_dir = dirs::config_dir().map(|h| h.join("evcxr"));
    if let Some(config_dir) = &config_dir {
        fs::create_dir_all(config_dir).ok();
        let history_file = config_dir.join("history.txt");
        editor.load_history(&history_file).ok();
        opt_history_file = Some(history_file);
    }
    loop {
        let prompt = format!("{}", PROMPT.yellow());
        let readline = editor.readline(&prompt);
        match readline {
            Ok(line) => {
                editor.add_history_entry(line.clone());
                repl.execute(&line);
            }
            Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => break,
            Err(err) => {
                eprintln!("Error: {:?}", err);
                break;
            }
        }
    }
    if let Some(history_file) = &opt_history_file {
        editor.save_history(&history_file).ok();
    }
}
<commit_msg>Add flag for disabling readline<commit_after>// Copyright 2018 Google Inc.
//
// 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
//
//     https://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 dirs;
use evcxr;

use colored::*;
use evcxr::{CommandContext, CompilationError, Error};
use rustyline::{error::ReadlineError, Editor};
use std::fs;
use std::io;
use std::sync::mpsc;

const PROMPT: &str = ">> ";

struct Repl {
    command_context: CommandContext,
}

fn send_output<T: io::Write + Send + 'static>(channel: mpsc::Receiver<String>, mut output: T) {
    std::thread::spawn(move || {
        while let Ok(line) = channel.recv() {
            if writeln!(output, "{}", line).is_err() {
                break;
            }
        }
    });
}

impl Repl {
    fn new() -> Result<Repl, Error> {
        let (command_context, outputs) = CommandContext::new()?;
        send_output(outputs.stdout, io::stdout());
        send_output(outputs.stderr, io::stderr());
        let mut repl = Repl { command_context };
        repl.execute(":load_config");
        Ok(repl)
    }

    fn execute(&mut self, to_run: &str) {
        match self.command_context.execute(to_run) {
            Ok(output) => {
                if let Some(text) = output.get("text/plain") {
                    println!("{}", text);
                }
                if let Some(duration) = output.timing {
                    println!("{}", format!("Took {}ms", duration.as_millis()).blue());

                    for phase in output.phases {
                        println!(
                            "{}",
                            format!("  {}: {}ms", phase.name, phase.duration.as_millis()).blue()
                        );
                    }
                }
            }
            Err(evcxr::Error::CompilationErrors(errors)) => {
                self.display_errors(errors);
            }
            Err(err) => eprintln!("{}", format!("{}", err).bright_red()),
        }
    }

    fn display_errors(&mut self, errors: Vec<CompilationError>) {
        for error in errors {
            if error.is_from_user_code() {
                for spanned_message in error.spanned_messages() {
                    if let Some(span) = &spanned_message.span {
                        for _ in 1..span.start_column + PROMPT.len() {
                            print!(" ");
                        }
                        let mut carrots = String::new();
                        for _ in span.start_column..span.end_column {
                            carrots.push('^');
                        }
                        print!("{}", carrots.bright_red());
                        println!(" {}", spanned_message.label.bright_blue());
                    } else {
                        // Our error originates from both user-code and generated
                        // code.
                        println!("{}", spanned_message.label.bright_blue());
                    }
                }
                println!("{}", error.message().bright_red());
                for help in error.help() {
                    println!("{} {}", "help:".bold(), help);
                }
                if let Some(extra_hint) = error.evcxr_extra_hint() {
                    println!("{}", extra_hint);
                }
            } else {
                println!(
                    "A compilation error was found in code we generated.\n\
                     Ideally this should't happen. Type :last_error_json to see details.\n{}",
                    error.rendered()
                );
            }
        }
    }
}

fn readline_direct(prompt: &str) -> rustyline::Result<String> {
    use std::io::Write;

    // Write prompt and flush it to stdout
    let mut stdout = io::stdout();
    stdout.write_all(prompt.as_bytes())?;
    stdout.flush()?;

    let mut line = String::new();
    if io::stdin().read_line(&mut line)? > 0 {
        Ok(line)
    } else {
        Err(rustyline::error::ReadlineError::Eof)
    }
}

fn main() {
    evcxr::runtime_hook();
    println!("Welcome to evcxr. For help, type :help");
    let mut repl = match Repl::new() {
        Ok(c) => c,
        Err(error) => {
            eprintln!("{}", error);
            return;
        }
    };

    let disable_readline = std::env::args().any(|x| x == "--disable-readline");

    let mut editor = Editor::<()>::new();
    let mut opt_history_file = None;
    let config_dir = dirs::config_dir().map(|h| h.join("evcxr"));
    if let Some(config_dir) = &config_dir {
        fs::create_dir_all(config_dir).ok();
        let history_file = config_dir.join("history.txt");
        editor.load_history(&history_file).ok();
        opt_history_file = Some(history_file);
    }
    loop {
        let prompt = format!("{}", PROMPT.yellow());
        let readline = if disable_readline {
            readline_direct(&prompt)
        } else {
            editor.readline(&prompt)
        };
        match readline {
            Ok(line) => {
                editor.add_history_entry(line.clone());
                repl.execute(&line);
            }
            Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => break,
            Err(err) => {
                eprintln!("Error: {:?}", err);
                break;
            }
        }
    }
    if let Some(history_file) = &opt_history_file {
        editor.save_history(&history_file).ok();
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Abstractions for global scopes.

use dom::bindings::js::{JS, JSRef, Root};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::window::Window;
use page::Page;
use script_task::ScriptChan;

use js::jsapi::JSContext;

use url::Url;

pub enum GlobalRef<'a> {
    Window(JSRef<'a, Window>),
}

pub enum GlobalRoot<'a, 'b> {
    WindowRoot(Root<'a, 'b, Window>),
}

#[deriving(Encodable)]
pub enum GlobalField {
    WindowField(JS<Window>),
}

impl<'a> GlobalRef<'a> {
    pub fn get_cx(&self) -> *mut JSContext {
        match *self {
            Window(ref window) => window.get_cx(),
        }
    }

    pub fn as_window<'b>(&'b self) -> &'b JSRef<'b, Window> {
        match *self {
            Window(ref window) => window,
        }
    }

    pub fn page<'b>(&'b self) -> &'b Page {
        self.as_window().page()
    }

    pub fn get_url(&self) -> Url {
        self.as_window().get_url()
    }

    pub fn script_chan<'b>(&'b self) -> &'b ScriptChan {
        &self.as_window().script_chan
    }
}

impl<'a> Reflectable for GlobalRef<'a> {
    fn reflector<'b>(&'b self) -> &'b Reflector {
        match *self {
            Window(ref window) => window.reflector(),
        }
    }
}

impl<'a, 'b> GlobalRoot<'a, 'b> {
    pub fn root_ref<'c>(&'c self) -> GlobalRef<'c> {
        match *self {
            WindowRoot(ref window) => Window(window.root_ref()),
        }
    }
}

impl GlobalField {
    pub fn from_rooted(global: &GlobalRef) -> GlobalField {
        match *global {
            Window(ref window) => WindowField(JS::from_rooted(window)),
        }
    }

    pub fn root(&self) -> GlobalRoot {
        match *self {
            WindowField(ref window) => WindowRoot(window.root()),
        }
    }
}
<commit_msg>Add worker scope variants to the Global enums.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Abstractions for global scopes.

use dom::bindings::js::{JS, JSRef, Root};
use dom::bindings::utils::{Reflectable, Reflector};
use dom::workerglobalscope::WorkerGlobalScope;
use dom::window::Window;
use page::Page;
use script_task::ScriptChan;

use js::jsapi::JSContext;

use url::Url;

pub enum GlobalRef<'a> {
    Window(JSRef<'a, Window>),
    Worker(JSRef<'a, WorkerGlobalScope>),
}

pub enum GlobalRoot<'a, 'b> {
    WindowRoot(Root<'a, 'b, Window>),
    WorkerRoot(Root<'a, 'b, WorkerGlobalScope>),
}

#[deriving(Encodable)]
pub enum GlobalField {
    WindowField(JS<Window>),
    WorkerField(JS<WorkerGlobalScope>),
}

impl<'a> GlobalRef<'a> {
    pub fn get_cx(&self) -> *mut JSContext {
        match *self {
            Window(ref window) => window.get_cx(),
            Worker(_) => fail!("NYI"),
        }
    }

    pub fn as_window<'b>(&'b self) -> &'b JSRef<'b, Window> {
        match *self {
            Window(ref window) => window,
            Worker(_) => fail!("expected a Window scope"),
        }
    }

    pub fn page<'b>(&'b self) -> &'b Page {
        self.as_window().page()
    }

    pub fn get_url(&self) -> Url {
        self.as_window().get_url()
    }

    pub fn script_chan<'b>(&'b self) -> &'b ScriptChan {
        &self.as_window().script_chan
    }
}

impl<'a> Reflectable for GlobalRef<'a> {
    fn reflector<'b>(&'b self) -> &'b Reflector {
        match *self {
            Window(ref window) => window.reflector(),
            Worker(ref worker) => worker.reflector(),
        }
    }
}

impl<'a, 'b> GlobalRoot<'a, 'b> {
    pub fn root_ref<'c>(&'c self) -> GlobalRef<'c> {
        match *self {
            WindowRoot(ref window) => Window(window.root_ref()),
            WorkerRoot(ref worker) => Worker(worker.root_ref()),
        }
    }
}

impl GlobalField {
    pub fn from_rooted(global: &GlobalRef) -> GlobalField {
        match *global {
            Window(ref window) => WindowField(JS::from_rooted(window)),
            Worker(ref worker) => WorkerField(JS::from_rooted(worker)),
        }
    }

    pub fn root(&self) -> GlobalRoot {
        match *self {
            WindowField(ref window) => WindowRoot(window.root()),
            WorkerField(ref worker) => WorkerRoot(worker.root()),
        }
    }
}
<|endoftext|>


<commit_before>//! Run the learning code with a single scale.

extern crate midilearn;

use midilearn::{MidiLearn, Problem};

fn main() {
    let prob = Problem::new("scale: C major",
                            r#"{
                                "type": "scale",
                                "base": "C",
                                "intervals": "WWHWWWH",
                                "hands": 1,
                                "octaves": 2,
                                "style": "updown"
                            }"#);
    println!("Learn a single word");

    MidiLearn::with_new(|learn: &mut MidiLearn| {
        println!("Status: {:?}", learn.single(&prob));
    }).unwrap();
}
<commit_msg>Fix midilearn scale example<commit_after>//! Run the learning code with a single scale.

extern crate midilearn;

use midilearn::{MidiLearn, Problem, User};

fn main() {
    let prob = Problem::new("scale: C major",
                            r#"{
                                "type": "scale",
                                "base": "C",
                                "intervals": "WWHWWWH",
                                "hands": 1,
                                "octaves": 2,
                                "style": "updown"
                            }"#);
    println!("Learn a single word");

    MidiLearn::with_new(|learn: &mut MidiLearn| {
        println!("Status: {:?}", learn.single(&prob));
    }).unwrap();
}
<|endoftext|>


<commit_before>/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

#![feature(thread_local)]
#![feature(std_misc)]
#![feature(alloc)]

#[macro_use]
extern crate autograd;

use autograd::Context;

#[test]
fn single_thread_multiple_run() {
    for _ in 0..10 {
        // TODO make it longer to run.
        let context = new_autograd_context!(f32, 1000);
        let x1 = context.new_variable(1.5);
        let x2 = context.new_variable(2.5);

        let y = x1 * x2;
        assert_eq!(y.value, 3.75);

        context.differentiate(y);
        assert_eq!(context.get_derivative(x1), 2.5);
        assert_eq!(context.get_derivative(x2), 1.5);
        assert_eq!(context.get_derivative(y), 1.);
    }
}

#[test]
fn multi_thread_multiple_run() {
    // TODO Insert purposeful sleep for each task?
    let task_pool = std::sync::TaskPool::new(10);
    let semaphore = std::sync::Arc::new(std::sync::Semaphore::new(-999));
    for _ in 0..1000 {
        let semaphore_task = semaphore.clone();
        task_pool.execute(move || {
            single_thread_multiple_run();
            semaphore_task.release();
        });
    }
    semaphore.access();
}

#[test]
#[should_panic(expected = "This Context instance is in use now. Note that a Context instance is allowed per construction location and per thread. Consequently, it cannot be recursively constructed unless it is destructed. This is a limitation caused by the thread local static variables usages in the current implementation.")]
#[allow(unused_variables)]
fn context_lock() {
    fn recursive_context(n: usize) {
        if n > 0 {
            let context = new_autograd_context!(f32, 10);
            recursive_context(n - 1);
        }
    }
    recursive_context(2);
}

#[test]
#[allow(unused_variables)]
fn context_capacity_expression_argument() {
    let a = 200;
    let b = 10;
    let context = new_autograd_context!(f32, a/b);
}

#[test]
fn capacity_full() {
    let context = new_autograd_context!(f32, 100);
    for _ in 0..99 {
        context.new_variable(1.);
    }
    let y = context.new_variable(1.);
    context.differentiate(y)
}

// TODO Test capacity overflow check at context.differentiate(...). But it will be double-panic since it's also panicking at Drop.

#[test]
#[should_panic(expected = "There are more recorded variables, 101, than its capacity, 100. Memory is corrupted. Please consider using bigger capacity.")]
fn capacity_overflow_drop() {
    let context = new_autograd_context!(f32, 100);
    for _ in 0..101 {
        context.new_variable(1.);
    }
}
<commit_msg>Disable broken multi_thread_multiple_run test.<commit_after>/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

#![feature(thread_local)]
#![feature(std_misc)]
#![feature(alloc)]

#[macro_use]
extern crate autograd;

use autograd::Context;

#[test]
fn single_thread_multiple_run() {
    for _ in 0..10 {
        // TODO make it longer to run.
        let context = new_autograd_context!(f32, 1000);
        let x1 = context.new_variable(1.5);
        let x2 = context.new_variable(2.5);

        let y = x1 * x2;
        assert_eq!(y.value, 3.75);

        context.differentiate(y);
        assert_eq!(context.get_derivative(x1), 2.5);
        assert_eq!(context.get_derivative(x2), 1.5);
        assert_eq!(context.get_derivative(y), 1.);
    }
}

// TODO std::sync::TaskPool is removed. https://github.com/rust-lang/rust/pull/22783
//      Find a way to re-enable this test.

// #[test]
// fn multi_thread_multiple_run() {
//     // TODO Insert purposeful sleep for each task?
//     let task_pool = std::sync::TaskPool::new(10);
//     let semaphore = std::sync::Arc::new(std::sync::Semaphore::new(-999));
//     for _ in 0..1000 {
//         let semaphore_task = semaphore.clone();
//         task_pool.execute(move || {
//             single_thread_multiple_run();
//             semaphore_task.release();
//         });
//     }
//     semaphore.access();
// }

#[test]
#[should_panic(expected = "This Context instance is in use now. Note that a Context instance is allowed per construction location and per thread. Consequently, it cannot be recursively constructed unless it is destructed. This is a limitation caused by the thread local static variables usages in the current implementation.")]
#[allow(unused_variables)]
fn context_lock() {
    fn recursive_context(n: usize) {
        if n > 0 {
            let context = new_autograd_context!(f32, 10);
            recursive_context(n - 1);
        }
    }
    recursive_context(2);
}

#[test]
#[allow(unused_variables)]
fn context_capacity_expression_argument() {
    let a = 200;
    let b = 10;
    let context = new_autograd_context!(f32, a/b);
}

#[test]
fn capacity_full() {
    let context = new_autograd_context!(f32, 100);
    for _ in 0..99 {
        context.new_variable(1.);
    }
    let y = context.new_variable(1.);
    context.differentiate(y)
}

// TODO Test capacity overflow check at context.differentiate(...). But it will be double-panic since it's also panicking at Drop.

#[test]
#[should_panic(expected = "There are more recorded variables, 101, than its capacity, 100. Memory is corrupted. Please consider using bigger capacity.")]
fn capacity_overflow_drop() {
    let context = new_autograd_context!(f32, 100);
    for _ in 0..101 {
        context.new_variable(1.);
    }
}
<|endoftext|>


<commit_before>use libimagstore::storeid::StoreId;
use libimagstore::store::Entry;
use libimagstore::store::EntryHeader;
use libimagstore::store::Result as StoreResult;

use error::{LinkError, LinkErrorKind};
use result::Result;

use toml::Value;

pub type Link = StoreId;

pub trait InternalLinker {

    /// Get the internal links from the implementor object
    fn get_internal_links(&self) -> Result<Vec<Link>>;

    /// Set the internal links for the implementor object
    fn set_internal_links(&mut self, links: Vec<&mut Entry>) -> Result<Vec<Link>>;

    /// Add an internal link to the implementor object
    fn add_internal_link(&mut self, link: &mut Entry) -> Result<()>;

    /// Remove an internal link from the implementor object
    fn remove_internal_link(&mut self, link: &mut Entry) -> Result<()>;

}

impl InternalLinker for Entry {

    fn get_internal_links(&self) -> Result<Vec<Link>> {
        process_rw_result(self.get_header().read("imag.links"))
    }

    /// Set the links in a header and return the old links, if any.
    fn set_internal_links(&mut self, links: Vec<&mut Entry>) -> Result<Vec<Link>> {
        let self_location = self.get_location().clone();
        let mut new_links = vec![];

        for link in links {
            if let Err(e) = add_foreign_link(link, self_location.clone()) {
                return Err(e);
            }
            let link = link.get_location().clone();
            let link = link.to_str();
            if link.is_none() {
                return Err(LinkError::new(LinkErrorKind::InternalConversionError, None));
            }
            let link = link.unwrap();

            new_links.push(Value::String(String::from(link)));
        }

        process_rw_result(self.get_header_mut().set("imag.links", Value::Array(new_links)))
    }

    fn add_internal_link(&mut self, link: &mut Entry) -> Result<()> {
        let new_link = link.get_location().clone();

        add_foreign_link(link, self.get_location().clone())
            .and_then(|_| {
                self.get_internal_links()
                    .and_then(|mut links| {
                        links.push(new_link);
                        rewrite_links(self.get_header_mut(), links)
                    })
            })
    }

    fn remove_internal_link(&mut self, link: &mut Entry) -> Result<()> {
        let own_loc   = link.get_location().clone();
        let other_loc = link.get_location().clone();

        link.get_internal_links()
            .and_then(|links| {
                let links = links.into_iter().filter(|l| l.clone() != own_loc).collect();
                rewrite_links(self.get_header_mut(), links)
            })
            .and_then(|_| {
                self.get_internal_links()
                    .and_then(|links| {
                        let links = links.into_iter().filter(|l| l.clone() != other_loc).collect();
                        rewrite_links(link.get_header_mut(), links)
                    })
            })
    }

}

fn rewrite_links(header: &mut EntryHeader, links: Vec<StoreId>) -> Result<()> {
    let links : Vec<Option<Value>> = links
        .into_iter()
        .map(|s| s.to_str().map(|s| Value::String(String::from(s))))
        .collect();

    if links.iter().any(|o| o.is_none()) {
        // if any type convert failed we fail as well
        Err(LinkError::new(LinkErrorKind::InternalConversionError, None))
    } else {
        // I know it is ugly
        let links = links.into_iter().map(|opt| opt.unwrap()).collect();
        let process = header.set("imag.links", Value::Array(links));
        process_rw_result(process).map(|_| ())
    }
}

/// When Linking A -> B, the specification wants us to link back B -> A.
/// This is a helper function which does this.
fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> {
    target.get_internal_links()
        .and_then(|mut links| {
            links.push(from);
            let links : Vec<Option<Value>> = links
                .into_iter()
                .map(|s| {
                    match s.to_str() {
                        Some(s) => Some(Value::String(String::from(s))),
                        _ => None
                    }
                })
                .collect();
            if links.iter().any(|o| o.is_none()) {
                Err(LinkError::new(LinkErrorKind::InternalConversionError, None))
            } else {
                let links = links.into_iter().map(|opt| opt.unwrap()).collect();
                process_rw_result(target.get_header_mut().set("imag.links", Value::Array(links)))
                    .map(|_| ())
            }
        })
}

fn process_rw_result(links: StoreResult<Option<Value>>) -> Result<Vec<Link>> {
    if links.is_err() {
        let lerr  = LinkError::new(LinkErrorKind::EntryHeaderReadError,
                                   Some(Box::new(links.err().unwrap())));
        return Err(lerr);
    }
    let links = links.unwrap();

    if links.iter().any(|l| match l { &Value::String(_) => true, _ => false }) {
        return Err(LinkError::new(LinkErrorKind::ExistingLinkTypeWrong, None));
    }

    let links : Vec<Link> = links.into_iter()
        .map(|link| {
            match link {
                Value::String(s) => StoreId::from(s),
                _ => unreachable!(),
            }
        })
        .collect();

    Ok(links)
}

<commit_msg>Rewrite process_rw_result()<commit_after>use libimagstore::storeid::StoreId;
use libimagstore::store::Entry;
use libimagstore::store::EntryHeader;
use libimagstore::store::Result as StoreResult;

use error::{LinkError, LinkErrorKind};
use result::Result;

use toml::Value;

pub type Link = StoreId;

pub trait InternalLinker {

    /// Get the internal links from the implementor object
    fn get_internal_links(&self) -> Result<Vec<Link>>;

    /// Set the internal links for the implementor object
    fn set_internal_links(&mut self, links: Vec<&mut Entry>) -> Result<Vec<Link>>;

    /// Add an internal link to the implementor object
    fn add_internal_link(&mut self, link: &mut Entry) -> Result<()>;

    /// Remove an internal link from the implementor object
    fn remove_internal_link(&mut self, link: &mut Entry) -> Result<()>;

}

impl InternalLinker for Entry {

    fn get_internal_links(&self) -> Result<Vec<Link>> {
        process_rw_result(self.get_header().read("imag.links"))
    }

    /// Set the links in a header and return the old links, if any.
    fn set_internal_links(&mut self, links: Vec<&mut Entry>) -> Result<Vec<Link>> {
        let self_location = self.get_location().clone();
        let mut new_links = vec![];

        for link in links {
            if let Err(e) = add_foreign_link(link, self_location.clone()) {
                return Err(e);
            }
            let link = link.get_location().clone();
            let link = link.to_str();
            if link.is_none() {
                return Err(LinkError::new(LinkErrorKind::InternalConversionError, None));
            }
            let link = link.unwrap();

            new_links.push(Value::String(String::from(link)));
        }

        process_rw_result(self.get_header_mut().set("imag.links", Value::Array(new_links)))
    }

    fn add_internal_link(&mut self, link: &mut Entry) -> Result<()> {
        let new_link = link.get_location().clone();

        add_foreign_link(link, self.get_location().clone())
            .and_then(|_| {
                self.get_internal_links()
                    .and_then(|mut links| {
                        links.push(new_link);
                        rewrite_links(self.get_header_mut(), links)
                    })
            })
    }

    fn remove_internal_link(&mut self, link: &mut Entry) -> Result<()> {
        let own_loc   = link.get_location().clone();
        let other_loc = link.get_location().clone();

        link.get_internal_links()
            .and_then(|links| {
                let links = links.into_iter().filter(|l| l.clone() != own_loc).collect();
                rewrite_links(self.get_header_mut(), links)
            })
            .and_then(|_| {
                self.get_internal_links()
                    .and_then(|links| {
                        let links = links.into_iter().filter(|l| l.clone() != other_loc).collect();
                        rewrite_links(link.get_header_mut(), links)
                    })
            })
    }

}

fn rewrite_links(header: &mut EntryHeader, links: Vec<StoreId>) -> Result<()> {
    let links : Vec<Option<Value>> = links
        .into_iter()
        .map(|s| s.to_str().map(|s| Value::String(String::from(s))))
        .collect();

    if links.iter().any(|o| o.is_none()) {
        // if any type convert failed we fail as well
        Err(LinkError::new(LinkErrorKind::InternalConversionError, None))
    } else {
        // I know it is ugly
        let links = links.into_iter().map(|opt| opt.unwrap()).collect();
        let process = header.set("imag.links", Value::Array(links));
        process_rw_result(process).map(|_| ())
    }
}

/// When Linking A -> B, the specification wants us to link back B -> A.
/// This is a helper function which does this.
fn add_foreign_link(target: &mut Entry, from: StoreId) -> Result<()> {
    target.get_internal_links()
        .and_then(|mut links| {
            links.push(from);
            let links : Vec<Option<Value>> = links
                .into_iter()
                .map(|s| {
                    match s.to_str() {
                        Some(s) => Some(Value::String(String::from(s))),
                        _ => None
                    }
                })
                .collect();
            if links.iter().any(|o| o.is_none()) {
                Err(LinkError::new(LinkErrorKind::InternalConversionError, None))
            } else {
                let links = links.into_iter().map(|opt| opt.unwrap()).collect();
                process_rw_result(target.get_header_mut().set("imag.links", Value::Array(links)))
                    .map(|_| ())
            }
        })
}

fn process_rw_result(links: StoreResult<Option<Value>>) -> Result<Vec<Link>> {
    if links.is_err() {
        debug!("RW action on store failed. Generating LinkError");
        let lerr  = LinkError::new(LinkErrorKind::EntryHeaderReadError,
                                   Some(Box::new(links.err().unwrap())));
        return Err(lerr);
    }
    let links = links.unwrap();

    if links.is_none() {
        debug!("We got no value from the header!");
        return Ok(vec![])
    }
    let links = links.unwrap();

    let links = {
        match links {
            Value::Array(a) => a,
            _ => {
                debug!("We expected an Array for the links, but there was a non-Array!");
                return Err(LinkError::new(LinkErrorKind::ExistingLinkTypeWrong, None));
            },
        }
    };

    if !links.iter().all(|l| match l { &Value::String(_) => true, _ => false }) {
        debug!("At least one of the Values which were expected in the Array of links is a non-String!");
        debug!("Generating LinkError");
        return Err(LinkError::new(LinkErrorKind::ExistingLinkTypeWrong, None));
    }

    let links : Vec<Link> = links.into_iter()
        .map(|link| {
            match link {
                Value::String(s) => StoreId::from(s),
                _ => unreachable!(),
            }
        })
        .collect();

    debug!("Ok, the RW action was successful, returning link vector now!");
    Ok(links)
}

<|endoftext|>


<commit_before>//! The Ref object is a helper over the link functionality, so one is able to create references to
//! files outside of the imag store.

use std::path::PathBuf;
use std::ops::Deref;
use std::ops::DerefMut;

use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId;
use libimagstore::store::Store;
use libimagerror::into::IntoError;

use toml::Value;

use error::RefErrorKind as REK;
use flags::RefFlags;
use result::Result;

pub struct Ref<'a>(FileLockEntry<'a>);

impl<'a> Ref<'a> {

    /// Try to get `si` as Ref object from the store
    pub fn get(store: &'a Store, si: StoreId) -> Result<Ref<'a>> {
        match store.get(si) {
            Err(e) => return Err(REK::StoreReadError.into_error_with_cause(Box::new(e))),
            Ok(None) => return Err(REK::RefNotInStore.into_error()),
            Ok(Some(fle)) => Ref::read_reference(&fle).map(|_| Ref(fle)),
        }
    }

    fn read_reference(fle: &FileLockEntry<'a>) -> Result<PathBuf> {
        match fle.get_header().read("ref.reference") {
            Ok(Some(Value::String(s))) => Ok(PathBuf::from(s)),
            Ok(Some(_)) => Err(REK::HeaderTypeError.into_error()),
            Ok(None)    => Err(REK::HeaderFieldMissingError.into_error()),
            Err(e)      => Err(REK::StoreReadError.into_error_with_cause(Box::new(e))),
        }
    }

    /// Create a Ref object which refers to `pb`
    pub fn create(store: &Store, pb: PathBuf, flags: RefFlags) -> Result<Ref<'a>> {
        unimplemented!()
    }

    /// Creates a Hash from a PathBuf by making the PathBuf absolute and then running a hash
    /// algorithm on it
    fn hash_path(pb: &PathBuf) -> String {
        unimplemented!()
    }

    /// check whether the pointer the Ref represents still points to a file which exists
    pub fn fs_link_exists(&self) -> bool {
        unimplemented!()
    }

    /// Alias for `!Ref::fs_link_exists()`
    pub fn is_dangling(&self) -> bool {
        !self.fs_link_exists()
    }

    /// check whether the pointer the Ref represents is valid
    /// This includes:
    ///     - Hashsum of the file is still the same as stored in the Ref
    ///     - file permissions are still valid
    pub fn fs_link_valid(&self) -> bool {
        unimplemented!()
    }

    /// Check whether the file permissions of the referenced file are equal to the stored
    /// permissions
    pub fn fs_link_valid_permissions(&self) -> bool {
        unimplemented!()
    }

    /// Check whether the Hashsum of the referenced file is equal to the stored hashsum
    pub fn fs_link_valid_hash(&self) -> bool {
        unimplemented!()
    }

    /// Update the Ref by re-checking the file from FS
    /// This errors if the file is not present or cannot be read()
    pub fn update_ref(&mut self) -> Result<()> {
        unimplemented!()
    }

    /// Get the path of the file which is reffered to by this Ref
    pub fn fs_file(&self) -> &PathBuf {
        unimplemented!()
    }

    /// Check whether there is a reference to the file at `pb`
    pub fn exists(store: &Store, pb: PathBuf) -> Result<bool> {
        unimplemented!()
    }

    /// Re-find a referenced file
    ///
    /// This function tries to re-find a ref by searching all directories in `search_roots` recursively
    /// for a file which matches the hash of the Ref `ref`.
    ///
    /// If `search_roots` is `None`, it starts at the filesystem root `/`.
    ///
    /// # Warning
    ///
    /// This option causes heavy I/O as it recursively searches the Filesystem.
    pub fn refind(&self, search_roots: Option<Vec<PathBuf>>) -> Option<PathBuf> {
        unimplemented!()
    }

}

impl<'a> Deref for Ref<'a> {
    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.0
    }

}

impl<'a> DerefMut for Ref<'a> {

    fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
        &mut self.0
    }

}
<commit_msg>Impl Ref::is_ref_to_file()<commit_after>//! The Ref object is a helper over the link functionality, so one is able to create references to
//! files outside of the imag store.

use std::path::PathBuf;
use std::ops::Deref;
use std::ops::DerefMut;

use libimagstore::store::FileLockEntry;
use libimagstore::storeid::StoreId;
use libimagstore::store::Store;
use libimagerror::into::IntoError;

use toml::Value;

use error::RefErrorKind as REK;
use flags::RefFlags;
use result::Result;

pub struct Ref<'a>(FileLockEntry<'a>);

impl<'a> Ref<'a> {

    /// Try to get `si` as Ref object from the store
    pub fn get(store: &'a Store, si: StoreId) -> Result<Ref<'a>> {
        match store.get(si) {
            Err(e) => return Err(REK::StoreReadError.into_error_with_cause(Box::new(e))),
            Ok(None) => return Err(REK::RefNotInStore.into_error()),
            Ok(Some(fle)) => Ref::read_reference(&fle).map(|_| Ref(fle)),
        }
    }

    fn read_reference(fle: &FileLockEntry<'a>) -> Result<PathBuf> {
        match fle.get_header().read("ref.reference") {
            Ok(Some(Value::String(s))) => Ok(PathBuf::from(s)),
            Ok(Some(_)) => Err(REK::HeaderTypeError.into_error()),
            Ok(None)    => Err(REK::HeaderFieldMissingError.into_error()),
            Err(e)      => Err(REK::StoreReadError.into_error_with_cause(Box::new(e))),
        }
    }

    /// Create a Ref object which refers to `pb`
    pub fn create(store: &Store, pb: PathBuf, flags: RefFlags) -> Result<Ref<'a>> {
        unimplemented!()
    }

    /// Creates a Hash from a PathBuf by making the PathBuf absolute and then running a hash
    /// algorithm on it
    fn hash_path(pb: &PathBuf) -> String {
        unimplemented!()
    }

    /// check whether the pointer the Ref represents still points to a file which exists
    pub fn fs_link_exists(&self) -> bool {
        unimplemented!()
    }

    /// Alias for `r.fs_link_exists() && r.deref().is_file()`
    pub fn is_ref_to_file(&self) -> bool {
        unimplemented!()
    }

    /// Alias for `!Ref::fs_link_exists()`
    pub fn is_dangling(&self) -> bool {
        !self.fs_link_exists()
    }

    /// check whether the pointer the Ref represents is valid
    /// This includes:
    ///     - Hashsum of the file is still the same as stored in the Ref
    ///     - file permissions are still valid
    pub fn fs_link_valid(&self) -> bool {
        unimplemented!()
    }

    /// Check whether the file permissions of the referenced file are equal to the stored
    /// permissions
    pub fn fs_link_valid_permissions(&self) -> bool {
        unimplemented!()
    }

    /// Check whether the Hashsum of the referenced file is equal to the stored hashsum
    pub fn fs_link_valid_hash(&self) -> bool {
        unimplemented!()
    }

    /// Update the Ref by re-checking the file from FS
    /// This errors if the file is not present or cannot be read()
    pub fn update_ref(&mut self) -> Result<()> {
        unimplemented!()
    }

    /// Get the path of the file which is reffered to by this Ref
    pub fn fs_file(&self) -> &PathBuf {
        unimplemented!()
    }

    /// Check whether there is a reference to the file at `pb`
    pub fn exists(store: &Store, pb: PathBuf) -> Result<bool> {
        unimplemented!()
    }

    /// Re-find a referenced file
    ///
    /// This function tries to re-find a ref by searching all directories in `search_roots` recursively
    /// for a file which matches the hash of the Ref `ref`.
    ///
    /// If `search_roots` is `None`, it starts at the filesystem root `/`.
    ///
    /// # Warning
    ///
    /// This option causes heavy I/O as it recursively searches the Filesystem.
    pub fn refind(&self, search_roots: Option<Vec<PathBuf>>) -> Option<PathBuf> {
        unimplemented!()
    }

}

impl<'a> Deref for Ref<'a> {
    type Target = FileLockEntry<'a>;

    fn deref(&self) -> &FileLockEntry<'a> {
        &self.0
    }

}

impl<'a> DerefMut for Ref<'a> {

    fn deref_mut(&mut self) -> &mut FileLockEntry<'a> {
        &mut self.0
    }

}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Arithmetic/Rational
use std::num;
use std::fmt;

#[cfg(not(test))]
fn main() {
    for p in perfect_numbers(1 << 19).iter() {
        println!("{} is perfect", p);
    }
}

fn perfect_numbers(max: i64) -> Vec<i64> {
    let mut ret=Vec::new();
    for candidate in range(2, max) {
        let mut sum=Frac::secure_new(1, candidate).unwrap();
        let max2=((candidate as f64).sqrt().floor()) as i64;

        for factor in std::iter::range_inclusive(2, max2) {
            if candidate % factor == 0 {
                sum = sum + Frac::new(1, factor) + Frac::new(factor, candidate);
            }
        }
        if sum == Frac::new(1,1) {ret.push(candidate);}
    }
    ret
}

struct Frac {
    num: i64,
    den: i64
}

fn gcd(m: i64, n:i64) -> i64 {
    let mut t: i64;
    let (mut m, mut n)=(num::abs(m), num::abs(n));
    while n>0 { t = n; n = m % n; m = t; }
    m
}

fn lcm(m: i64, n:i64) -> i64 {
    num::abs(m) / gcd(m, n) * num::abs(n)
}

impl Frac {
    // fails on den=0
    fn new(num: i64, den:i64) -> Frac {
        let (n, d) = match (num, den) {
            (0, _)          => (0, 0),
            (n, d) if d<0   => (-n, -d),
            a @ _           => a
        };

        Frac {num: n, den: d}
    }

    // does not fail (returns Err on den=0)
    fn secure_new(num: i64, den:i64) -> Result<Frac, String> {
        if den==0 {
            Err("Error: Division by zero".to_string())
        } else {
            Ok(Frac::new(num, den))
        }
    }

    // fails on den=0, returns frac already in its reduced form
    fn new_reduced(num: i64, den:i64) -> Frac {
        Frac::new(num, den).reduce()
    }

    // reduces the fraction to lowest terms
    fn reduce(mut self) -> Frac {
        match self {
            z @ Frac{num:0, den:0} => z,
            _         => {
                let gcd=gcd(self.num, self.den);
                self.num /= gcd;
                self.den /= gcd;
                self
            }
        }
    }
}

impl fmt::Show for Frac {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match (self.num, self.den) {
            (_,1) | (0,0) => write!(f, "{}", self.num),
            (_,_) => write!(f, "{}/{}", self.num, self.den)
        }
    }
}

impl PartialEq for Frac {
    fn eq(&self, other: &Frac) -> bool {
        let (red_a, red_b) = (self.reduce(), other.reduce());
        red_a.num==red_b.num && red_a.den==red_b.den
    }
}

impl Eq for Frac {}

impl PartialOrd for Frac {
    fn lt(&self, other: &Frac) -> bool {
        (self.num * other.den) < (self.den * other.num)
    }
}

impl Ord for Frac {
    fn cmp(&self, other: &Frac) -> Ordering {
        (self.num * other.den).cmp(&(self.den * other.num))
    }
}

impl Neg<Frac> for Frac {
    fn neg(&self) -> Frac {
        Frac{num:-self.num, den:self.den}
    }
}

impl Add<Frac, Frac> for Frac {
    fn add(&self, other: &Frac) -> Frac {
        let (a, b)=(self.reduce(), other.reduce());
        let m = lcm(a.den, b.den);

        let na = a.num * m / a.den;
        let nb = b.num * m / b.den;
        Frac::new_reduced(na + nb, m)
    }
}

impl Sub<Frac, Frac> for Frac {
    fn sub(&self, other: &Frac) -> Frac {
        self + (-other)
    }
}

impl Mul<Frac, Frac> for Frac {
    fn mul(&self, other: &Frac) -> Frac {
        Frac::new_reduced(self.num * other.num, self.den * other.den)
    }
}

impl Div<Frac, Frac> for Frac {
    fn div(&self, other: &Frac) -> Frac {
        Frac::new_reduced(self.num * other.den, self.den * other.num)
    }
}

impl num::Zero for Frac {
    fn zero() -> Frac {
        Frac::new(0, 1)
    }

    fn is_zero(&self) -> bool {
        self.num == 0 && self.den == 0
    }
}

impl num::One for Frac {
    fn one() -> Frac {
        Frac::new(1, 1)
    }
}

#[test]
fn operators() {
    let (a, b) =  (Frac::new(1, 2), Frac::new(12,15));
    assert_eq!(a+b, Frac::secure_new(13, 10).unwrap());
    assert_eq!(b-a, Frac::new(3, 10));
    assert_eq!(a-b, Frac::new(-3, 10));
    assert_eq!(a*b, Frac::new(2, 5));
    assert_eq!(a/b, Frac::new(5, 8));

    let (a, b) =  (Frac::new(1, 2), Frac::new(1,2));
    assert_eq!(a+b, num::One::one());
    assert_eq!(b-a, num::Zero::zero());
    assert_eq!(a-b, num::Zero::zero());
    assert_eq!(a*b, Frac::new(1, 4));
    assert_eq!(a/b, Frac::new(1, 1));
}

#[test]
fn first_perfect_numbers() {
    assert_eq!(perfect_numbers(8150), vec![6,28,496,8128]);
}<commit_msg>Fix arithmetic_rational<commit_after>// http://rosettacode.org/wiki/Arithmetic/Rational
use std::num;
use std::fmt;

#[cfg(not(test))]
fn main() {
    for p in perfect_numbers(1 << 19).iter() {
        println!("{} is perfect", p);
    }
}

fn perfect_numbers(max: i64) -> Vec<i64> {
    let mut ret=Vec::new();
    for candidate in range(2, max) {
        let mut sum=Frac::secure_new(1, candidate).unwrap();
        let max2=((candidate as f64).sqrt().floor()) as i64;

        for factor in std::iter::range_inclusive(2, max2) {
            if candidate % factor == 0 {
                sum = sum + Frac::new(1, factor) + Frac::new(factor, candidate);
            }
        }
        if sum == Frac::new(1,1) {ret.push(candidate);}
    }
    ret
}

struct Frac {
    num: i64,
    den: i64
}

fn gcd(m: i64, n:i64) -> i64 {
    let mut t: i64;
    let (mut m, mut n)=(num::abs(m), num::abs(n));
    while n>0 { t = n; n = m % n; m = t; }
    m
}

fn lcm(m: i64, n:i64) -> i64 {
    num::abs(m) / gcd(m, n) * num::abs(n)
}

impl Frac {
    // fails on den=0
    fn new(num: i64, den:i64) -> Frac {
        let (n, d) = match (num, den) {
            (0, _)          => (0, 0),
            (n, d) if d<0   => (-n, -d),
            a @ _           => a
        };

        Frac {num: n, den: d}
    }

    // does not fail (returns Err on den=0)
    fn secure_new(num: i64, den:i64) -> Result<Frac, String> {
        if den==0 {
            Err("Error: Division by zero".to_string())
        } else {
            Ok(Frac::new(num, den))
        }
    }

    // fails on den=0, returns frac already in its reduced form
    fn new_reduced(num: i64, den:i64) -> Frac {
        Frac::new(num, den).reduce()
    }

    // reduces the fraction to lowest terms
    fn reduce(mut self) -> Frac {
        match self {
            z @ Frac{num:0, den:0} => z,
            _         => {
                let gcd=gcd(self.num, self.den);
                self.num /= gcd;
                self.den /= gcd;
                self
            }
        }
    }
}

impl fmt::Show for Frac {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match (self.num, self.den) {
            (_,1) | (0,0) => write!(f, "{}", self.num),
            (_,_) => write!(f, "{}/{}", self.num, self.den)
        }
    }
}

impl PartialEq for Frac {
    fn eq(&self, other: &Frac) -> bool {
        let (red_a, red_b) = (self.reduce(), other.reduce());
        red_a.num==red_b.num && red_a.den==red_b.den
    }
}

impl Eq for Frac {}

impl PartialOrd for Frac {
    fn partial_cmp(&self, other: &Frac) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Frac {
    fn cmp(&self, other: &Frac) -> Ordering {
        (self.num * other.den).cmp(&(self.den * other.num))
    }
}

impl Neg<Frac> for Frac {
    fn neg(&self) -> Frac {
        Frac{num:-self.num, den:self.den}
    }
}

impl Add<Frac, Frac> for Frac {
    fn add(&self, other: &Frac) -> Frac {
        let (a, b)=(self.reduce(), other.reduce());
        let m = lcm(a.den, b.den);

        let na = a.num * m / a.den;
        let nb = b.num * m / b.den;
        Frac::new_reduced(na + nb, m)
    }
}

impl Sub<Frac, Frac> for Frac {
    fn sub(&self, other: &Frac) -> Frac {
        self + (-other)
    }
}

impl Mul<Frac, Frac> for Frac {
    fn mul(&self, other: &Frac) -> Frac {
        Frac::new_reduced(self.num * other.num, self.den * other.den)
    }
}

impl Div<Frac, Frac> for Frac {
    fn div(&self, other: &Frac) -> Frac {
        Frac::new_reduced(self.num * other.den, self.den * other.num)
    }
}

impl num::Zero for Frac {
    fn zero() -> Frac {
        Frac::new(0, 1)
    }

    fn is_zero(&self) -> bool {
        self.num == 0 && self.den == 0
    }
}

impl num::One for Frac {
    fn one() -> Frac {
        Frac::new(1, 1)
    }
}

#[test]
fn operators() {
    let (a, b) =  (Frac::new(1, 2), Frac::new(12,15));
    assert_eq!(a+b, Frac::secure_new(13, 10).unwrap());
    assert_eq!(b-a, Frac::new(3, 10));
    assert_eq!(a-b, Frac::new(-3, 10));
    assert_eq!(a*b, Frac::new(2, 5));
    assert_eq!(a/b, Frac::new(5, 8));

    let (a, b) =  (Frac::new(1, 2), Frac::new(1,2));
    assert_eq!(a+b, num::One::one());
    assert_eq!(b-a, num::Zero::zero());
    assert_eq!(a-b, num::Zero::zero());
    assert_eq!(a*b, Frac::new(1, 4));
    assert_eq!(a/b, Frac::new(1, 1));
}

#[test]
fn first_perfect_numbers() {
    assert_eq!(perfect_numbers(8150), vec![6,28,496,8128]);
}<|endoftext|>


<commit_before>#![no_std]
#![no_main]
#![feature(globs)]
#![feature(lang_items)]
#![feature(asm)]

#![allow(uppercase_variables)]
#![allow(non_camel_case_types)]

extern crate core;

use core::prelude::*;

use core::mem;
use core::intrinsics::{volatile_load, volatile_store};
use core::ty::Unsafe;

#[lang = "begin_unwind"]
extern fn begin_unwind(args: &core::fmt::Arguments,
                       file: &str,
                       line: uint) -> ! {
    loop {}
}

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[no_mangle]
pub unsafe extern "C" fn _kill() { loop{} }

#[no_mangle]
pub unsafe extern "C" fn _getpid() { loop{} }

static SCS_BASE: uint = 0xE000E000; // System Control Space Base Address
static SysTick_BASE: uint = SCS_BASE +  0x0010; // SysTick Base Address
static NVIC_BASE: uint = SCS_BASE +  0x0100;    //NVIC Base Address
static SCB_BASE: uint = SCS_BASE +  0x0D00;

#[repr(C)]
struct SysTick {
  CTRL: Reg<u32>, // Offset: 0x000 (R/W)  SysTick Control and Status Register
  LOAD: Reg<u32>, // Offset: 0x004 (R/W)  SysTick Reload Value Register
  VAL: Reg<u32>,  // Offset: 0x008 (R/W)  SysTick Current Value Register
  CALIB: Reg<u32>,
}

static SysTick_CTRL_COUNTFLAG_Pos: uint = 16;                                    // SysTick CTRL: COUNTFLAG Position
static SysTick_CTRL_COUNTFLAG_Msk: u32 = (1 << SysTick_CTRL_COUNTFLAG_Pos);   // SysTick CTRL: COUNTFLAG Mask

static SysTick_CTRL_CLKSOURCE_Pos: uint =  2;                                    // SysTick CTRL: CLKSOURCE Position
static SysTick_CTRL_CLKSOURCE_Msk: u32 = (1 << SysTick_CTRL_CLKSOURCE_Pos);   // SysTick CTRL: CLKSOURCE Mask

static SysTick_CTRL_TICKINT_Pos: uint =    1;                                    // SysTick CTRL: TICKINT Position
static SysTick_CTRL_TICKINT_Msk: u32 =   (1 << SysTick_CTRL_TICKINT_Pos);    //  SysTick CTRL: TICKINT Mask

static SysTick_CTRL_ENABLE_Pos: uint =     0;                                  // SysTick CTRL: ENABLE Position
static SysTick_CTRL_ENABLE_Msk: u32 =    (1 << SysTick_CTRL_ENABLE_Pos);    // SysTick CTRL: ENABLE Mask

#[repr(C)]
struct Reg<T> {
  value: Unsafe<T>,
}

impl<T:Copy> Reg<T> {
  #[inline]
  fn get(&self) -> T {
    unsafe {
      volatile_load(self.value.get() as *const T)
    }
  }

  #[inline]
  fn set(&self, value: T) {
    unsafe {
      volatile_store(self.value.get(), value)
    }
  }
}

impl Reg<u32> {
  fn write_bit(&self, b: u8) {
    self.set(1 << (b as uint));
  }

  fn set_bit(&self, b: u8) {
    let old = self.get();
    self.set(old | (1 << (b as uint)));
  }

  fn clear_bit(&self, b: u8) {
    let old = self.get();
    self.set(old & !(1 << (b as uint)));
  }
}

impl SysTick {
  fn get() -> &'static SysTick {
    unsafe { &*(SysTick_BASE as *const SysTick) }
  }

  fn init(&self, ticks: u32) {
    self.LOAD.set(ticks - 1);
    self.VAL.set(0);
    self.CTRL.set(SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
  }
}

static SCU_BASE: u32 = 0x40086000;

#[repr(C)]
struct SCU {
  SFSP: [[Reg<u32>, ..32], ..16],
  RSVD1: [u32, ..256],
  SFSCLK: [Reg<u32>, ..4],
  RSVD2: [u32, ..28],
  SFSUSB: Reg<u32>,
  SFSI2C0: Reg<u32>,
  SFSENAIO: [Reg<u32>, ..3],
  RSVD3: [u32, ..27],
  EMCDELAYCLK: Reg<u32>,
  RSVD4: [u32, ..63],
  PINTSEL: [Reg<u32>, ..2],
}

static PDN_ENABLE: u32 =        (1 << 3);	// Pull-down enable
static PDN_DISABLE: u32 =       (0 << 3);      // Pull-down disable
static PUP_ENABLE: u32 =        (0 << 4);      // Pull-up enable
static PUP_DISABLE: u32 =       (1 << 4);	// Pull-up disable
static SLEWRATE_SLOW: u32 =	  (0 << 5);	// Slew rate for low noise with medium speed
static SLEWRATE_FAST: u32 =	  (1 << 5);	// Slew rate for medium noise with fast speed
static INBUF_ENABLE: u32 =	  (1 << 6);	// Input buffer
static INBUF_DISABLE: u32 =	  (0 << 6);	// Input buffer
static FILTER_ENABLE: u32 =	  (0 << 7);	// Glitch filter (for signals below 30MHz)
static FILTER_DISABLE: u32 =	  (1 << 7);	// No glitch filter (for signals above 30MHz)
static DRIVE_8MA: u32 =         (1 << 8);	// Drive strength of 8mA
static DRIVE_14MA: u32 =        (1 << 9);	// Drive strength of 14mA
static DRIVE_20MA: u32 =        (3 << 8);	// Drive strength of 20mA

impl SCU {
  fn get() -> &'static SCU {
    unsafe { &*(SCU_BASE as *const SCU) }
  }

  fn pinmux(&self, (port, pin): (u8, u8), mode: u32, func: u32) {
    self.SFSP[port as uint][pin as uint].set(mode | func);
  }
}

static LED1: (u8, u8) = (11, 2);
static LED2: (u8, u8) = (7, 3);

static GPIO_PORT_BASE: u32 = 0x400F4000;

#[repr(C)]
struct GPIO {
  B: [Reg<u8>, ..256],
  RESERVED0: [u32, ..960],
  W: [Reg<u32>, ..256],
  RESERVED1: [u32, ..768],
  DIR: [Reg<u32>, ..8],
  RESERVED2: [u32, ..24],
  MASK: [Reg<u32>, ..8],
  RESERVED3: [u32, ..24],
  PIN: [Reg<u32>, ..8],
  RESERVED4: [u32, ..24],
  MPIN: [Reg<u32>, ..8],
  RESERVED5: [u32, ..24],
  SET: [Reg<u32>, ..8],
  RESERVED6: [u32, ..24],
  CLR: [Reg<u32>, ..8],
  RESERVED7: [u32, ..24],
  NOT: [Reg<u32>, ..8],
  RESERVED8: [u32, ..24],
}

impl GPIO {
  fn get() -> &'static GPIO {
    unsafe { &*(GPIO_PORT_BASE as *const GPIO) }
  }

  fn dir(&self, (port, pin): (u8, u8), output: bool) {
    if output {
      self.DIR[port as uint].set_bit(pin);
    } else {
      self.DIR[port as uint].clear_bit(pin);
    }
  }

  fn write(&self, (port, pin): (u8, u8), value: bool) {
    if value {
      self.SET[port as uint].write_bit(pin);
    } else {
      self.CLR[port as uint].write_bit(pin);
    }
  }

  fn toggle(&self, (port, pin): (u8, u8)) {
    self.NOT[port as uint].write_bit(pin);
  }
}

static LED1_GPIO: (u8, u8) = (5, 22);
static LED2_GPIO: (u8, u8) = (3, 11);

#[no_mangle]
#[no_split_stack]
pub unsafe extern "C" fn _reset_handler() {
  let systick = SysTick::get();
  let scu = SCU::get();
  systick.init(180_000_000 / 1000);

  scu.pinmux(LED1, PUP_DISABLE, 4);
  scu.pinmux(LED2, PUP_DISABLE, 0);

  let gpio = GPIO::get();
  gpio.write(LED1_GPIO, true);
  gpio.dir(LED1_GPIO, true);
  gpio.write(LED2_GPIO, false);
  gpio.dir(LED2_GPIO, true);

  asm!("CPSIE i");
  loop{}
}

static mut count: u32 = 0;

#[no_mangle]
pub unsafe extern "C" fn SysTick_Handler() {
  let gpio = GPIO::get();
  count += 1;
  if count % 100 == 0 {
    gpio.toggle(LED1_GPIO);
    gpio.toggle(LED2_GPIO);
  }
}
<commit_msg>rust: renamed lints and lang items<commit_after>#![no_std]
#![no_main]
#![feature(globs)]
#![feature(lang_items)]
#![feature(asm)]

#![allow(dead_code)]
#![allow(non_snake_case)]

extern crate core;

use core::prelude::*;

use core::mem;
use core::intrinsics::{volatile_load, volatile_store};
use core::ty::Unsafe;

#[lang = "fail_fmt"]
extern fn fail_fmt(args: &core::fmt::Arguments,
                       file: &str,
                       line: uint) -> ! {
    loop {}
}

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[no_mangle]
pub unsafe extern "C" fn _kill() { loop{} }

#[no_mangle]
pub unsafe extern "C" fn _getpid() { loop{} }

static SCS_BASE: uint = 0xE000E000; // System Control Space Base Address
static SysTick_BASE: uint = SCS_BASE +  0x0010; // SysTick Base Address
static NVIC_BASE: uint = SCS_BASE +  0x0100;    //NVIC Base Address
static SCB_BASE: uint = SCS_BASE +  0x0D00;

#[repr(C)]
struct SysTick {
  CTRL: Reg<u32>, // Offset: 0x000 (R/W)  SysTick Control and Status Register
  LOAD: Reg<u32>, // Offset: 0x004 (R/W)  SysTick Reload Value Register
  VAL: Reg<u32>,  // Offset: 0x008 (R/W)  SysTick Current Value Register
  CALIB: Reg<u32>,
}

static SysTick_CTRL_COUNTFLAG_Pos: uint = 16;                                    // SysTick CTRL: COUNTFLAG Position
static SysTick_CTRL_COUNTFLAG_Msk: u32 = (1 << SysTick_CTRL_COUNTFLAG_Pos);   // SysTick CTRL: COUNTFLAG Mask

static SysTick_CTRL_CLKSOURCE_Pos: uint =  2;                                    // SysTick CTRL: CLKSOURCE Position
static SysTick_CTRL_CLKSOURCE_Msk: u32 = (1 << SysTick_CTRL_CLKSOURCE_Pos);   // SysTick CTRL: CLKSOURCE Mask

static SysTick_CTRL_TICKINT_Pos: uint =    1;                                    // SysTick CTRL: TICKINT Position
static SysTick_CTRL_TICKINT_Msk: u32 =   (1 << SysTick_CTRL_TICKINT_Pos);    //  SysTick CTRL: TICKINT Mask

static SysTick_CTRL_ENABLE_Pos: uint =     0;                                  // SysTick CTRL: ENABLE Position
static SysTick_CTRL_ENABLE_Msk: u32 =    (1 << SysTick_CTRL_ENABLE_Pos);    // SysTick CTRL: ENABLE Mask

#[repr(C)]
struct Reg<T> {
  value: Unsafe<T>,
}

impl<T:Copy> Reg<T> {
  #[inline]
  fn get(&self) -> T {
    unsafe {
      volatile_load(self.value.get() as *const T)
    }
  }

  #[inline]
  fn set(&self, value: T) {
    unsafe {
      volatile_store(self.value.get(), value)
    }
  }
}

impl Reg<u32> {
  fn write_bit(&self, b: u8) {
    self.set(1 << (b as uint));
  }

  fn set_bit(&self, b: u8) {
    let old = self.get();
    self.set(old | (1 << (b as uint)));
  }

  fn clear_bit(&self, b: u8) {
    let old = self.get();
    self.set(old & !(1 << (b as uint)));
  }
}

impl SysTick {
  fn get() -> &'static SysTick {
    unsafe { &*(SysTick_BASE as *const SysTick) }
  }

  fn init(&self, ticks: u32) {
    self.LOAD.set(ticks - 1);
    self.VAL.set(0);
    self.CTRL.set(SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
  }
}

static SCU_BASE: u32 = 0x40086000;

#[repr(C)]
struct SCU {
  SFSP: [[Reg<u32>, ..32], ..16],
  RSVD1: [u32, ..256],
  SFSCLK: [Reg<u32>, ..4],
  RSVD2: [u32, ..28],
  SFSUSB: Reg<u32>,
  SFSI2C0: Reg<u32>,
  SFSENAIO: [Reg<u32>, ..3],
  RSVD3: [u32, ..27],
  EMCDELAYCLK: Reg<u32>,
  RSVD4: [u32, ..63],
  PINTSEL: [Reg<u32>, ..2],
}

static PDN_ENABLE: u32 =        (1 << 3);	// Pull-down enable
static PDN_DISABLE: u32 =       (0 << 3);      // Pull-down disable
static PUP_ENABLE: u32 =        (0 << 4);      // Pull-up enable
static PUP_DISABLE: u32 =       (1 << 4);	// Pull-up disable
static SLEWRATE_SLOW: u32 =	  (0 << 5);	// Slew rate for low noise with medium speed
static SLEWRATE_FAST: u32 =	  (1 << 5);	// Slew rate for medium noise with fast speed
static INBUF_ENABLE: u32 =	  (1 << 6);	// Input buffer
static INBUF_DISABLE: u32 =	  (0 << 6);	// Input buffer
static FILTER_ENABLE: u32 =	  (0 << 7);	// Glitch filter (for signals below 30MHz)
static FILTER_DISABLE: u32 =	  (1 << 7);	// No glitch filter (for signals above 30MHz)
static DRIVE_8MA: u32 =         (1 << 8);	// Drive strength of 8mA
static DRIVE_14MA: u32 =        (1 << 9);	// Drive strength of 14mA
static DRIVE_20MA: u32 =        (3 << 8);	// Drive strength of 20mA

impl SCU {
  fn get() -> &'static SCU {
    unsafe { &*(SCU_BASE as *const SCU) }
  }

  fn pinmux(&self, (port, pin): (u8, u8), mode: u32, func: u32) {
    self.SFSP[port as uint][pin as uint].set(mode | func);
  }
}

static LED1: (u8, u8) = (11, 2);
static LED2: (u8, u8) = (7, 3);

static GPIO_PORT_BASE: u32 = 0x400F4000;

#[repr(C)]
struct GPIO {
  B: [Reg<u8>, ..256],
  RESERVED0: [u32, ..960],
  W: [Reg<u32>, ..256],
  RESERVED1: [u32, ..768],
  DIR: [Reg<u32>, ..8],
  RESERVED2: [u32, ..24],
  MASK: [Reg<u32>, ..8],
  RESERVED3: [u32, ..24],
  PIN: [Reg<u32>, ..8],
  RESERVED4: [u32, ..24],
  MPIN: [Reg<u32>, ..8],
  RESERVED5: [u32, ..24],
  SET: [Reg<u32>, ..8],
  RESERVED6: [u32, ..24],
  CLR: [Reg<u32>, ..8],
  RESERVED7: [u32, ..24],
  NOT: [Reg<u32>, ..8],
  RESERVED8: [u32, ..24],
}

impl GPIO {
  fn get() -> &'static GPIO {
    unsafe { &*(GPIO_PORT_BASE as *const GPIO) }
  }

  fn dir(&self, (port, pin): (u8, u8), output: bool) {
    if output {
      self.DIR[port as uint].set_bit(pin);
    } else {
      self.DIR[port as uint].clear_bit(pin);
    }
  }

  fn write(&self, (port, pin): (u8, u8), value: bool) {
    if value {
      self.SET[port as uint].write_bit(pin);
    } else {
      self.CLR[port as uint].write_bit(pin);
    }
  }

  fn toggle(&self, (port, pin): (u8, u8)) {
    self.NOT[port as uint].write_bit(pin);
  }
}

static LED1_GPIO: (u8, u8) = (5, 22);
static LED2_GPIO: (u8, u8) = (3, 11);

#[no_mangle]
#[no_split_stack]
pub unsafe extern "C" fn _reset_handler() {
  let systick = SysTick::get();
  let scu = SCU::get();
  systick.init(180_000_000 / 1000);

  scu.pinmux(LED1, PUP_DISABLE, 4);
  scu.pinmux(LED2, PUP_DISABLE, 0);

  let gpio = GPIO::get();
  gpio.write(LED1_GPIO, true);
  gpio.dir(LED1_GPIO, true);
  gpio.write(LED2_GPIO, false);
  gpio.dir(LED2_GPIO, true);

  asm!("CPSIE i");
  loop{}
}

static mut count: u32 = 0;

#[no_mangle]
pub unsafe extern "C" fn SysTick_Handler() {
  let gpio = GPIO::get();
  count += 1;
  if count % 100 == 0 {
    gpio.toggle(LED1_GPIO);
    gpio.toggle(LED2_GPIO);
  }
}
<|endoftext|>


<commit_before>extern mod std;

use std::run;
use std::str;
use std::option::*;
use std::trie::*;
use std::libc::{execvp, perror};
use std::c_str::*;
use std::vec;
use std::ptr;

fn session_is_attached(line: &str) -> bool {
    line.ends_with("(attached)")
}

fn session_number(line: &str) -> Option<uint> {
    line.split_iter(':').next().and_then(|s| from_str(s))
}

fn detached_sessions(output: ~str) -> TrieSet {
    let mut set = TrieSet::new();
    for line in output.line_iter(){
        if !session_is_attached(line) {
            match session_number(line) {
                Some(n) => { set.insert(n); }
                None => ()
            }
        }
    }
    set
}

#[fixed_stack_segment]
fn exec_program(program: &str, args: &[~str]) {
    do program.with_c_str() |c_program| {
        // I don't much care about the ownership of the strings here
        // at this point, so let's just fail if execvp isn't working.
        unsafe {
            let mut c_args = args.map(|arg| { arg.to_c_str().unwrap() });
            c_args.push(ptr::null());
            execvp(c_program, vec::raw::to_ptr(c_args));
            perror("Running tmux failed:".to_c_str().unwrap());
        }
        fail!(fmt!("Couldn't exec %s", program));
    }
}

fn main() {
    let proc = run::process_output("tmux", &[~"list-sessions"]);
    if proc.status != 0 {
        fail!(fmt!("Tmux exited with an error status: %d", proc.status));
    }
    let output = str::from_utf8(proc.output);
    let sessions = detached_sessions(output);
    match sessions.iter().next() {
        Some(n) => {
            let session = n.to_str();
            exec_program("tmux", &[~"tmux", ~"attach-session", ~"-t", session]);
        }
        _ => { exec_program("tmux", &[~"tmux"]); }
    }
}

#[test]
fn test_session_is_attached() {
    assert!(session_is_attached("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)"));
    assert!(!session_is_attached("20: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]"));
}

#[test]
fn test_session_number_with_numbers(){
    match(session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)")) {
        Some(11) => (),
        Some(n) => fail!(fmt!("Should have returned 11, got %u!", n)),
        None => fail!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match(session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)")) {
        Some(n) => fail!(fmt!("Should have returned None, got %u!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions(~"3: foo (attached)\n2: bar\n4: abz (attached)\nfoo: baz");
    assert!(set.contains(&2));

    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // missing session:
    assert!(!set.contains(&1));
}
<commit_msg>Rewrite detached_sessions to use filter_map<commit_after>extern mod std;

use std::run;
use std::str;
use std::option::*;
use std::trie::*;
use std::libc::{execvp, perror};
use std::c_str::*;
use std::vec;
use std::ptr;

fn session_is_attached(line: &str) -> bool {
    line.ends_with("(attached)")
}

fn session_number(line: &str) -> Option<uint> {
    line.split_iter(':').next().and_then(|s| from_str(s))
}

fn detached_sessions(output: ~str) -> TrieSet {
    output.line_iter().filter_map(|line| {
        if !session_is_attached(line) {
            session_number(line)
        } else {
            None
        }
    }).collect()
}

#[fixed_stack_segment]
fn exec_program(program: &str, args: &[~str]) {
    do program.with_c_str() |c_program| {
        // I don't much care about the ownership of the strings here
        // at this point, so let's just fail if execvp isn't working.
        unsafe {
            let mut c_args = args.map(|arg| { arg.to_c_str().unwrap() });
            c_args.push(ptr::null());
            execvp(c_program, vec::raw::to_ptr(c_args));
            perror("Running tmux failed:".to_c_str().unwrap());
        }
        fail!(fmt!("Couldn't exec %s", program));
    }
}

fn main() {
    let proc = run::process_output("tmux", &[~"list-sessions"]);
    if proc.status != 0 {
        fail!(fmt!("Tmux exited with an error status: %d", proc.status));
    }
    let output = str::from_utf8(proc.output);
    let sessions = detached_sessions(output);
    match sessions.iter().next() {
        Some(n) => {
            let session = n.to_str();
            exec_program("tmux", &[~"tmux", ~"attach-session", ~"-t", session]);
        }
        _ => { exec_program("tmux", &[~"tmux"]); }
    }
}

#[test]
fn test_session_is_attached() {
    assert!(session_is_attached("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)"));
    assert!(!session_is_attached("20: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]"));
}

#[test]
fn test_session_number_with_numbers(){
    match(session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)")) {
        Some(11) => (),
        Some(n) => fail!(fmt!("Should have returned 11, got %u!", n)),
        None => fail!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match(session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)")) {
        Some(n) => fail!(fmt!("Should have returned None, got %u!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions(~"3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use std;
use gl;
use gl::types::{
    GLint,
    GLuint,
    GLchar,
    GLenum,
    GLsizeiptr,
    GLsizei,
};
use cgmath::matrix::{
    Matrix,
    Mat4,
    Mat3,
    ToMat4,
};
use cgmath::vector::{
    Vec3,
};
use cgmath::angle;
use stb_image::image;
use misc::{
    deg_to_rad,
    read_file,
};
use gl_types::{
    Float,
    MatId,
};
use core_types::{
    Size2,
    Int,
};

pub use load_gl_funcs_with = gl::load_with;

fn c_str(s: &str) -> *GLchar {
    unsafe {
        s.to_c_str().unwrap()
    }
}

fn compile_shader(src: &str, shader_type: GLenum) -> GLuint {
    let shader = gl::CreateShader(shader_type);
    unsafe {
        gl::ShaderSource(shader, 1, &c_str(src), std::ptr::null());
        gl::CompileShader(shader);
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            // subtract 1 to skip the trailing null character
            let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
            gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
                buf.as_mut_ptr() as *mut GLchar
            );
            fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
        }
    }
    shader
}

fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vertex_shader);
    gl::AttachShader(program, fragment_shader);
    gl::LinkProgram(program);
    unsafe {
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            // subtract 1 to skip the trailing null character
            let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
            gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
                buf.as_mut_ptr() as *mut GLchar
            );
            fail!("link_program(): " + std::str::raw::from_utf8(buf));
        }
    }
    program
}

fn compile_program(vertex_shader_src: &str, frag_shader_src: &str) -> Shader {
    let vertex_shader = compile_shader(
        vertex_shader_src, gl::VERTEX_SHADER);
    let fragment_shader = compile_shader(
        frag_shader_src, gl::FRAGMENT_SHADER);
    let program = link_program(vertex_shader, fragment_shader);
    // mark shaders for deletion after program deletion
    gl::DeleteShader(fragment_shader);
    gl::DeleteShader(vertex_shader);
    Shader(program)
}

pub fn draw_mesh(faces_count: Int) {
    let starting_index = 0;
    let vertices_count = faces_count * 3;
    gl::DrawArrays(gl::TRIANGLES, starting_index, vertices_count);
}

pub fn uniform_mat4f(mat_id: MatId, mat: &Mat4<Float>) {
    unsafe {
        let MatId(id) = mat_id;
        gl::UniformMatrix4fv(id as Int, 1, gl::FALSE, mat.cr(0, 0));
    }
}

pub fn tr(m: Mat4<Float>, v: Vec3<Float>) -> Mat4<Float> {
    let mut t = Mat4::<Float>::identity();
    *t.mut_cr(3, 0) = v.x;
    *t.mut_cr(3, 1) = v.y;
    *t.mut_cr(3, 2) = v.z;
    m.mul_m(&t)
}

pub fn rot_x(m: Mat4<Float>, angle: Float) -> Mat4<Float> {
    let rad = angle::rad(deg_to_rad(angle));
    let r = Mat3::from_angle_x(rad).to_mat4();
    m.mul_m(&r)
}

pub fn rot_z(m: Mat4<Float>, angle: Float) -> Mat4<Float> {
    let rad = angle::rad(deg_to_rad(angle));
    let r = Mat3::from_angle_z(rad).to_mat4();
    m.mul_m(&r)
}

pub fn init_opengl() {
    gl::Enable(gl::DEPTH_TEST);
}

pub fn set_clear_color(r: Float, g: Float, b: Float) {
    gl::ClearColor(r, g, b, 1.0);
}

pub fn clear() {
    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
}

pub fn viewport(size: Size2<Int>) {
    gl::Viewport(0, 0, size.w, size.h);
}

pub struct Texture(GLuint);

impl Texture {
    pub fn new(path: ~str) -> Texture {
        load_texture(path)
    }

    pub fn enable(&self, shader: &Shader) {
        let Texture(id) = *self;
        let basic_texture_loc = shader.get_uniform("basic_texture") as GLint;
        gl::Uniform1ui(basic_texture_loc, 0);
        gl::ActiveTexture(gl::TEXTURE0);
        gl::BindTexture(gl::TEXTURE_2D, id);
    }
}

pub struct Shader(GLuint);

impl Shader {
    pub fn new(vs: &str, fs: &str) -> Shader {
        compile_program(
            read_file(&Path::new(vs)),
            read_file(&Path::new(fs)),
        )
    }

    pub fn activate(&self) {
        let Shader(id) = *self;
        gl::UseProgram(id);
    }

    pub fn get_attr(&self, name: &str) -> Attr {
        unsafe {
            let Shader(id) = *self;
            let attr_id = gl::GetAttribLocation(id, c_str(name));
            Attr(attr_id as GLuint)
        }
    }

    pub fn get_uniform(&self, name: &str) -> GLuint {
        let Shader(id) = *self;
        unsafe {
            gl::GetUniformLocation(id, c_str(name)) as GLuint
        }
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        let Shader(id) = *self;
        gl::DeleteProgram(id);
    }
}

pub struct Vbo(GLuint);

fn get_new_vbo_id() -> GLuint {
    let mut id = 0;
    unsafe {
        gl::GenBuffers(1, &mut id);
    }
    id
}

impl Vbo {
    pub fn from_data<T>(data: &[T]) -> Vbo {
        let vbo = Vbo(get_new_vbo_id());
        vbo.bind();
        let size = std::mem::size_of::<T>();
        let buf_size = (data.len() * size) as GLsizeiptr;
        unsafe {
            let data_ptr = std::cast::transmute(&data[0]);
            gl::BufferData(gl::ARRAY_BUFFER, buf_size, data_ptr, gl::STATIC_DRAW);
        }
        vbo
    }

    pub fn bind(&self) {
        let Vbo(id) = *self;
        gl::BindBuffer(gl::ARRAY_BUFFER, id);
    }
}

impl Drop for Vbo {
    fn drop(&mut self) {
        unsafe {
            let Vbo(id) = *self;
            gl::DeleteBuffers(1, &id);
        }
    }
}

pub struct Attr(GLuint);

impl Attr {
    pub fn enable(&self) {
        let Attr(id) = *self;
        gl::EnableVertexAttribArray(id);
    }

    // TODO: Rename
    pub fn vertex_pointer(&self, components_count: Int) {
        let normalized = gl::FALSE;
        let stride = 0;
        let Attr(id) = *self;
        unsafe {
            gl::VertexAttribPointer(
                id,
                components_count,
                gl::FLOAT,
                normalized,
                stride,
                std::ptr::null(),
            );
        }
    }
}

fn load_image(path: ~str) -> image::Image<u8> {
    let load_result = image::load(path);
    match load_result {
        image::ImageU8(image) => {
            image
        },
        image::Error(message) => {
            fail!("{}", message);
        },
        _ => {
            fail!("Unknown image format");
        }
    }
}

fn load_texture(path: ~str) -> Texture {
    let image = load_image(path);
    let mut id = 0;
    unsafe {
        gl::GenTextures(1, &mut id)
    };
    gl::ActiveTexture(gl::TEXTURE0);
    gl::BindTexture(gl::TEXTURE_2D, id);
    let format = match image.depth {
        4 => gl::RGBA,
        3 => gl::RGB,
        _ => fail!("wrong depth"),
    };
    unsafe {
        let level = 0;
        let border = 0;
        gl::TexImage2D(
            gl::TEXTURE_2D,
            level,
            format as GLint,
            image.width as GLsizei,
            image.height as GLsizei,
            border,
            format,
            gl::UNSIGNED_BYTE,
            std::cast::transmute(&image.data[0]),
        );
    }
    gl::TexParameteri(gl::TEXTURE_2D,
        gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
    gl::TexParameteri(gl::TEXTURE_2D,
        gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
    gl::TexParameteri(gl::TEXTURE_2D,
        gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint);
    gl::TexParameteri(gl::TEXTURE_2D,
        gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
    Texture(id)
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>gl_helpers.rs: Simplified load_image<commit_after>// See LICENSE file for copyright and license details.

use std;
use gl;
use gl::types::{
    GLint,
    GLuint,
    GLchar,
    GLenum,
    GLsizeiptr,
    GLsizei,
};
use cgmath::matrix::{
    Matrix,
    Mat4,
    Mat3,
    ToMat4,
};
use cgmath::vector::{
    Vec3,
};
use cgmath::angle;
use stb_image::image;
use misc::{
    deg_to_rad,
    read_file,
};
use gl_types::{
    Float,
    MatId,
};
use core_types::{
    Size2,
    Int,
};

pub use load_gl_funcs_with = gl::load_with;

fn c_str(s: &str) -> *GLchar {
    unsafe {
        s.to_c_str().unwrap()
    }
}

fn compile_shader(src: &str, shader_type: GLenum) -> GLuint {
    let shader = gl::CreateShader(shader_type);
    unsafe {
        gl::ShaderSource(shader, 1, &c_str(src), std::ptr::null());
        gl::CompileShader(shader);
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            // subtract 1 to skip the trailing null character
            let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
            gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
                buf.as_mut_ptr() as *mut GLchar
            );
            fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
        }
    }
    shader
}

fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vertex_shader);
    gl::AttachShader(program, fragment_shader);
    gl::LinkProgram(program);
    unsafe {
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            // subtract 1 to skip the trailing null character
            let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
            gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
                buf.as_mut_ptr() as *mut GLchar
            );
            fail!("link_program(): " + std::str::raw::from_utf8(buf));
        }
    }
    program
}

fn compile_program(vertex_shader_src: &str, frag_shader_src: &str) -> Shader {
    let vertex_shader = compile_shader(
        vertex_shader_src, gl::VERTEX_SHADER);
    let fragment_shader = compile_shader(
        frag_shader_src, gl::FRAGMENT_SHADER);
    let program = link_program(vertex_shader, fragment_shader);
    // mark shaders for deletion after program deletion
    gl::DeleteShader(fragment_shader);
    gl::DeleteShader(vertex_shader);
    Shader(program)
}

pub fn draw_mesh(faces_count: Int) {
    let starting_index = 0;
    let vertices_count = faces_count * 3;
    gl::DrawArrays(gl::TRIANGLES, starting_index, vertices_count);
}

pub fn uniform_mat4f(mat_id: MatId, mat: &Mat4<Float>) {
    unsafe {
        let MatId(id) = mat_id;
        gl::UniformMatrix4fv(id as Int, 1, gl::FALSE, mat.cr(0, 0));
    }
}

pub fn tr(m: Mat4<Float>, v: Vec3<Float>) -> Mat4<Float> {
    let mut t = Mat4::<Float>::identity();
    *t.mut_cr(3, 0) = v.x;
    *t.mut_cr(3, 1) = v.y;
    *t.mut_cr(3, 2) = v.z;
    m.mul_m(&t)
}

pub fn rot_x(m: Mat4<Float>, angle: Float) -> Mat4<Float> {
    let rad = angle::rad(deg_to_rad(angle));
    let r = Mat3::from_angle_x(rad).to_mat4();
    m.mul_m(&r)
}

pub fn rot_z(m: Mat4<Float>, angle: Float) -> Mat4<Float> {
    let rad = angle::rad(deg_to_rad(angle));
    let r = Mat3::from_angle_z(rad).to_mat4();
    m.mul_m(&r)
}

pub fn init_opengl() {
    gl::Enable(gl::DEPTH_TEST);
}

pub fn set_clear_color(r: Float, g: Float, b: Float) {
    gl::ClearColor(r, g, b, 1.0);
}

pub fn clear() {
    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
}

pub fn viewport(size: Size2<Int>) {
    gl::Viewport(0, 0, size.w, size.h);
}

pub struct Texture(GLuint);

impl Texture {
    pub fn new(path: ~str) -> Texture {
        load_texture(path)
    }

    pub fn enable(&self, shader: &Shader) {
        let Texture(id) = *self;
        let basic_texture_loc = shader.get_uniform("basic_texture") as GLint;
        gl::Uniform1ui(basic_texture_loc, 0);
        gl::ActiveTexture(gl::TEXTURE0);
        gl::BindTexture(gl::TEXTURE_2D, id);
    }
}

pub struct Shader(GLuint);

impl Shader {
    pub fn new(vs: &str, fs: &str) -> Shader {
        compile_program(
            read_file(&Path::new(vs)),
            read_file(&Path::new(fs)),
        )
    }

    pub fn activate(&self) {
        let Shader(id) = *self;
        gl::UseProgram(id);
    }

    pub fn get_attr(&self, name: &str) -> Attr {
        unsafe {
            let Shader(id) = *self;
            let attr_id = gl::GetAttribLocation(id, c_str(name));
            Attr(attr_id as GLuint)
        }
    }

    pub fn get_uniform(&self, name: &str) -> GLuint {
        let Shader(id) = *self;
        unsafe {
            gl::GetUniformLocation(id, c_str(name)) as GLuint
        }
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        let Shader(id) = *self;
        gl::DeleteProgram(id);
    }
}

pub struct Vbo(GLuint);

fn get_new_vbo_id() -> GLuint {
    let mut id = 0;
    unsafe {
        gl::GenBuffers(1, &mut id);
    }
    id
}

impl Vbo {
    pub fn from_data<T>(data: &[T]) -> Vbo {
        let vbo = Vbo(get_new_vbo_id());
        vbo.bind();
        let size = std::mem::size_of::<T>();
        let buf_size = (data.len() * size) as GLsizeiptr;
        unsafe {
            let data_ptr = std::cast::transmute(&data[0]);
            gl::BufferData(gl::ARRAY_BUFFER, buf_size, data_ptr, gl::STATIC_DRAW);
        }
        vbo
    }

    pub fn bind(&self) {
        let Vbo(id) = *self;
        gl::BindBuffer(gl::ARRAY_BUFFER, id);
    }
}

impl Drop for Vbo {
    fn drop(&mut self) {
        unsafe {
            let Vbo(id) = *self;
            gl::DeleteBuffers(1, &id);
        }
    }
}

pub struct Attr(GLuint);

impl Attr {
    pub fn enable(&self) {
        let Attr(id) = *self;
        gl::EnableVertexAttribArray(id);
    }

    // TODO: Rename
    pub fn vertex_pointer(&self, components_count: Int) {
        let normalized = gl::FALSE;
        let stride = 0;
        let Attr(id) = *self;
        unsafe {
            gl::VertexAttribPointer(
                id,
                components_count,
                gl::FLOAT,
                normalized,
                stride,
                std::ptr::null(),
            );
        }
    }
}

fn load_image(path: ~str) -> image::Image<u8> {
    let load_result = image::load(path);
    match load_result {
        image::ImageU8(image) => image,
        image::Error(message) => fail!("{}", message),
        _ => fail!("Unknown image format"),
    }
}

fn load_texture(path: ~str) -> Texture {
    let image = load_image(path);
    let mut id = 0;
    unsafe {
        gl::GenTextures(1, &mut id)
    };
    gl::ActiveTexture(gl::TEXTURE0);
    gl::BindTexture(gl::TEXTURE_2D, id);
    let format = match image.depth {
        4 => gl::RGBA,
        3 => gl::RGB,
        _ => fail!("wrong depth"),
    };
    unsafe {
        let level = 0;
        let border = 0;
        gl::TexImage2D(
            gl::TEXTURE_2D,
            level,
            format as GLint,
            image.width as GLsizei,
            image.height as GLsizei,
            border,
            format,
            gl::UNSIGNED_BYTE,
            std::cast::transmute(&image.data[0]),
        );
    }
    gl::TexParameteri(gl::TEXTURE_2D,
        gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
    gl::TexParameteri(gl::TEXTURE_2D,
        gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
    gl::TexParameteri(gl::TEXTURE_2D,
        gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint);
    gl::TexParameteri(gl::TEXTURE_2D,
        gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
    Texture(id)
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>