<commit_before><commit_msg>Initial compiling stuff<commit_after>#[macro_use]
extern crate nickel;

use std::collections::HashMap;
use std::convert::From;
use std::path::Path;
use nickel::{Nickel, HttpRouter, StaticFilesHandler, FormBody};
use nickel::{NickelError, Response};
use nickel::status::StatusCode;
use std::ascii::AsciiExt;

fn main() {
    let mut server = Nickel::new();

    server.utilize(StaticFilesHandler::new("public/"));
    server.post("/",
                middleware! {|req, mut res|
        let form_body = req.form_body().or_else(|err| {
            Err("No form body available".to_string())
        });

        let account_info =
            form_body.and_then(|form| {
                let uname: Result<&str, String> = form.get("username").ok_or({
                    "Username must be set".to_string()
                });

                let token = form.get("token").ok_or({
                    "Token must be set".to_string()
                });

                let pass = form.get("password").ok_or({
                    "Password must be set".to_string()
                });

                uname.and_then(|u| {
                    token.and_then(|t| {
                        pass.and_then(|p| {
                            Ok((u, t, p))
                        })
                    })
                })
            });

        let output = account_info.and_then(|(uname, token, pass): (&str, &str, &str)| {
            // now that we've gathered the information, validate that this is a legit request and
            // do the password reset

            if !validate_uname_and_token(uname, token) {
                return Err("invalid username or token".to_string());
            }
            // set_new_password(uname, pass); // TODO
            Ok("We did it boys".to_string())
        });

        match output {
            Ok(o) => {
                o
            }
            Err(e) => {
                res.set(StatusCode::BadRequest);
                e
            }
        }
    });

    let _ = server.listen("127.0.0.1:6767").unwrap();
}

fn validate_uname_and_token(uname: &str, token: &str) -> bool {
    // token database is just the filesystem (fuckit shipit).
    // Tokens are stored in the hierarchy "tokens/token" relative to the program's cwd.
    // The token file contains the string "username".
    //
    // For obvious security reasons, '.' and '/' should be invalid in the token. Just assert it's
    // alphanumeric for simplicity, which solves that.
    if !token.chars().all(|c| c.is_ascii() && c.is_alphanumeric()) {
        return false;
    }
    Path::new(format!("tokens/{}", token).as_str()).exists()
}
<|endoftext|>


<commit_before><commit_msg>Revert 'main.rs'<commit_after><|endoftext|>


<commit_before><commit_msg>resource bars in character menu<commit_after><|endoftext|>


<commit_before><commit_msg>load game visuals are feature complete<commit_after><|endoftext|>


<commit_before><commit_msg>introduce center-of-gravity concept<commit_after><|endoftext|>


<commit_before><commit_msg>Docs: Add code to generate #derive(Not) docs<commit_after>#![allow(dead_code)]
#[macro_use]
extern crate derive_more;

#[derive(Not)]
struct MyInts(i32, i32);

#[derive(Not)]
struct Point2D {
    x: i32,
    y: i32,
}

#[derive(Not)]
enum MixedInts {
    SmallInt(i32),
    BigInt(i64),
    TwoSmallInts(i32, i32),
    NamedSmallInts { x: i32, y: i32 },
    UnsignedOne(u32),
    UnsignedTwo(u32),
}

#[derive(Not)]
enum EnumWithUnit {
    SmallInt(i32),
    Unit,
}
<|endoftext|>


<commit_before><commit_msg>Add example for request params (#379)<commit_after>use jsonrpc_core::*;
use serde_derive::{Deserialize};

#[derive(Deserialize)]
struct HelloParams {
	name:String,
}

fn main() {
	let mut io = IoHandler::new();

	io.add_method("say_hello", |params: Params| {
    let parsed: HelloParams = params.parse().unwrap();
		Ok(Value::String(format!("hello, {}", parsed.name)))
	});

	let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": { "name": "world" }, "id": 1}"#;
	let response = r#"{"jsonrpc":"2.0","result":"hello, world","id":1}"#;

	assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
}
<|endoftext|>


<commit_before><commit_msg>add basic event enum<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2014 Jeremy Letang
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

pub enum Event {
    Close,
    Move,
    Resize,
    KeyUp,
    KeyDown,
    MouseMoved,
    LeftMouseDown,
    LeftMouseUp,
    RightMouseDown,
    RightMouseUp,
    ScrollWheel,
    MouseEntered,
    MouseExited
}<|endoftext|>


<commit_before><commit_msg>bin: add smoke program to disassemble all functions<commit_after>use anyhow::Result;
use log::{debug, error, info};
#[macro_use]
extern crate clap;

use lancelot::{loader::pe::load_pe, util};

fn _main() -> Result<()> {
    better_panic::install();

    let matches = clap::clap_app!(lancelot =>
        (author: "Willi Ballenthin <william.ballenthin@mandiant.com>")
        (about: "Binary analysis framework")
        (@arg verbose: -v --verbose +multiple "log verbose messages")
        (@arg quiet: -q --quiet "disable informational messages")
        (@arg input: +required "path to file to analyze"))
    .get_matches();

    // --quiet overrides --verbose
    let log_level = if matches.is_present("quiet") {
        log::LevelFilter::Error
    } else {
        match matches.occurrences_of("verbose") {
            0 => log::LevelFilter::Info,
            1 => log::LevelFilter::Debug,
            2 => log::LevelFilter::Trace,
            _ => log::LevelFilter::Trace,
        }
    };

    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{} [{:5}] {} {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                record.level(),
                if log_level == log::LevelFilter::Trace {
                    record.target()
                } else {
                    ""
                },
                message
            ))
        })
        .level(log_level)
        .chain(std::io::stderr())
        .filter(|metadata| !metadata.target().starts_with("goblin::pe"))
        .apply()
        .expect("failed to configure logging");

    let filename = matches.value_of("input").unwrap();
    debug!("input: {}", filename);

    let buf = util::read_file(filename)?;
    let pe = load_pe(&buf)?;

    let functions = lancelot::analysis::pe::find_function_starts(&pe)?;
    info!("found {} functions", functions.len());

    for &va in functions.iter() {
        let cfg = lancelot::analysis::cfg::build_cfg(&pe.module, va)?;
        println!("{:#x}: {} basic blocks", va, cfg.basic_blocks.len());
    }

    Ok(())
}

fn main() {
    if let Err(e) = _main() {
        #[cfg(debug_assertions)]
        error!("{:?}", e);
        #[cfg(not(debug_assertions))]
        error!("{:}", e);
    }
}
<|endoftext|>


<commit_before><commit_msg>Problem 36<commit_after>fn factors(n: uint) -> ~[(uint, uint)] {
    if n <= 1 {
        return ~[(n, 1)];
    }
    let mut primes = ~[2];
    let mut result = ~[];
    let mut i = 3;
    let mut n = n;
    while n != 1 {
        let &p = primes.last().unwrap();
        let mut j = 0;
        while n % p == 0 {
            j += 1;
            n /= p;
        }
        if j > 0 {
            result.push((p, j));
        }
        while primes.iter().any(|&x| i%x == 0) {
            i += 2;
        }
        primes.push(i);
    }
    result
}

fn main() {
    println!("{:?}", factors(315));
}

<|endoftext|>


<commit_before><commit_msg>Make a gameplay constants file<commit_after>pub const poly_perimeter_grid_thickness : f32 = 0.05;
pub const poly_interior_grid_thickness : f32 = 0.02;
<|endoftext|>


<commit_before>use std::collections::HashMap;

#[derive(PartialEq,Eq,Debug,Hash,Clone)]
pub enum BasicValue {
    Byte(u8),
    Boolean(bool),
    Int16(i16),
    Uint16(u16),
    Int32(i32),
    Uint32(u32),
    Int64(i64),
    Uint64(u64),
    String(String),
    ObjectPath(Path),
    Signature(Signature),
}

#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub struct Path(pub String);

#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub struct Signature(pub String);

#[derive(PartialEq,Debug,Clone)]
pub struct Struct {
    pub objects: Vec<Value>,
    pub signature: Signature
}

pub type Dictionary = HashMap<BasicValue,Value>;

#[derive(PartialEq,Debug,Clone)]
pub enum Value {
    BasicValue(BasicValue),
    Double(f64),
    Array(Vec<Value>),
    Variant(Box<Value>),
    Struct(Struct),
    Dictionary(Dictionary)
}
<commit_msg>types.rs: implement From traits for BasicValue<commit_after>use std::collections::HashMap;

#[derive(PartialEq,Eq,Debug,Hash,Clone)]
pub enum BasicValue {
    Byte(u8),
    Boolean(bool),
    Int16(i16),
    Uint16(u16),
    Int32(i32),
    Uint32(u32),
    Int64(i64),
    Uint64(u64),
    String(String),
    ObjectPath(Path),
    Signature(Signature),
}

#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub struct Path(pub String);

#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub struct Signature(pub String);

#[derive(PartialEq,Debug,Clone)]
pub struct Struct {
    pub objects: Vec<Value>,
    pub signature: Signature
}

pub type Dictionary = HashMap<BasicValue,Value>;

#[derive(PartialEq,Debug,Clone)]
pub enum Value {
    BasicValue(BasicValue),
    Double(f64),
    Array(Vec<Value>),
    Variant(Box<Value>),
    Struct(Struct),
    Dictionary(Dictionary)
}

impl<'a> From<&'a Value> for u8 {
    fn from(v: &'a Value) -> u8 {
        match v {
            &Value::BasicValue(BasicValue::Byte(x)) => x,
            _ => panic!("Not a byte")
        }
    }
}

impl<'a> From<&'a Value> for i16 {
    fn from(v: &'a Value) -> i16 {
        match v {
            &Value::BasicValue(BasicValue::Int16(x)) => x,
            _ => panic!("Not an Int16")
        }
    }
}

impl<'a> From<&'a Value> for i32 {
    fn from(v: &'a Value) -> i32 {
        match v {
            &Value::BasicValue(BasicValue::Int32(x)) => x,
            _ => panic!("Not an Int32")
        }
    }
}

impl<'a> From<&'a Value> for i64 {
    fn from(v: &'a Value) -> i64 {
        match v {
            &Value::BasicValue(BasicValue::Int64(x)) => x,
            _ => panic!("Not an Int64")
        }
    }
}

impl<'a> From<&'a Value> for u16 {
    fn from(v: &'a Value) -> u16 {
        match v {
            &Value::BasicValue(BasicValue::Uint16(x)) => x,
            _ => panic!("Not a Uint16")
        }
    }
}

impl<'a> From<&'a Value> for u32 {
    fn from(v: &'a Value) -> u32 {
        match v {
            &Value::BasicValue(BasicValue::Uint32(x)) => x,
            _ => panic!("Not a Uint32")
        }
    }
}

impl<'a> From<&'a Value> for u64 {
    fn from(v: &'a Value) -> u64 {
        match v {
            &Value::BasicValue(BasicValue::Uint64(x)) => x,
            _ => panic!("Not a Uint32")
        }
    }
}

impl<'a> From<&'a Value> for String {
    fn from(v: &'a Value) -> String {
        match v {
            &Value::BasicValue(BasicValue::String(ref x)) => x.to_string(),
            &Value::BasicValue(BasicValue::ObjectPath(Path(ref x))) => x.to_string(),
            &Value::BasicValue(BasicValue::Signature(Signature(ref x))) => x.to_string(),
            _ => panic!("Not a string type")
        }
    }
}

<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-android: FIXME(#10381)
// ignore-test: FIXME(#12021)

// This test case checks if function arguments already have the correct value when breaking at the
// first line of the function, that is if the function prologue has already been executed at the
// first line. Note that because of the __morestack part of the prologue GDB incorrectly breaks at
// before the arguments have been properly loaded when setting the breakpoint via the function name.
// Therefore the setup here sets them using line numbers (so be careful when changing this file).

// compile-flags:-g
// debugger:set print pretty off
// debugger:break function-arg-initialization.rs:139
// debugger:break function-arg-initialization.rs:154
// debugger:break function-arg-initialization.rs:158
// debugger:break function-arg-initialization.rs:162
// debugger:break function-arg-initialization.rs:166
// debugger:break function-arg-initialization.rs:170
// debugger:break function-arg-initialization.rs:174
// debugger:break function-arg-initialization.rs:178
// debugger:break function-arg-initialization.rs:182
// debugger:break function-arg-initialization.rs:190
// debugger:break function-arg-initialization.rs:197

// debugger:run

// IMMEDIATE ARGS
// debugger:print a
// check:$1 = 1
// debugger:print b
// check:$2 = true
// debugger:print c
// check:$3 = 2.5
// debugger:continue

// NON IMMEDIATE ARGS
// debugger:print a
// check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10}
// debugger:print b
// check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18}
// debugger:continue

// BINDING
// debugger:print a
// check:$6 = 19
// debugger:print b
// check:$7 = 20
// debugger:print c
// check:$8 = 21.5
// debugger:continue

// ASSIGNMENT
// debugger:print a
// check:$9 = 22
// debugger:print b
// check:$10 = 23
// debugger:print c
// check:$11 = 24.5
// debugger:continue

// FUNCTION CALL
// debugger:print x
// check:$12 = 25
// debugger:print y
// check:$13 = 26
// debugger:print z
// check:$14 = 27.5
// debugger:continue

// EXPR
// debugger:print x
// check:$15 = 28
// debugger:print y
// check:$16 = 29
// debugger:print z
// check:$17 = 30.5
// debugger:continue

// RETURN EXPR
// debugger:print x
// check:$18 = 31
// debugger:print y
// check:$19 = 32
// debugger:print z
// check:$20 = 33.5
// debugger:continue

// ARITHMETIC EXPR
// debugger:print x
// check:$21 = 34
// debugger:print y
// check:$22 = 35
// debugger:print z
// check:$23 = 36.5
// debugger:continue

// IF EXPR
// debugger:print x
// check:$24 = 37
// debugger:print y
// check:$25 = 38
// debugger:print z
// check:$26 = 39.5
// debugger:continue

// WHILE EXPR
// debugger:print x
// check:$27 = 40
// debugger:print y
// check:$28 = 41
// debugger:print z
// check:$29 = 42
// debugger:continue

// LOOP EXPR
// debugger:print x
// check:$30 = 43
// debugger:print y
// check:$31 = 44
// debugger:print z
// check:$32 = 45
// debugger:continue

#[allow(unused_variable)];

fn immediate_args(a: int, b: bool, c: f64) {
    ()
}

struct BigStruct {
    a: u64,
    b: u64,
    c: u64,
    d: u64,
    e: u64,
    f: u64,
    g: u64,
    h: u64
}

fn non_immediate_args(a: BigStruct, b: BigStruct) {
    ()
}

fn binding(a: i64, b: u64, c: f64) {
    let x = 0;
}

fn assignment(mut a: u64, b: u64, c: f64) {
    a = b;
}

fn function_call(x: u64, y: u64, z: f64) {
    std::io::stdio::print("Hi!")
}

fn identifier(x: u64, y: u64, z: f64) -> u64 {
    x
}

fn return_expr(x: u64, y: u64, z: f64) -> u64 {
    return x;
}

fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 {
    x + y
}

fn if_expr(x: u64, y: u64, z: f64) -> u64 {
    if x + y < 1000 {
        x
    } else {
        y
    }
}

fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
    while x + y < 1000 {
        x += z
    }
    return x;
}

fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 {
    loop {
        x += z;

        if x + y > 1000 {
            return x;
        }
    }
}

fn main() {
    immediate_args(1, true, 2.5);

    non_immediate_args(
        BigStruct {
            a: 3,
            b: 4,
            c: 5,
            d: 6,
            e: 7,
            f: 8,
            g: 9,
            h: 10
        },
        BigStruct {
            a: 11,
            b: 12,
            c: 13,
            d: 14,
            e: 15,
            f: 16,
            g: 17,
            h: 18
        }
    );

    binding(19, 20, 21.5);
    assignment(22, 23, 24.5);
    function_call(25, 26, 27.5);
    identifier(28, 29, 30.5);
    return_expr(31, 32, 33.5);
    arithmetic_expr(34, 35, 36.5);
    if_expr(37, 38, 39.5);
    while_expr(40, 41, 42);
    loop_expr(43, 44, 45);
}

<commit_msg>debuginfo: Re-enable test case that should have worked all along.<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-android: FIXME(#10381)

// This test case checks if function arguments already have the correct value when breaking at the
// first line of the function, that is if the function prologue has already been executed at the
// first line. Note that because of the __morestack part of the prologue GDB incorrectly breaks at
// before the arguments have been properly loaded when setting the breakpoint via the function name.
// Therefore the setup here sets them using line numbers (so be careful when changing this file).

// compile-flags:-g
// debugger:set print pretty off
// debugger:break function-arg-initialization.rs:139
// debugger:break function-arg-initialization.rs:154
// debugger:break function-arg-initialization.rs:158
// debugger:break function-arg-initialization.rs:162
// debugger:break function-arg-initialization.rs:166
// debugger:break function-arg-initialization.rs:170
// debugger:break function-arg-initialization.rs:174
// debugger:break function-arg-initialization.rs:178
// debugger:break function-arg-initialization.rs:182
// debugger:break function-arg-initialization.rs:190
// debugger:break function-arg-initialization.rs:197

// debugger:run

// IMMEDIATE ARGS
// debugger:print a
// check:$1 = 1
// debugger:print b
// check:$2 = true
// debugger:print c
// check:$3 = 2.5
// debugger:continue

// NON IMMEDIATE ARGS
// debugger:print a
// check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10}
// debugger:print b
// check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18}
// debugger:continue

// BINDING
// debugger:print a
// check:$6 = 19
// debugger:print b
// check:$7 = 20
// debugger:print c
// check:$8 = 21.5
// debugger:continue

// ASSIGNMENT
// debugger:print a
// check:$9 = 22
// debugger:print b
// check:$10 = 23
// debugger:print c
// check:$11 = 24.5
// debugger:continue

// FUNCTION CALL
// debugger:print x
// check:$12 = 25
// debugger:print y
// check:$13 = 26
// debugger:print z
// check:$14 = 27.5
// debugger:continue

// EXPR
// debugger:print x
// check:$15 = 28
// debugger:print y
// check:$16 = 29
// debugger:print z
// check:$17 = 30.5
// debugger:continue

// RETURN EXPR
// debugger:print x
// check:$18 = 31
// debugger:print y
// check:$19 = 32
// debugger:print z
// check:$20 = 33.5
// debugger:continue

// ARITHMETIC EXPR
// debugger:print x
// check:$21 = 34
// debugger:print y
// check:$22 = 35
// debugger:print z
// check:$23 = 36.5
// debugger:continue

// IF EXPR
// debugger:print x
// check:$24 = 37
// debugger:print y
// check:$25 = 38
// debugger:print z
// check:$26 = 39.5
// debugger:continue

// WHILE EXPR
// debugger:print x
// check:$27 = 40
// debugger:print y
// check:$28 = 41
// debugger:print z
// check:$29 = 42
// debugger:continue

// LOOP EXPR
// debugger:print x
// check:$30 = 43
// debugger:print y
// check:$31 = 44
// debugger:print z
// check:$32 = 45
// debugger:continue

#[allow(unused_variable)];

fn immediate_args(a: int, b: bool, c: f64) {
    ()
}

struct BigStruct {
    a: u64,
    b: u64,
    c: u64,
    d: u64,
    e: u64,
    f: u64,
    g: u64,
    h: u64
}

fn non_immediate_args(a: BigStruct, b: BigStruct) {
    ()
}

fn binding(a: i64, b: u64, c: f64) {
    let x = 0;
}

fn assignment(mut a: u64, b: u64, c: f64) {
    a = b;
}

fn function_call(x: u64, y: u64, z: f64) {
    std::io::stdio::print("Hi!")
}

fn identifier(x: u64, y: u64, z: f64) -> u64 {
    x
}

fn return_expr(x: u64, y: u64, z: f64) -> u64 {
    return x;
}

fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 {
    x + y
}

fn if_expr(x: u64, y: u64, z: f64) -> u64 {
    if x + y < 1000 {
        x
    } else {
        y
    }
}

fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
    while x + y < 1000 {
        x += z
    }
    return x;
}

fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 {
    loop {
        x += z;

        if x + y > 1000 {
            return x;
        }
    }
}

fn main() {
    immediate_args(1, true, 2.5);

    non_immediate_args(
        BigStruct {
            a: 3,
            b: 4,
            c: 5,
            d: 6,
            e: 7,
            f: 8,
            g: 9,
            h: 10
        },
        BigStruct {
            a: 11,
            b: 12,
            c: 13,
            d: 14,
            e: 15,
            f: 16,
            g: 17,
            h: 18
        }
    );

    binding(19, 20, 21.5);
    assignment(22, 23, 24.5);
    function_call(25, 26, 27.5);
    identifier(28, 29, 30.5);
    return_expr(31, 32, 33.5);
    arithmetic_expr(34, 35, 36.5);
    if_expr(37, 38, 39.5);
    while_expr(40, 41, 42);
    loop_expr(43, 44, 45);
}

<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All rights reserved.
//
// 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.

//! An engine for handling edits (possibly from async sources) and undo. This
//! module actually implements a mini Conflict-free Replicated Data Type, but
//! is considerably simpler than the usual CRDT implementation techniques,
//! because all operations are serialized in this central engine.

use std::borrow::Cow;
use std::collections::BTreeSet;
use std;

use rope::{Rope, RopeInfo};
use subset::Subset;
use delta::Delta;

pub struct Engine {
    rev_id_counter: usize,
    union_str: Rope,
    revs: Vec<Revision>,
}

struct Revision {
    rev_id: usize,
    deletes_from_union: Subset,
    union_str_len: usize,
    edit: Contents,
}

use self::Contents::*;

enum Contents {
    Edit {
        priority: usize,
        undo_group: usize,
        inserts: Subset,
        deletes: Subset,
    },
    Undo {
        groups: BTreeSet<usize>,  // set of undo_group id's
    }
}

impl Engine {
    pub fn new(initial_contents: Rope) -> Engine {
        let rev = Revision {
            rev_id: 0,
            deletes_from_union: Subset::default(),
            union_str_len: initial_contents.len(),
            edit: Undo { groups: BTreeSet::default() },
        };
        Engine {
            rev_id_counter: 1,
            union_str: initial_contents,
            revs: vec![rev],
        }
    }

    fn get_current_undo(&self) -> Option<&BTreeSet<usize>> {
        for rev in self.revs.iter().rev() {
            if let Undo { ref groups } = rev.edit {
                return Some(groups);
            }
        }
        None
    }

    fn find_rev(&self, rev_id: usize) -> Option<usize> {
        for (i, rev) in self.revs.iter().enumerate().rev() {
            if rev.rev_id == rev_id {
                return Some(i)
            }
        }
        None
    }

    fn get_rev_from_index(&self, rev_index: usize) -> Rope {
        let mut deletes_from_union = Cow::Borrowed(&self.revs[rev_index].deletes_from_union);
        for rev in &self.revs[rev_index + 1..] {
            if let Edit { ref inserts, .. } = rev.edit {
                if !inserts.is_empty() {
                    deletes_from_union = Cow::Owned(deletes_from_union.transform_union(inserts));
                }
            }
        }
        deletes_from_union.delete_in(&self.union_str)
    }

    fn get_subset_from_index(&self, rev_index: usize) -> Cow<Subset> {
        let mut deletes_from_union = Cow::Borrowed(&self.revs[rev_index].deletes_from_union);
        for rev in &self.revs[rev_index + 1..] {
            if let Edit { ref inserts, .. } = rev.edit {
                if !inserts.is_empty() {
                    deletes_from_union = Cow::Owned(deletes_from_union.transform_union(inserts));
                }
            }
        }
        deletes_from_union
    }

    /// Get revision id of head revision.
    pub fn get_head_rev_id(&self) -> usize {
        self.revs.last().unwrap().rev_id
    }

    /// Get text of head revision.
    pub fn get_head(&self) -> Rope {
        self.get_rev_from_index(self.revs.len() - 1)
    }

    /// Get text of a given revision, if it can be found.
    pub fn get_rev(&self, rev: usize) -> Option<Rope> {
        self.find_rev(rev).map(|rev_index| self.get_rev_from_index(rev_index))
    }

    /// A delta that, when applied to previous head, results in the current head. Panics
    /// if there is not at least one edit.
    pub fn delta_rev_head(&self, base_rev: usize) -> Delta<RopeInfo> {
        let ix = self.find_rev(base_rev).expect("base revision not found");
        let rev = &self.revs[ix];
        let mut prev_from_union = Cow::Borrowed(&rev.deletes_from_union);
        for r in &self.revs[ix + 1..] {
            if let Edit { ref inserts, .. } = r.edit {
                if !inserts.is_empty() {
                    prev_from_union = Cow::Owned(prev_from_union.transform_union(inserts));
                }
            }
        }
        let head_rev = &self.revs.last().unwrap();
        Delta::synthesize(&self.union_str, &prev_from_union, &head_rev.deletes_from_union)
    }

    fn mk_new_rev(&self, new_priority: usize, undo_group: usize,
            base_rev: usize, delta: Delta<RopeInfo>) -> (Revision, Rope) {
        let ix = self.find_rev(base_rev).expect("base revision not found");
        let rev = &self.revs[ix];
        let (ins_delta, deletes) = delta.factor();
        let mut union_ins_delta = ins_delta.transform_expand(&rev.deletes_from_union, rev.union_str_len, true);
        let mut new_deletes = deletes.transform_expand(&rev.deletes_from_union);
        for r in &self.revs[ix + 1..] {
            if let Edit { priority, ref inserts, .. } = r.edit {
                if !inserts.is_empty() {
                    let after = new_priority >= priority;  // should never be ==
                    union_ins_delta = union_ins_delta.transform_expand(inserts, r.union_str_len, after);
                    new_deletes = new_deletes.transform_expand(inserts);
                }
            }
        }
        let new_inserts = union_ins_delta.inserted_subset();
        if !new_inserts.is_empty() {
            new_deletes = new_deletes.transform_expand(&new_inserts);
        }
        let new_union_str = union_ins_delta.apply(&self.union_str);
        let undone = self.get_current_undo().map_or(false, |undos| undos.contains(&undo_group));
        let mut new_from_union = Cow::Borrowed(&self.revs.last().unwrap().deletes_from_union);
        if undone {
            if !new_inserts.is_empty() {
                new_from_union = Cow::Owned(new_from_union.transform_union(&new_inserts));
            }
        } else {
            if !new_inserts.is_empty() {
                new_from_union = Cow::Owned(new_from_union.transform_expand(&new_inserts));
            }
            if !new_deletes.is_empty() {
                new_from_union = Cow::Owned(new_from_union.union(&new_deletes));
            }
        }
        (Revision {
            rev_id: self.rev_id_counter,
            deletes_from_union: new_from_union.into_owned(),
            union_str_len: new_union_str.len(),
            edit: Edit {
                priority: new_priority,
                undo_group: undo_group,
                inserts: new_inserts,
                deletes: new_deletes,
            }
        }, new_union_str)
    }

    pub fn edit_rev(&mut self, priority: usize, undo_group: usize,
            base_rev: usize, delta: Delta<RopeInfo>) {
        let (new_rev, new_union_str) = self.mk_new_rev(priority, undo_group, base_rev, delta);
        self.rev_id_counter += 1;
        self.revs.push(new_rev);
        self.union_str = new_union_str;
    }

    // This computes undo all the way from the beginning. An optimization would be to not
    // recompute the prefix up to where the history diverges, but it's not clear that's
    // even worth the code complexity.
    fn compute_undo(&self, groups: BTreeSet<usize>) -> Revision {
        let mut deletes_from_union = Subset::default();
        for rev in &self.revs {
            if let Edit { ref undo_group, ref inserts, ref deletes, .. } = rev.edit {
                if groups.contains(undo_group) {
                    if !inserts.is_empty() {
                        deletes_from_union = deletes_from_union.transform_union(inserts);
                    }
                } else {
                    if !inserts.is_empty() {
                        deletes_from_union = deletes_from_union.transform_expand(inserts);
                    }
                    if !deletes.is_empty() {
                        deletes_from_union = deletes_from_union.union(deletes);
                    }
                }
            }
        }
        Revision {
            rev_id: self.rev_id_counter,
            deletes_from_union: deletes_from_union,
            union_str_len: self.union_str.len(),
            edit: Undo {
                groups: groups
            }
        }
    }

    pub fn undo(&mut self, groups: BTreeSet<usize>) {
        let new_rev = self.compute_undo(groups);
        self.revs.push(new_rev);
        self.rev_id_counter += 1;
    }

    pub fn is_equivalent_revision(&self, base_rev: usize, other_rev: usize) -> bool {
        let base_subset = self.find_rev(base_rev).map(|rev_index| self.get_subset_from_index(rev_index));
        let other_subset = self.find_rev(other_rev).map(|rev_index| self.get_subset_from_index(rev_index));

        base_subset.is_some() && base_subset == other_subset
    }

    // Note: this function would need some work to handle retaining arbitrary revisions,
    // partly because the reachability calculation would become more complicated (a
    // revision might hold content from an undo group that would otherwise be gc'ed),
    // and partly because you need to retain more undo history, to supply input to the
    // reachability calculation.
    //
    // Thus, it's easiest to defer gc to when all plugins quiesce, but it's certainly
    // possible to fix it so that's not necessary.
    pub fn gc(&mut self, gc_groups: &BTreeSet<usize>) {
        let mut gc_dels = Subset::default();
        // TODO: want to let caller retain more rev_id's.
        let mut retain_revs = BTreeSet::new();
        if let Some(last) = self.revs.last() {
            retain_revs.insert(last.rev_id);
        }
        {
            let cur_undo = self.get_current_undo();
            for rev in &self.revs {
                if let Edit { ref undo_group, ref inserts, ref deletes, .. } = rev.edit {
                    if !retain_revs.contains(&rev.rev_id) && gc_groups.contains(undo_group) {
                        if cur_undo.map_or(false, |undos| undos.contains(undo_group)) {
                            if !inserts.is_empty() {
                                gc_dels = gc_dels.transform_union(inserts);
                            }
                        } else {
                            if !inserts.is_empty() {
                                gc_dels = gc_dels.transform_expand(inserts);
                            }
                            if !deletes.is_empty() {
                                gc_dels = gc_dels.union(deletes);
                            }
                        }
                    } else if !inserts.is_empty() {
                        gc_dels = gc_dels.transform_expand(inserts);
                    }
                }
            }
        }
        if !gc_dels.is_empty() {
            self.union_str = gc_dels.delete_in(&self.union_str);
        }
        let old_revs = std::mem::replace(&mut self.revs, Vec::new());
        for rev in old_revs.into_iter().rev() {
            match rev.edit {
                Edit { priority, undo_group, inserts, deletes } => {
                    let new_gc_dels = if inserts.is_empty() {
                        None
                    } else {
                        Some(inserts.transform_shrink(&gc_dels))
                    };
                    if retain_revs.contains(&rev.rev_id) || !gc_groups.contains(&undo_group) {
                        let (inserts, deletes, deletes_from_union, len) = if gc_dels.is_empty() {
                            (inserts, deletes, rev.deletes_from_union, rev.union_str_len)
                        } else {
                            (gc_dels.transform_shrink(&inserts),
                                gc_dels.transform_shrink(&deletes),
                                gc_dels.transform_shrink(&rev.deletes_from_union),
                                gc_dels.len_after_delete(rev.union_str_len))
                        };
                        self.revs.push(Revision {
                            rev_id: rev.rev_id,
                            deletes_from_union: deletes_from_union,
                            union_str_len: len,
                            edit: Edit {
                                priority: priority,
                                undo_group: undo_group,
                                inserts: inserts,
                                deletes: deletes,
                            }
                        });
                    }
                    if let Some(new_gc_dels) = new_gc_dels {
                        gc_dels = new_gc_dels;
                    }
                }
                Undo { groups } => {
                    // We're super-aggressive about dropping these; after gc, the history
                    // of which undos were used to compute deletes_from_union in edits may be lost.
                    if retain_revs.contains(&rev.rev_id) {
                        let (deletes_from_union, len) = if gc_dels.is_empty() {
                            (rev.deletes_from_union, rev.union_str_len)
                        } else {
                            (gc_dels.transform_shrink(&rev.deletes_from_union),
                                gc_dels.len_after_delete(rev.union_str_len))
                        };
                        self.revs.push(Revision {
                            rev_id: rev.rev_id,
                            deletes_from_union: deletes_from_union,
                            union_str_len: len,
                            edit: Undo {
                                groups: &groups - gc_groups,
                            }
                        })
                    }
                }
            }
        }
        self.revs.reverse();
    }
}
<commit_msg>Remove duplicatation in Engine method<commit_after>// Copyright 2016 Google Inc. All rights reserved.
//
// 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.

//! An engine for handling edits (possibly from async sources) and undo. This
//! module actually implements a mini Conflict-free Replicated Data Type, but
//! is considerably simpler than the usual CRDT implementation techniques,
//! because all operations are serialized in this central engine.

use std::borrow::Cow;
use std::collections::BTreeSet;
use std;

use rope::{Rope, RopeInfo};
use subset::Subset;
use delta::Delta;

pub struct Engine {
    rev_id_counter: usize,
    union_str: Rope,
    revs: Vec<Revision>,
}

struct Revision {
    rev_id: usize,
    deletes_from_union: Subset,
    union_str_len: usize,
    edit: Contents,
}

use self::Contents::*;

enum Contents {
    Edit {
        priority: usize,
        undo_group: usize,
        inserts: Subset,
        deletes: Subset,
    },
    Undo {
        groups: BTreeSet<usize>,  // set of undo_group id's
    }
}

impl Engine {
    pub fn new(initial_contents: Rope) -> Engine {
        let rev = Revision {
            rev_id: 0,
            deletes_from_union: Subset::default(),
            union_str_len: initial_contents.len(),
            edit: Undo { groups: BTreeSet::default() },
        };
        Engine {
            rev_id_counter: 1,
            union_str: initial_contents,
            revs: vec![rev],
        }
    }

    fn get_current_undo(&self) -> Option<&BTreeSet<usize>> {
        for rev in self.revs.iter().rev() {
            if let Undo { ref groups } = rev.edit {
                return Some(groups);
            }
        }
        None
    }

    fn find_rev(&self, rev_id: usize) -> Option<usize> {
        for (i, rev) in self.revs.iter().enumerate().rev() {
            if rev.rev_id == rev_id {
                return Some(i)
            }
        }
        None
    }

    /// Get the contents of the document at a given revision number
    fn get_rev_from_index(&self, rev_index: usize) -> Rope {
        self.get_subset_from_index(rev_index).delete_in(&self.union_str)
    }

    /// Get the Subset to delete from the current union string in order to obtain a revision's content
    fn get_subset_from_index(&self, rev_index: usize) -> Cow<Subset> {
        let mut deletes_from_union = Cow::Borrowed(&self.revs[rev_index].deletes_from_union);
        for rev in &self.revs[rev_index + 1..] {
            if let Edit { ref inserts, .. } = rev.edit {
                if !inserts.is_empty() {
                    deletes_from_union = Cow::Owned(deletes_from_union.transform_union(inserts));
                }
            }
        }
        deletes_from_union
    }

    /// Get revision id of head revision.
    pub fn get_head_rev_id(&self) -> usize {
        self.revs.last().unwrap().rev_id
    }

    /// Get text of head revision.
    pub fn get_head(&self) -> Rope {
        self.get_rev_from_index(self.revs.len() - 1)
    }

    /// Get text of a given revision, if it can be found.
    pub fn get_rev(&self, rev: usize) -> Option<Rope> {
        self.find_rev(rev).map(|rev_index| self.get_rev_from_index(rev_index))
    }

    /// A delta that, when applied to previous head, results in the current head. Panics
    /// if there is not at least one edit.
    pub fn delta_rev_head(&self, base_rev: usize) -> Delta<RopeInfo> {
        let ix = self.find_rev(base_rev).expect("base revision not found");
        let rev = &self.revs[ix];
        let mut prev_from_union = Cow::Borrowed(&rev.deletes_from_union);
        for r in &self.revs[ix + 1..] {
            if let Edit { ref inserts, .. } = r.edit {
                if !inserts.is_empty() {
                    prev_from_union = Cow::Owned(prev_from_union.transform_union(inserts));
                }
            }
        }
        let head_rev = &self.revs.last().unwrap();
        Delta::synthesize(&self.union_str, &prev_from_union, &head_rev.deletes_from_union)
    }

    fn mk_new_rev(&self, new_priority: usize, undo_group: usize,
            base_rev: usize, delta: Delta<RopeInfo>) -> (Revision, Rope) {
        let ix = self.find_rev(base_rev).expect("base revision not found");
        let rev = &self.revs[ix];
        let (ins_delta, deletes) = delta.factor();
        let mut union_ins_delta = ins_delta.transform_expand(&rev.deletes_from_union, rev.union_str_len, true);
        let mut new_deletes = deletes.transform_expand(&rev.deletes_from_union);
        for r in &self.revs[ix + 1..] {
            if let Edit { priority, ref inserts, .. } = r.edit {
                if !inserts.is_empty() {
                    let after = new_priority >= priority;  // should never be ==
                    union_ins_delta = union_ins_delta.transform_expand(inserts, r.union_str_len, after);
                    new_deletes = new_deletes.transform_expand(inserts);
                }
            }
        }
        let new_inserts = union_ins_delta.inserted_subset();
        if !new_inserts.is_empty() {
            new_deletes = new_deletes.transform_expand(&new_inserts);
        }
        let new_union_str = union_ins_delta.apply(&self.union_str);
        let undone = self.get_current_undo().map_or(false, |undos| undos.contains(&undo_group));
        let mut new_from_union = Cow::Borrowed(&self.revs.last().unwrap().deletes_from_union);
        if undone {
            if !new_inserts.is_empty() {
                new_from_union = Cow::Owned(new_from_union.transform_union(&new_inserts));
            }
        } else {
            if !new_inserts.is_empty() {
                new_from_union = Cow::Owned(new_from_union.transform_expand(&new_inserts));
            }
            if !new_deletes.is_empty() {
                new_from_union = Cow::Owned(new_from_union.union(&new_deletes));
            }
        }
        (Revision {
            rev_id: self.rev_id_counter,
            deletes_from_union: new_from_union.into_owned(),
            union_str_len: new_union_str.len(),
            edit: Edit {
                priority: new_priority,
                undo_group: undo_group,
                inserts: new_inserts,
                deletes: new_deletes,
            }
        }, new_union_str)
    }

    pub fn edit_rev(&mut self, priority: usize, undo_group: usize,
            base_rev: usize, delta: Delta<RopeInfo>) {
        let (new_rev, new_union_str) = self.mk_new_rev(priority, undo_group, base_rev, delta);
        self.rev_id_counter += 1;
        self.revs.push(new_rev);
        self.union_str = new_union_str;
    }

    // This computes undo all the way from the beginning. An optimization would be to not
    // recompute the prefix up to where the history diverges, but it's not clear that's
    // even worth the code complexity.
    fn compute_undo(&self, groups: BTreeSet<usize>) -> Revision {
        let mut deletes_from_union = Subset::default();
        for rev in &self.revs {
            if let Edit { ref undo_group, ref inserts, ref deletes, .. } = rev.edit {
                if groups.contains(undo_group) {
                    if !inserts.is_empty() {
                        deletes_from_union = deletes_from_union.transform_union(inserts);
                    }
                } else {
                    if !inserts.is_empty() {
                        deletes_from_union = deletes_from_union.transform_expand(inserts);
                    }
                    if !deletes.is_empty() {
                        deletes_from_union = deletes_from_union.union(deletes);
                    }
                }
            }
        }
        Revision {
            rev_id: self.rev_id_counter,
            deletes_from_union: deletes_from_union,
            union_str_len: self.union_str.len(),
            edit: Undo {
                groups: groups
            }
        }
    }

    pub fn undo(&mut self, groups: BTreeSet<usize>) {
        let new_rev = self.compute_undo(groups);
        self.revs.push(new_rev);
        self.rev_id_counter += 1;
    }

    pub fn is_equivalent_revision(&self, base_rev: usize, other_rev: usize) -> bool {
        let base_subset = self.find_rev(base_rev).map(|rev_index| self.get_subset_from_index(rev_index));
        let other_subset = self.find_rev(other_rev).map(|rev_index| self.get_subset_from_index(rev_index));

        base_subset.is_some() && base_subset == other_subset
    }

    // Note: this function would need some work to handle retaining arbitrary revisions,
    // partly because the reachability calculation would become more complicated (a
    // revision might hold content from an undo group that would otherwise be gc'ed),
    // and partly because you need to retain more undo history, to supply input to the
    // reachability calculation.
    //
    // Thus, it's easiest to defer gc to when all plugins quiesce, but it's certainly
    // possible to fix it so that's not necessary.
    pub fn gc(&mut self, gc_groups: &BTreeSet<usize>) {
        let mut gc_dels = Subset::default();
        // TODO: want to let caller retain more rev_id's.
        let mut retain_revs = BTreeSet::new();
        if let Some(last) = self.revs.last() {
            retain_revs.insert(last.rev_id);
        }
        {
            let cur_undo = self.get_current_undo();
            for rev in &self.revs {
                if let Edit { ref undo_group, ref inserts, ref deletes, .. } = rev.edit {
                    if !retain_revs.contains(&rev.rev_id) && gc_groups.contains(undo_group) {
                        if cur_undo.map_or(false, |undos| undos.contains(undo_group)) {
                            if !inserts.is_empty() {
                                gc_dels = gc_dels.transform_union(inserts);
                            }
                        } else {
                            if !inserts.is_empty() {
                                gc_dels = gc_dels.transform_expand(inserts);
                            }
                            if !deletes.is_empty() {
                                gc_dels = gc_dels.union(deletes);
                            }
                        }
                    } else if !inserts.is_empty() {
                        gc_dels = gc_dels.transform_expand(inserts);
                    }
                }
            }
        }
        if !gc_dels.is_empty() {
            self.union_str = gc_dels.delete_in(&self.union_str);
        }
        let old_revs = std::mem::replace(&mut self.revs, Vec::new());
        for rev in old_revs.into_iter().rev() {
            match rev.edit {
                Edit { priority, undo_group, inserts, deletes } => {
                    let new_gc_dels = if inserts.is_empty() {
                        None
                    } else {
                        Some(inserts.transform_shrink(&gc_dels))
                    };
                    if retain_revs.contains(&rev.rev_id) || !gc_groups.contains(&undo_group) {
                        let (inserts, deletes, deletes_from_union, len) = if gc_dels.is_empty() {
                            (inserts, deletes, rev.deletes_from_union, rev.union_str_len)
                        } else {
                            (gc_dels.transform_shrink(&inserts),
                                gc_dels.transform_shrink(&deletes),
                                gc_dels.transform_shrink(&rev.deletes_from_union),
                                gc_dels.len_after_delete(rev.union_str_len))
                        };
                        self.revs.push(Revision {
                            rev_id: rev.rev_id,
                            deletes_from_union: deletes_from_union,
                            union_str_len: len,
                            edit: Edit {
                                priority: priority,
                                undo_group: undo_group,
                                inserts: inserts,
                                deletes: deletes,
                            }
                        });
                    }
                    if let Some(new_gc_dels) = new_gc_dels {
                        gc_dels = new_gc_dels;
                    }
                }
                Undo { groups } => {
                    // We're super-aggressive about dropping these; after gc, the history
                    // of which undos were used to compute deletes_from_union in edits may be lost.
                    if retain_revs.contains(&rev.rev_id) {
                        let (deletes_from_union, len) = if gc_dels.is_empty() {
                            (rev.deletes_from_union, rev.union_str_len)
                        } else {
                            (gc_dels.transform_shrink(&rev.deletes_from_union),
                                gc_dels.len_after_delete(rev.union_str_len))
                        };
                        self.revs.push(Revision {
                            rev_id: rev.rev_id,
                            deletes_from_union: deletes_from_union,
                            union_str_len: len,
                            edit: Undo {
                                groups: &groups - gc_groups,
                            }
                        })
                    }
                }
            }
        }
        self.revs.reverse();
    }
}
<|endoftext|>


<commit_before>use alloc::arc::{Arc, Weak};
use alloc::boxed::Box;

use collections::{BTreeMap, String};
use collections::string::ToString;

use core::cell::Cell;
use core::mem::size_of;
use core::ops::DerefMut;

use scheduler::context::{context_switch, Context, ContextMemory};

use schemes::{Result, Resource, ResourceSeek, KScheme, Url};

use sync::Intex;

use system::error::{Error, EBADF, EFAULT, EINVAL, ENOENT, ESPIPE, ESRCH};
use system::scheme::Packet;
use system::syscall::{SYS_CLOSE, SYS_FSYNC, SYS_FTRUNCATE,
                    SYS_LSEEK, SEEK_SET, SEEK_CUR, SEEK_END,
                    SYS_OPEN, SYS_READ, SYS_WRITE, SYS_UNLINK};

struct SchemeInner {
    context: *mut Context,
    next_id: Cell<usize>,
    todo: Intex<BTreeMap<usize, (usize, usize, usize, usize)>>,
    done: Intex<BTreeMap<usize, (usize, usize, usize, usize)>>,
}

impl SchemeInner {
    fn new(context: *mut Context) -> SchemeInner {
        SchemeInner {
            context: context,
            next_id: Cell::new(1),
            todo: Intex::new(BTreeMap::new()),
            done: Intex::new(BTreeMap::new()),
        }
    }

    fn call(inner: &Weak<SchemeInner>, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        let id;
        if let Some(scheme) = inner.upgrade() {
            id = scheme.next_id.get();

            //TODO: What should be done about collisions in self.todo or self.done?
            let mut next_id = id + 1;
            if next_id <= 0 {
                next_id = 1;
            }
            scheme.next_id.set(next_id);

            scheme.todo.lock().insert(id, (a, b, c, d));
        } else {
            return Err(Error::new(EBADF));
        }

        loop {
            if let Some(scheme) = inner.upgrade() {
                if let Some(regs) = scheme.done.lock().remove(&id) {
                    return Error::demux(regs.0);
                }
            } else {
                return Err(Error::new(EBADF));
            }

            unsafe { context_switch(false) } ;
        }
    }
}

pub struct SchemeResource {
    inner: Weak<SchemeInner>,
    file_id: usize,
}

impl SchemeResource {
    fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        SchemeInner::call(&self.inner, a, b, c, d)
    }
}

impl Resource for SchemeResource {
    /// Duplicate the resource
    fn dup(&self) -> Result<Box<Resource>> {
        Err(Error::new(EBADF))
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        Url::new()
    }

    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(physical_address) = unsafe { current.translate(buf.as_mut_ptr() as usize) } {
                let offset = physical_address % 4096;

                let mut virtual_address = 0;
                if let Some(scheme) = self.inner.upgrade() {
                    unsafe {
                        virtual_address = (*scheme.context).next_mem();
                        (*(*scheme.context).memory.get()).push(ContextMemory {
                            physical_address: physical_address - offset,
                            virtual_address: virtual_address,
                            virtual_size: buf.len() + offset,
                            writeable: true,
                            allocated: false,
                        });
                    }
                }

                if virtual_address > 0 {
                    let result = self.call(SYS_READ, self.file_id, virtual_address + offset, buf.len());

                    if let Some(scheme) = self.inner.upgrade() {
                        unsafe {
                            if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                                mem.virtual_size = 0;
                            }
                            (*scheme.context).clean_mem();
                        }
                    }

                    result
                } else {
                    Err(Error::new(EBADF))
                }
            } else {
                Err(Error::new(EFAULT))
            }
        } else {
            Err(Error::new(ESRCH))
        }
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(physical_address) = unsafe { current.translate(buf.as_ptr() as usize) } {
                let offset = physical_address % 4096;

                let mut virtual_address = 0;
                if let Some(scheme) = self.inner.upgrade() {
                    unsafe {
                        virtual_address = (*scheme.context).next_mem();
                        (*(*scheme.context).memory.get()).push(ContextMemory {
                            physical_address: physical_address - offset,
                            virtual_address: virtual_address,
                            virtual_size: buf.len() + offset,
                            writeable: false,
                            allocated: false,
                        });
                    }
                }

                if virtual_address > 0 {
                    let result = self.call(SYS_WRITE, self.file_id, virtual_address + offset, buf.len());

                    if let Some(scheme) = self.inner.upgrade() {
                        unsafe {
                            if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                                mem.virtual_size = 0;
                            }
                            (*scheme.context).clean_mem();
                        }
                    }

                    result
                } else {
                    Err(Error::new(EBADF))
                }
            } else {
                Err(Error::new(EFAULT))
            }
        } else {
            Err(Error::new(ESRCH))
        }
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        let (whence, offset) = match pos {
            ResourceSeek::Start(offset) => (SEEK_SET, offset as usize),
            ResourceSeek::Current(offset) => (SEEK_CUR, offset as usize),
            ResourceSeek::End(offset) => (SEEK_END, offset as usize)
        };

        self.call(SYS_LSEEK, self.file_id, offset, whence)
    }

    /// Sync the resource
    fn sync(&mut self) -> Result<()> {
        self.call(SYS_FSYNC, self.file_id, 0, 0).and(Ok(()))
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        self.call(SYS_FTRUNCATE, self.file_id, len, 0).and(Ok(()))
    }
}

impl Drop for SchemeResource {
    fn drop(&mut self) {
        let _ = self.call(SYS_CLOSE, self.file_id, 0, 0);
    }
}

pub struct SchemeServerResource {
    path: String,
    inner: Arc<SchemeInner>,
}

impl Resource for SchemeServerResource {
    /// Duplicate the resource
    fn dup(&self) -> Result<Box<Resource>> {
        Ok(box SchemeServerResource {
            path: self.path.clone(),
            inner: self.inner.clone()
        })
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        Url::from_str(&self.path)
    }

    // TODO: Make use of Write and Read trait
    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        if buf.len() == size_of::<Packet>() {
            let packet_ptr: *mut Packet = buf.as_mut_ptr() as *mut Packet;
            let packet = unsafe { &mut *packet_ptr };
            loop {
                let mut todo = self.inner.todo.lock();

                packet.id = if let Some(id) = todo.keys().next() {
                    *id
                } else {
                    0
                };

                if packet.id > 0 {
                    if let Some(regs) = todo.remove(&packet.id) {
                        packet.a = regs.0;
                        packet.b = regs.1;
                        packet.c = regs.2;
                        packet.d = regs.3;
                        return Ok(size_of::<Packet>())
                    }
                }

                unsafe { context_switch(false) };
            }
        } else {
            return Err(Error::new(EINVAL))
        }
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        if buf.len() == size_of::<Packet>() {
            let packet_ptr: *const Packet = buf.as_ptr() as *const Packet;
            let packet = unsafe { & *packet_ptr };
            self.inner.done.lock().insert(packet.id, (packet.a, packet.b, packet.c, packet.d));
            return Ok(size_of::<Packet>())
        } else {
            return Err(Error::new(EINVAL))
        }
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        Err(Error::new(ESPIPE))
    }

    /// Sync the resource
    fn sync(&mut self) -> Result<()> {
        Err(Error::new(EINVAL))
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        Err(Error::new(EINVAL))
    }
}

/// Scheme has to be wrapped
pub struct Scheme {
    name: String,
    inner: Weak<SchemeInner>
}

impl Scheme {
    pub fn new(name: String) -> Result<(Box<Scheme>, Box<Resource>)> {
        if let Some(context) = ::env().contexts.lock().current_mut() {
            let server = box SchemeServerResource {
                path: ":".to_string() + &name,
                inner: Arc::new(SchemeInner::new(context.deref_mut()))
            };
            let scheme = box Scheme {
                name: name,
                inner: Arc::downgrade(&server.inner)
            };
            Ok((scheme, server))
        } else {
            Err(Error::new(ESRCH))
        }
    }

    fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        SchemeInner::call(&self.inner, a, b, c, d)
    }
}

impl KScheme for Scheme {
    fn on_irq(&mut self, irq: u8) {

    }

    fn on_poll(&mut self) {

    }

    fn scheme(&self) -> &str {
        &self.name
    }

    fn open(&mut self, url: &Url, flags: usize) -> Result<Box<Resource>> {
        let c_str = url.string.clone() + "\0";

        let physical_address = c_str.as_ptr() as usize;

        let mut virtual_address = 0;
        if let Some(scheme) = self.inner.upgrade() {
            unsafe {
                virtual_address = (*scheme.context).next_mem();
                (*(*scheme.context).memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: c_str.len(),
                    writeable: false,
                    allocated: false,
                });
            }
        }

        if virtual_address > 0 {
            let result = self.call(SYS_OPEN, virtual_address, flags, 0);

            if let Some(scheme) = self.inner.upgrade() {
                unsafe {
                    if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                        mem.virtual_size = 0;
                    }
                    (*scheme.context).clean_mem();
                }
            }

            match result {
                Ok(file_id) => Ok(box SchemeResource {
                    inner: self.inner.clone(),
                    file_id: file_id,
                }),
                Err(err) => Err(err)
            }
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn unlink(&mut self, url: &Url) -> Result<()> {
        let c_str = url.string.clone() + "\0";

        let physical_address = c_str.as_ptr() as usize;

        let mut virtual_address = 0;
        if let Some(scheme) = self.inner.upgrade() {
            unsafe {
                virtual_address = (*scheme.context).next_mem();
                (*(*scheme.context).memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: c_str.len(),
                    writeable: false,
                    allocated: false,
                });
            }
        }

        if virtual_address > 0 {
            let result = self.call(SYS_UNLINK, virtual_address, 0, 0);

            if let Some(scheme) = self.inner.upgrade() {
                unsafe {
                    if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                        mem.virtual_size = 0;
                    }
                    (*scheme.context).clean_mem();
                }
            }

            result.and(Ok(()))
        } else {
            Err(Error::new(EBADF))
        }
    }
}
<commit_msg>Cleanup schemes when dropped<commit_after>use alloc::arc::{Arc, Weak};
use alloc::boxed::Box;

use collections::{BTreeMap, String};
use collections::string::ToString;

use core::cell::Cell;
use core::mem::size_of;
use core::ops::DerefMut;

use scheduler::context::{context_switch, Context, ContextMemory};

use schemes::{Result, Resource, ResourceSeek, KScheme, Url};

use sync::Intex;

use system::error::{Error, EBADF, EFAULT, EINVAL, ENOENT, ESPIPE, ESRCH};
use system::scheme::Packet;
use system::syscall::{SYS_CLOSE, SYS_FSYNC, SYS_FTRUNCATE,
                    SYS_LSEEK, SEEK_SET, SEEK_CUR, SEEK_END,
                    SYS_OPEN, SYS_READ, SYS_WRITE, SYS_UNLINK};

struct SchemeInner {
    name: String,
    context: *mut Context,
    next_id: Cell<usize>,
    todo: Intex<BTreeMap<usize, (usize, usize, usize, usize)>>,
    done: Intex<BTreeMap<usize, (usize, usize, usize, usize)>>,
}

impl SchemeInner {
    fn new(name: String, context: *mut Context) -> SchemeInner {
        SchemeInner {
            name: name,
            context: context,
            next_id: Cell::new(1),
            todo: Intex::new(BTreeMap::new()),
            done: Intex::new(BTreeMap::new()),
        }
    }

    fn call(inner: &Weak<SchemeInner>, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        let id;
        if let Some(scheme) = inner.upgrade() {
            id = scheme.next_id.get();

            //TODO: What should be done about collisions in self.todo or self.done?
            let mut next_id = id + 1;
            if next_id <= 0 {
                next_id = 1;
            }
            scheme.next_id.set(next_id);

            scheme.todo.lock().insert(id, (a, b, c, d));
        } else {
            return Err(Error::new(EBADF));
        }

        loop {
            if let Some(scheme) = inner.upgrade() {
                if let Some(regs) = scheme.done.lock().remove(&id) {
                    return Error::demux(regs.0);
                }
            } else {
                return Err(Error::new(EBADF));
            }

            unsafe { context_switch(false) } ;
        }
    }
}

impl Drop for SchemeInner {
    fn drop(&mut self) {
        let mut schemes = ::env().schemes.lock();

        let mut i = 0;
        while i < schemes.len() {
            let mut remove = false;
            if let Some(scheme) = schemes.get(i){
                if scheme.scheme() == self.name {
                    remove = true;
                }
            }

            if remove {
                schemes.remove(i);
            } else {
                i += 1;
            }
        }
    }
}

pub struct SchemeResource {
    inner: Weak<SchemeInner>,
    file_id: usize,
}

impl SchemeResource {
    fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        SchemeInner::call(&self.inner, a, b, c, d)
    }
}

impl Resource for SchemeResource {
    /// Duplicate the resource
    fn dup(&self) -> Result<Box<Resource>> {
        Err(Error::new(EBADF))
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        Url::new()
    }

    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(physical_address) = unsafe { current.translate(buf.as_mut_ptr() as usize) } {
                let offset = physical_address % 4096;

                let mut virtual_address = 0;
                if let Some(scheme) = self.inner.upgrade() {
                    unsafe {
                        virtual_address = (*scheme.context).next_mem();
                        (*(*scheme.context).memory.get()).push(ContextMemory {
                            physical_address: physical_address - offset,
                            virtual_address: virtual_address,
                            virtual_size: buf.len() + offset,
                            writeable: true,
                            allocated: false,
                        });
                    }
                }

                if virtual_address > 0 {
                    let result = self.call(SYS_READ, self.file_id, virtual_address + offset, buf.len());

                    if let Some(scheme) = self.inner.upgrade() {
                        unsafe {
                            if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                                mem.virtual_size = 0;
                            }
                            (*scheme.context).clean_mem();
                        }
                    }

                    result
                } else {
                    Err(Error::new(EBADF))
                }
            } else {
                Err(Error::new(EFAULT))
            }
        } else {
            Err(Error::new(ESRCH))
        }
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(physical_address) = unsafe { current.translate(buf.as_ptr() as usize) } {
                let offset = physical_address % 4096;

                let mut virtual_address = 0;
                if let Some(scheme) = self.inner.upgrade() {
                    unsafe {
                        virtual_address = (*scheme.context).next_mem();
                        (*(*scheme.context).memory.get()).push(ContextMemory {
                            physical_address: physical_address - offset,
                            virtual_address: virtual_address,
                            virtual_size: buf.len() + offset,
                            writeable: false,
                            allocated: false,
                        });
                    }
                }

                if virtual_address > 0 {
                    let result = self.call(SYS_WRITE, self.file_id, virtual_address + offset, buf.len());

                    if let Some(scheme) = self.inner.upgrade() {
                        unsafe {
                            if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                                mem.virtual_size = 0;
                            }
                            (*scheme.context).clean_mem();
                        }
                    }

                    result
                } else {
                    Err(Error::new(EBADF))
                }
            } else {
                Err(Error::new(EFAULT))
            }
        } else {
            Err(Error::new(ESRCH))
        }
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        let (whence, offset) = match pos {
            ResourceSeek::Start(offset) => (SEEK_SET, offset as usize),
            ResourceSeek::Current(offset) => (SEEK_CUR, offset as usize),
            ResourceSeek::End(offset) => (SEEK_END, offset as usize)
        };

        self.call(SYS_LSEEK, self.file_id, offset, whence)
    }

    /// Sync the resource
    fn sync(&mut self) -> Result<()> {
        self.call(SYS_FSYNC, self.file_id, 0, 0).and(Ok(()))
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        self.call(SYS_FTRUNCATE, self.file_id, len, 0).and(Ok(()))
    }
}

impl Drop for SchemeResource {
    fn drop(&mut self) {
        let _ = self.call(SYS_CLOSE, self.file_id, 0, 0);
    }
}

pub struct SchemeServerResource {
    inner: Arc<SchemeInner>,
}

impl Resource for SchemeServerResource {
    /// Duplicate the resource
    fn dup(&self) -> Result<Box<Resource>> {
        Ok(box SchemeServerResource {
            inner: self.inner.clone()
        })
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        Url::from_string(":".to_string() + &self.inner.name)
    }

    // TODO: Make use of Write and Read trait
    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        if buf.len() == size_of::<Packet>() {
            let packet_ptr: *mut Packet = buf.as_mut_ptr() as *mut Packet;
            let packet = unsafe { &mut *packet_ptr };
            loop {
                let mut todo = self.inner.todo.lock();

                packet.id = if let Some(id) = todo.keys().next() {
                    *id
                } else {
                    0
                };

                if packet.id > 0 {
                    if let Some(regs) = todo.remove(&packet.id) {
                        packet.a = regs.0;
                        packet.b = regs.1;
                        packet.c = regs.2;
                        packet.d = regs.3;
                        return Ok(size_of::<Packet>())
                    }
                }

                unsafe { context_switch(false) };
            }
        } else {
            return Err(Error::new(EINVAL))
        }
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        if buf.len() == size_of::<Packet>() {
            let packet_ptr: *const Packet = buf.as_ptr() as *const Packet;
            let packet = unsafe { & *packet_ptr };
            self.inner.done.lock().insert(packet.id, (packet.a, packet.b, packet.c, packet.d));
            return Ok(size_of::<Packet>())
        } else {
            return Err(Error::new(EINVAL))
        }
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        Err(Error::new(ESPIPE))
    }

    /// Sync the resource
    fn sync(&mut self) -> Result<()> {
        Err(Error::new(EINVAL))
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        Err(Error::new(EINVAL))
    }
}

/// Scheme has to be wrapped
pub struct Scheme {
    name: String,
    inner: Weak<SchemeInner>
}

impl Scheme {
    pub fn new(name: String) -> Result<(Box<Scheme>, Box<Resource>)> {
        if let Some(context) = ::env().contexts.lock().current_mut() {
            let server = box SchemeServerResource {
                inner: Arc::new(SchemeInner::new(name.clone(), context.deref_mut()))
            };
            let scheme = box Scheme {
                name: name,
                inner: Arc::downgrade(&server.inner)
            };
            Ok((scheme, server))
        } else {
            Err(Error::new(ESRCH))
        }
    }

    fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
        SchemeInner::call(&self.inner, a, b, c, d)
    }
}

impl KScheme for Scheme {
    fn on_irq(&mut self, irq: u8) {

    }

    fn on_poll(&mut self) {

    }

    fn scheme(&self) -> &str {
        &self.name
    }

    fn open(&mut self, url: &Url, flags: usize) -> Result<Box<Resource>> {
        let c_str = url.string.clone() + "\0";

        let physical_address = c_str.as_ptr() as usize;

        let mut virtual_address = 0;
        if let Some(scheme) = self.inner.upgrade() {
            unsafe {
                virtual_address = (*scheme.context).next_mem();
                (*(*scheme.context).memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: c_str.len(),
                    writeable: false,
                    allocated: false,
                });
            }
        }

        if virtual_address > 0 {
            let result = self.call(SYS_OPEN, virtual_address, flags, 0);

            if let Some(scheme) = self.inner.upgrade() {
                unsafe {
                    if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                        mem.virtual_size = 0;
                    }
                    (*scheme.context).clean_mem();
                }
            }

            match result {
                Ok(file_id) => Ok(box SchemeResource {
                    inner: self.inner.clone(),
                    file_id: file_id,
                }),
                Err(err) => Err(err)
            }
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn unlink(&mut self, url: &Url) -> Result<()> {
        let c_str = url.string.clone() + "\0";

        let physical_address = c_str.as_ptr() as usize;

        let mut virtual_address = 0;
        if let Some(scheme) = self.inner.upgrade() {
            unsafe {
                virtual_address = (*scheme.context).next_mem();
                (*(*scheme.context).memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: c_str.len(),
                    writeable: false,
                    allocated: false,
                });
            }
        }

        if virtual_address > 0 {
            let result = self.call(SYS_UNLINK, virtual_address, 0, 0);

            if let Some(scheme) = self.inner.upgrade() {
                unsafe {
                    if let Some(mut mem) = (*scheme.context).get_mem_mut(virtual_address) {
                        mem.virtual_size = 0;
                    }
                    (*scheme.context).clean_mem();
                }
            }

            result.and(Ok(()))
        } else {
            Err(Error::new(EBADF))
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>add liquid/mod.rs<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Andres Vahter (andres.vahter@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#[allow(non_camel_case_types)]
#[allow(non_upper_case_globals)]
pub mod ffiliquid;
pub mod firfilt;
pub mod msresamp;
pub mod freqdem;

pub type Complex32 = ffiliquid::liquid_float_complex;
pub type Complex64 = ffiliquid::liquid_double_complex;
<|endoftext|>


<commit_before><commit_msg>Add Arc test, triggering an unusual bug.<commit_after>//! This test is a more subtle one. It is one which can hit thread destructors unexpectedly.

extern crate ralloc;

use std::sync::Arc;
use std::thread;

fn main() {
    let numbers: Vec<_> = (0..100).collect();
    let shared_numbers = Arc::new(numbers);

    for _ in 0..10 {
        let child_numbers = shared_numbers.clone();

        thread::spawn(move || {
            let local_numbers = &child_numbers[..];

            // Work with the local numbers
        });
    }
}
<|endoftext|>


<commit_before><commit_msg>test(*): add failing test<commit_after>
extern crate readext;

use std::io::{Read,Cursor};
use readext::ReadExt;

#[test]
fn test () {
    let bytes = b"hello";
    let mut input = Cursor::new(bytes);
    let s = input.read_into_string();
    assert_eq!(s, "hello");
}
<|endoftext|>


<commit_before><commit_msg>Add a can't-nest-rw-arcs test case (xfailed, #3177)<commit_after>// xfail-test
// error-pattern: instantiating a type parameter with an incompatible type
use std;
import std::arc::rw_arc;

fn main() {
    let arc1  = ~rw_arc(true);
    let _arc2 = ~rw_arc(arc1);
}
<|endoftext|>


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

#![feature(test)]

extern crate test;

extern crate futures;
extern crate tokio_core;
extern crate redis_async;

use test::Bencher;

use futures::Future;

use tokio_core::reactor::Core;

use redis_async::client;

#[bench]
fn bench_simple_getsetdel(b: &mut Bencher) {
    let mut core = Core::new().unwrap();
    let addr = "127.0.0.1:6379".parse().unwrap();

    let connection = client::paired_connect(&addr, &core.handle());
    let connection = core.run(connection).unwrap();

    b.iter(|| {
               let set = connection.send(["SET", "test_key", "42"].as_ref());
               let get = connection.send(["GET", "test_key"].as_ref());
               let del = connection.send(["DEL", "test_key"].as_ref());
               let get_set = get.join(del);
               let (_, _) = core.run(get_set).unwrap();
           });
}

#[bench]
fn bench_big_pipeline(b: &mut Bencher) {
    let mut core = Core::new().unwrap();
    let addr = "127.0.0.1:6379".parse().unwrap();

    let connection = client::paired_connect(&addr, &core.handle());
    let connection = core.run(connection).unwrap();

    let data_size = 1000;

    b.iter(|| {
        for x in 0..data_size {
            let test_key = format!("test_{}", x);
            connection.send(["SET", &test_key, &x.to_string()].as_ref());
        }
        let mut gets = Vec::with_capacity(data_size);
        for x in 0..data_size {
            let test_key = format!("test_{}", x);
            gets.push(connection.send(["GET", &test_key].as_ref()));
        }
        let last_get = gets.remove(999);
        let _ = core.run(last_get);
    });
}<|endoftext|>


<commit_before><commit_msg>Remove unnecessary ToExpr implementations<commit_after><|endoftext|>


<commit_before><commit_msg>Update simulation to test cuboid-cuboid interaction<commit_after><|endoftext|>


<commit_before><commit_msg>altered how commands are dealt with; updated to new process::Command from old_io<commit_after><|endoftext|>


<commit_before><commit_msg>store tree in memory and make max node number and max depth configurable<commit_after><|endoftext|>


<commit_before><commit_msg>Get started with implementing menus<commit_after>extern crate orbclient;

use orbclient::BmpFile;

use super::{CloneCell, Color, CopyCell, Event, Place, Point, Rect, Renderer, Widget, Window};
use super::callback::Click;

pub struct Menu {
    rect: Rect,
    fg: Color,
    actions: Vec<Action>,
}

pub struct Action {
    rect: CopyCell<Rect>,
    text: CloneCell<String>,
    icon: Option<BmpFile>,
    bg_up: Color,
    bg_down: Color,
    click_callback: Option<Arc<Fn()>>,
    pressed: CopyCell<bool>,
}

impl Menu {
    pub fn new() -> Self {
        Menu {
            rect: Rect::default(),
            fg: Color::rgb(0, 0, 0),
            actions: Vec::with_capacity(1),
        }
    }

    pub fn add_action(&mut self, name: &str, icon: Option<BmpFile>) {
        self.actions.insert(Action::new(name), icon);
    }
}

impl Action {
    pub fn new(text: &str) -> Self {
        Action {
            rect: Rect::default(),
            text: CloneCell::new(name.to_owned()),
            icon: None,
            bg_up: Color::rgb(220, 222, 227),
            bg_down: Color::rgb(203, 205, 210),
            click_callback: None,
            pressed: CopyCell::new(false),
        }
    }

    pub fn add_icon(mut self, icon: BmpFile) -> Self {
        self.icon = Some(icon);
        self
    }
}
<|endoftext|>


<commit_before><commit_msg>Implement bonus attacks<commit_after><|endoftext|>


<commit_before><commit_msg>test case for method macros<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(macro_rules)]

struct A;

macro_rules! make_thirteen_method {() => (pub fn thirteen(&self)->int {13})}
impl A { make_thirteen_method!() }

fn main() {
    assert_eq!(A.thirteen(),13);
}

<|endoftext|>


<commit_before><commit_msg>readd step counter for agent<commit_after><|endoftext|>


<commit_before><commit_msg>Factorization attempt<commit_after><|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Panic support for libcore
//!
//! The core library cannot define panicking, but it does *declare* panicking. This
//! means that the functions inside of libcore are allowed to panic, but to be
//! useful an upstream crate must define panicking for libcore to use. The current
//! interface for panicking is:
//!
//! ```ignore
//! fn panic_impl(fmt: fmt::Arguments, &(&'static str, uint)) -> !;
//! ```
//!
//! This definition allows for panicking with any general message, but it does not
//! allow for failing with a `Box<Any>` value. The reason for this is that libcore
//! is not allowed to allocate.
//!
//! This module contains a few other panicking functions, but these are just the
//! necessary lang items for the compiler. All panics are funneled through this
//! one function. Currently, the actual symbol is declared in the standard
//! library, but the location of this may change over time.

#![allow(dead_code, missing_docs)]

use fmt;

#[cold] #[inline(never)] // this is the slow path, always
#[lang="panic"]
pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
    let (expr, file, line) = *expr_file_line;
    panic_fmt(format_args!("{}", expr), &(file, line))
}

#[cold] #[inline(never)]
#[lang="panic_bounds_check"]
fn panic_bounds_check(file_line: &(&'static str, u32),
                     index: usize, len: usize) -> ! {
    panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
                           len, index), file_line)
}

#[cold] #[inline(never)]
pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
    #[allow(improper_ctypes)]
    extern {
        #[lang = "panic_fmt"]
        fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: uint) -> !;
    }
    let (file, line) = *file_line;
    unsafe { panic_impl(fmt, file, line as uint) }
}
<commit_msg>Remove core::panicking::panic's dependence on str's Display::fmt impl<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Panic support for libcore
//!
//! The core library cannot define panicking, but it does *declare* panicking. This
//! means that the functions inside of libcore are allowed to panic, but to be
//! useful an upstream crate must define panicking for libcore to use. The current
//! interface for panicking is:
//!
//! ```ignore
//! fn panic_impl(fmt: fmt::Arguments, &(&'static str, uint)) -> !;
//! ```
//!
//! This definition allows for panicking with any general message, but it does not
//! allow for failing with a `Box<Any>` value. The reason for this is that libcore
//! is not allowed to allocate.
//!
//! This module contains a few other panicking functions, but these are just the
//! necessary lang items for the compiler. All panics are funneled through this
//! one function. Currently, the actual symbol is declared in the standard
//! library, but the location of this may change over time.

#![allow(dead_code, missing_docs)]

use fmt;

#[cold] #[inline(never)] // this is the slow path, always
#[lang="panic"]
pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
    // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
    // reduce size overhead. The format_args! macro uses str's Display trait to
    // write expr, which calls Formatter::pad, which must accommodate string
    // truncation and padding (even though none is used here). Using
    // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
    // output binary, saving up to a few kilobytes.
    let (expr, file, line) = *expr_file_line;
    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line))
}

#[cold] #[inline(never)]
#[lang="panic_bounds_check"]
fn panic_bounds_check(file_line: &(&'static str, u32),
                     index: usize, len: usize) -> ! {
    panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
                           len, index), file_line)
}

#[cold] #[inline(never)]
pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
    #[allow(improper_ctypes)]
    extern {
        #[lang = "panic_fmt"]
        fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: uint) -> !;
    }
    let (file, line) = *file_line;
    unsafe { panic_impl(fmt, file, line as uint) }
}
<|endoftext|>