<commit_before>use data::{NBT, NBTFile};

use byteorder::WriteBytesExt;

use std::io;
use std::io::Write;

/// Given an NBT file, write it to the writer in the pretty text format
pub fn write_file<W: Write>(w: &mut W, file: &NBTFile) -> io::Result<()> {
    write!(w, "{}", file.compression.to_str())?;
    write_tag(w, &file.root, -1, true)?;

    Ok(())
}

fn write_tag<W: Write>(w: &mut W,
                       tag: &NBT,
                       indent: i8,
                       compound: bool)
                       -> io::Result<()> {

    match tag {
        &NBT::End => (),
        &NBT::Byte(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::Short(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::Int(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::Long(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::Float(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::Double(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::ByteArray(ref x) => {
            writeln!(w, " {}", x.len())?;
            for val in x {
                write_indent(w, indent + 1)?;
                writeln!(w, "{}", val)?;
            }
        },
        &NBT::String(ref x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w,
                     r#""{}""#,
                     /* Order is important here */
                     x.replace(r"\", r"\\").replace(r#"""#, r#"\""#))?
        },
        &NBT::List(ref x) => {
            /* If the list has length 0, then it just defaults to type "End". */
            let tag_type = if x.len() > 0 {
                x[0].type_string()
            } else {
                "End"
            };
            writeln!(w, " {} {}", tag_type, x.len())?;
            for val in x {
                match val {
                    &NBT::Compound(..) => (),
                    _ => write_indent(w, indent + 1)?,
                }
                write_tag(w, val, indent + 1, false)?;
            }
        },
        &NBT::Compound(ref x) => {
            if compound {
                writeln!(w, "")?;
            }
            for &(ref key, ref val) in x {
                write_indent(w, indent + 1)?;
                w.write_all(val.type_string().as_bytes())?;
                write!(w,
                       r#" "{}""#,
                       /* Order is important here */
                       key.replace(r"\", r"\\").replace(r#"""#, r#"\""#))?;
                write_tag(w, val, indent + 1, true)?;
            }

            write_indent(w, indent + 1)?;
            writeln!(w, "End")?;
        },
        &NBT::IntArray(ref x) => {
            writeln!(w, " {}", x.len())?;
            for val in x {
                write_indent(w, indent + 1)?;
                writeln!(w, "{}", val)?;
            }
        },
    }

    Ok(())
}

fn write_indent<W: Write>(w: &mut W, indent: i8) -> io::Result<()> {
    for _ in 0..indent {
        /* 9 = tab character */
        w.write_u8(9)?;
    }
    Ok(())
}
<commit_msg>Use u64 not i8 to count indent<commit_after>use data::{NBT, NBTFile};

use byteorder::WriteBytesExt;

use std::io;
use std::io::Write;

/// Given an NBT file, write it to the writer in the pretty text format
pub fn write_file<W: Write>(w: &mut W, file: &NBTFile) -> io::Result<()> {
    write!(w, "{}", file.compression.to_str())?;
    write_tag(w, &file.root, 0, true)?;

    Ok(())
}

fn write_tag<W: Write>(w: &mut W,
                       tag: &NBT,
                       indent: u64,
                       compound: bool)
                       -> io::Result<()> {

    match tag {
        &NBT::End => (),
        &NBT::Byte(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::Short(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::Int(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::Long(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::Float(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::Double(x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w, "{}", x)?;
        },
        &NBT::ByteArray(ref x) => {
            writeln!(w, " {}", x.len())?;
            for val in x {
                write_indent(w, indent)?;
                writeln!(w, "{}", val)?;
            }
        },
        &NBT::String(ref x) => {
            if compound {
                write!(w, " ")?;
            }
            writeln!(w,
                     r#""{}""#,
                     /* Order is important here */
                     x.replace(r"\", r"\\").replace(r#"""#, r#"\""#))?
        },
        &NBT::List(ref x) => {
            /* If the list has length 0, then it just defaults to type "End". */
            let tag_type = if x.len() > 0 {
                x[0].type_string()
            } else {
                "End"
            };
            writeln!(w, " {} {}", tag_type, x.len())?;
            for val in x {
                match val {
                    &NBT::Compound(..) => (),
                    _ => write_indent(w, indent)?,
                }
                write_tag(w, val, indent + 1, false)?;
            }
        },
        &NBT::Compound(ref x) => {
            if compound {
                writeln!(w, "")?;
            }
            for &(ref key, ref val) in x {
                write_indent(w, indent)?;
                w.write_all(val.type_string().as_bytes())?;
                write!(w,
                       r#" "{}""#,
                       /* Order is important here */
                       key.replace(r"\", r"\\").replace(r#"""#, r#"\""#))?;
                write_tag(w, val, indent + 1, true)?;
            }

            write_indent(w, indent)?;
            writeln!(w, "End")?;
        },
        &NBT::IntArray(ref x) => {
            writeln!(w, " {}", x.len())?;
            for val in x {
                write_indent(w, indent)?;
                writeln!(w, "{}", val)?;
            }
        },
    }

    Ok(())
}

fn write_indent<W: Write>(w: &mut W, indent: u64) -> io::Result<()> {
    for _ in 0..indent {
        /* 9 = tab character */
        w.write_u8(9)?;
    }
    Ok(())
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate futures;
#[macro_use]
extern crate serde_derive;

extern crate gluon;
#[macro_use]
extern crate gluon_vm;

use futures::future::lazy;
use futures::{Future, IntoFuture};

use gluon::base::types::{Alias, ArcType, Type};
use gluon::import::{add_extern_module, Import};
use gluon::vm::api::de::De;
use gluon::vm::api::{FunctionRef, FutureResult, OpaqueValue, Userdata, VmType, IO};
use gluon::vm::thread::{RootedThread, Thread, Traverseable};
use gluon::vm::types::VmInt;
use gluon::vm::{Error, ExternModule};
use gluon::Compiler;

fn load_script(vm: &Thread, filename: &str, input: &str) -> ::gluon::Result<()> {
    Compiler::new().load_script(vm, filename, input)
}

fn make_vm() -> RootedThread {
    let vm = ::gluon::new_vm();
    let import = vm.get_macros().get("import");
    import
        .as_ref()
        .and_then(|import| import.downcast_ref::<Import>())
        .expect("Import macro")
        .add_path("..");
    vm
}

#[test]
fn call_function() {
    let _ = ::env_logger::try_init();
    let add10 = r"
        let add10 : Int -> Int = \x -> x #Int+ 10 in add10
    ";
    let mul = r"
        let mul : Float -> Float -> Float = \x y -> x #Float* y in mul
    ";
    let mut vm = make_vm();
    load_script(&mut vm, "add10", &add10).unwrap_or_else(|err| panic!("{}", err));
    load_script(&mut vm, "mul", &mul).unwrap_or_else(|err| panic!("{}", err));
    {
        let mut f: FunctionRef<fn(VmInt) -> VmInt> = vm.get_global("add10").unwrap();
        let result = f.call(2).unwrap();
        assert_eq!(result, 12);
    }
    let mut f: FunctionRef<fn(f64, f64) -> f64> = vm.get_global("mul").unwrap();
    let result = f.call(4., 5.).unwrap();
    assert_eq!(result, 20.);
}

#[test]
fn root_data() {
    let _ = ::env_logger::try_init();

    #[derive(Debug)]
    struct Test(VmInt);
    impl Userdata for Test {}
    impl Traverseable for Test {}
    impl VmType for Test {
        type Type = Test;
    }

    let expr = r#"
        let test = import! test
        \x -> test x 1
    "#;
    let vm = make_vm();
    fn test(r: OpaqueValue<RootedThread, Test>, i: VmInt) -> VmInt {
        r.0 + i
    }
    vm.register_type::<Test>("Test", &[])
        .unwrap_or_else(|_| panic!("Could not add type"));

    add_extern_module(&vm, "test", |thread| {
        ExternModule::new(thread, primitive!(2, test))
    });

    load_script(&vm, "script_fn", expr).unwrap_or_else(|err| panic!("{}", err));
    let mut script_fn: FunctionRef<fn(Test) -> VmInt> = vm.get_global("script_fn").unwrap();
    let result = script_fn.call(Test(123)).unwrap();
    assert_eq!(result, 124);
}

#[test]
fn root_string() {
    let _ = ::env_logger::try_init();

    let expr = r#"
        let test = import! test
        test "hello"
    "#;
    fn test(s: OpaqueValue<&Thread, str>) -> String {
        let mut result = String::from(&s[..]);
        result.push_str(" world");
        result
    }

    let vm = make_vm();
    add_extern_module(&vm, "test", |thread| {
        ExternModule::new(thread, primitive!(1, test))
    });

    let result = Compiler::new()
        .run_expr::<String>(&vm, "<top>", expr)
        .unwrap();
    let expected = ("hello world".to_string(), Type::string());

    assert_eq!(result, expected);
}

#[test]
fn array() {
    let _ = ::env_logger::try_init();

    let expr = r#"
        let sum_bytes = import! sum_bytes
        sum_bytes [100b, 42b, 3b, 15b]
    "#;
    fn sum_bytes(s: &[u8]) -> u8 {
        s.iter().fold(0, |acc, b| acc + b)
    }

    let vm = make_vm();
    add_extern_module(&vm, "sum_bytes", |thread| {
        ExternModule::new(thread, primitive!(1, sum_bytes))
    });

    let result = Compiler::new()
        .run_expr::<u8>(&vm, "<top>", expr)
        .unwrap_or_else(|err| panic!("{}", err));
    let expected = (160, Type::byte());

    assert_eq!(result, expected);
}

#[test]
fn return_finished_future() {
    let _ = ::env_logger::try_init();

    fn add(x: i32, y: i32) -> FutureResult<impl Future<Item = i32, Error = Error>> {
        FutureResult(Ok(x + y).into_future())
    }

    let expr = r#"
        let add = import! add
        add 1 2
    "#;

    let vm = make_vm();
    add_extern_module(&vm, "add", |thread| {
        ExternModule::new(thread, primitive!(2, add))
    });

    let result = Compiler::new()
        .run_expr::<i32>(&vm, "<top>", expr)
        .unwrap_or_else(|err| panic!("{}", err));
    let expected = (3, Type::int());

    assert_eq!(result, expected);
}

fn poll_n(s: String) -> FutureResult<impl Future<Item = IO<String>, Error = Error>> {
    use futures::sync::oneshot::channel;
    use std::thread::spawn;

    let (ping_c, ping_p) = channel();
    let (pong_c, pong_p) = channel();
    spawn(move || {
        ping_p.wait().expect("wait");
        pong_c.send(s).expect("send");
    });
    FutureResult(
        lazy(move || {
            ping_c.send(()).unwrap();
            Ok(())
        }).and_then(|_| {
            pong_p
                .map(IO::Value)
                .map_err(|err| Error::Message(format!("{}", err)))
        }),
    )
}

#[test]
fn return_delayed_future_simple() {
    let _ = ::env_logger::try_init();

    let expr = r#"
        let poll_n = import! poll_n
        poll_n "test"
    "#;

    let vm = make_vm();
    add_extern_module(&vm, "poll_n", |thread| {
        ExternModule::new(thread, primitive!(1, poll_n))
    });

    let (result, _) = Compiler::new()
        .run_io(true)
        .run_expr::<IO<String>>(&vm, "<top>", expr)
        .unwrap_or_else(|err| panic!("{}", err));
    let expected = IO::Value("test".to_string());

    assert_eq!(result, expected);
}

#[test]
fn return_delayed_future_in_catch() {
    let _ = ::env_logger::try_init();

    let expr = r#"
        let io = import! std.io
        let poll_n = import! poll_n
        io.catch (poll_n "test") (\_ -> io.applicative.wrap "error")
    "#;

    let vm = make_vm();
    add_extern_module(&vm, "poll_n", |thread| {
        ExternModule::new(thread, primitive!(1, poll_n))
    });

    let (result, _) = Compiler::new()
        .run_io(true)
        .run_expr::<IO<String>>(&vm, "<top>", expr)
        .unwrap_or_else(|err| panic!("{}", err));
    let expected = IO::Value("test".to_string());

    assert_eq!(result, expected);
}

#[test]
fn io_future() {
    use gluon_vm::api::IO;

    let _ = ::env_logger::try_init();

    fn test(_: ()) -> FutureResult<impl Future<Item = IO<i32>, Error = Error>> {
        FutureResult(Ok(IO::Value(123)).into_future())
    }

    let expr = r#"
        let test = import! test
        let { applicative, monad }  = import! std.io
        monad.flat_map (\x -> applicative.wrap (x + 1)) (test ())
    "#;

    let vm = make_vm();
    add_extern_module(&vm, "test", |thread| {
        ExternModule::new(thread, primitive!(1, test))
    });

    let result = Compiler::new()
        .run_io(true)
        .run_expr::<IO<i32>>(&vm, "<top>", expr)
        .unwrap_or_else(|err| panic!("{}", err));

    assert_eq!(result.0, IO::Value(124));
}

#[test]
fn generic_record_type() {
    use gluon::base::types::ArcType;
    use gluon::vm::api::generic::A;
    use gluon::vm::api::Generic;

    fn type_of<T: VmType>(thread: &Thread, _: &T) -> ArcType {
        T::make_forall_type(thread)
    }
    fn test(_: Generic<A>) {}

    let record = record! {
        test => primitive!(1, test)
    };
    assert_eq!(
        type_of(&make_vm(), &record).to_string(),
        "{ test : forall a . a -> () }"
    )
}

#[test]
fn tuples_start_at_0() {
    let thread = make_vm();
    assert_eq!(<(i32, f64)>::make_type(&thread).to_string(), "(Int, Float)");
    assert_eq!(
        <(i32, f64, String)>::make_type(&thread).to_string(),
        "(Int, Float, String)"
    );
}

#[test]
fn use_type_from_type_field() {
    let _ = ::env_logger::try_init();
    let vm = make_vm();

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Test {
        A(i32),
        B(String),
        C,
    }
    impl VmType for Test {
        type Type = Self;
        fn make_type(vm: &Thread) -> ArcType {
            if let Some(typ) = vm.get_type::<Self>() {
                return typ;
            }

            let (name, typ) = gluon::vm::api::typ::from_rust::<Self>(vm).unwrap();
            vm.register_type_as(
                name.clone(),
                Alias::new(name, typ),
                ::std::any::TypeId::of::<Self>(),
            ).unwrap()
        }
    }

    add_extern_module(&vm, "test_types", |vm| {
        ExternModule::new(vm, record!{ type Test => Test })
    });
    let text = r#"
        let { Test } = import! test_types
        B "abc"
    "#;
    let (De(actual), _) = Compiler::new()
        .run_expr::<De<Test>>(&vm, "test", text)
        .unwrap_or_else(|err| panic!("{}", err));
    assert_eq!(actual, Test::B("abc".to_string()));
}

#[test]
fn use_rust_created_record_as_polymorphic() {
    let _ = ::env_logger::try_init();
    let test = r"\x -> x.x";
    let mut vm = make_vm();
    load_script(&mut vm, "test", test).unwrap_or_else(|err| panic!("{}", err));

    field_decl! { x }
    type Test = record_type!{
        x => i32
    };

    let mut f: FunctionRef<fn(Test) -> VmInt> = vm.get_global("test").unwrap();
    let result = f.call(record_no_decl!{ x => 1 }).unwrap();
    assert_eq!(result, 1);
}
<commit_msg>Add test for getting a boxed value from gluon<commit_after>extern crate env_logger;
extern crate futures;
#[macro_use]
extern crate serde_derive;

extern crate gluon;
#[macro_use]
extern crate gluon_vm;

use futures::future::lazy;
use futures::{Future, IntoFuture};

use gluon::base::types::{Alias, ArcType, Type};
use gluon::import::{add_extern_module, Import};
use gluon::vm::api::de::De;
use gluon::vm::api::{FunctionRef, FutureResult, OpaqueValue, Userdata, VmType, IO};
use gluon::vm::thread::{RootedThread, Thread, Traverseable};
use gluon::vm::types::VmInt;
use gluon::vm::{Error, ExternModule};
use gluon::Compiler;

fn load_script(vm: &Thread, filename: &str, input: &str) -> ::gluon::Result<()> {
    Compiler::new().load_script(vm, filename, input)
}

fn make_vm() -> RootedThread {
    let vm = ::gluon::new_vm();
    let import = vm.get_macros().get("import");
    import
        .as_ref()
        .and_then(|import| import.downcast_ref::<Import>())
        .expect("Import macro")
        .add_path("..");
    vm
}

#[test]
fn call_function() {
    let _ = ::env_logger::try_init();
    let add10 = r"
        let add10 : Int -> Int = \x -> x #Int+ 10 in add10
    ";
    let mul = r"
        let mul : Float -> Float -> Float = \x y -> x #Float* y in mul
    ";
    let mut vm = make_vm();
    load_script(&mut vm, "add10", &add10).unwrap_or_else(|err| panic!("{}", err));
    load_script(&mut vm, "mul", &mul).unwrap_or_else(|err| panic!("{}", err));
    {
        let mut f: FunctionRef<fn(VmInt) -> VmInt> = vm.get_global("add10").unwrap();
        let result = f.call(2).unwrap();
        assert_eq!(result, 12);
    }
    let mut f: FunctionRef<fn(f64, f64) -> f64> = vm.get_global("mul").unwrap();
    let result = f.call(4., 5.).unwrap();
    assert_eq!(result, 20.);
}

#[test]
fn root_data() {
    let _ = ::env_logger::try_init();

    #[derive(Debug)]
    struct Test(VmInt);
    impl Userdata for Test {}
    impl Traverseable for Test {}
    impl VmType for Test {
        type Type = Test;
    }

    let expr = r#"
        let test = import! test
        \x -> test x 1
    "#;
    let vm = make_vm();
    fn test(r: OpaqueValue<RootedThread, Test>, i: VmInt) -> VmInt {
        r.0 + i
    }
    vm.register_type::<Test>("Test", &[])
        .unwrap_or_else(|_| panic!("Could not add type"));

    add_extern_module(&vm, "test", |thread| {
        ExternModule::new(thread, primitive!(2, test))
    });

    load_script(&vm, "script_fn", expr).unwrap_or_else(|err| panic!("{}", err));
    let mut script_fn: FunctionRef<fn(Test) -> VmInt> = vm.get_global("script_fn").unwrap();
    let result = script_fn.call(Test(123)).unwrap();
    assert_eq!(result, 124);
}

#[test]
fn root_string() {
    let _ = ::env_logger::try_init();

    let expr = r#"
        let test = import! test
        test "hello"
    "#;
    fn test(s: OpaqueValue<&Thread, str>) -> String {
        let mut result = String::from(&s[..]);
        result.push_str(" world");
        result
    }

    let vm = make_vm();
    add_extern_module(&vm, "test", |thread| {
        ExternModule::new(thread, primitive!(1, test))
    });

    let result = Compiler::new()
        .run_expr::<String>(&vm, "<top>", expr)
        .unwrap();
    let expected = ("hello world".to_string(), Type::string());

    assert_eq!(result, expected);
}

#[test]
fn array() {
    let _ = ::env_logger::try_init();

    let expr = r#"
        let sum_bytes = import! sum_bytes
        sum_bytes [100b, 42b, 3b, 15b]
    "#;
    fn sum_bytes(s: &[u8]) -> u8 {
        s.iter().fold(0, |acc, b| acc + b)
    }

    let vm = make_vm();
    add_extern_module(&vm, "sum_bytes", |thread| {
        ExternModule::new(thread, primitive!(1, sum_bytes))
    });

    let result = Compiler::new()
        .run_expr::<u8>(&vm, "<top>", expr)
        .unwrap_or_else(|err| panic!("{}", err));
    let expected = (160, Type::byte());

    assert_eq!(result, expected);
}

#[test]
fn return_finished_future() {
    let _ = ::env_logger::try_init();

    fn add(x: i32, y: i32) -> FutureResult<impl Future<Item = i32, Error = Error>> {
        FutureResult(Ok(x + y).into_future())
    }

    let expr = r#"
        let add = import! add
        add 1 2
    "#;

    let vm = make_vm();
    add_extern_module(&vm, "add", |thread| {
        ExternModule::new(thread, primitive!(2, add))
    });

    let result = Compiler::new()
        .run_expr::<i32>(&vm, "<top>", expr)
        .unwrap_or_else(|err| panic!("{}", err));
    let expected = (3, Type::int());

    assert_eq!(result, expected);
}

fn poll_n(s: String) -> FutureResult<impl Future<Item = IO<String>, Error = Error>> {
    use futures::sync::oneshot::channel;
    use std::thread::spawn;

    let (ping_c, ping_p) = channel();
    let (pong_c, pong_p) = channel();
    spawn(move || {
        ping_p.wait().expect("wait");
        pong_c.send(s).expect("send");
    });
    FutureResult(
        lazy(move || {
            ping_c.send(()).unwrap();
            Ok(())
        }).and_then(|_| {
            pong_p
                .map(IO::Value)
                .map_err(|err| Error::Message(format!("{}", err)))
        }),
    )
}

#[test]
fn return_delayed_future_simple() {
    let _ = ::env_logger::try_init();

    let expr = r#"
        let poll_n = import! poll_n
        poll_n "test"
    "#;

    let vm = make_vm();
    add_extern_module(&vm, "poll_n", |thread| {
        ExternModule::new(thread, primitive!(1, poll_n))
    });

    let (result, _) = Compiler::new()
        .run_io(true)
        .run_expr::<IO<String>>(&vm, "<top>", expr)
        .unwrap_or_else(|err| panic!("{}", err));
    let expected = IO::Value("test".to_string());

    assert_eq!(result, expected);
}

#[test]
fn return_delayed_future_in_catch() {
    let _ = ::env_logger::try_init();

    let expr = r#"
        let io = import! std.io
        let poll_n = import! poll_n
        io.catch (poll_n "test") (\_ -> io.applicative.wrap "error")
    "#;

    let vm = make_vm();
    add_extern_module(&vm, "poll_n", |thread| {
        ExternModule::new(thread, primitive!(1, poll_n))
    });

    let (result, _) = Compiler::new()
        .run_io(true)
        .run_expr::<IO<String>>(&vm, "<top>", expr)
        .unwrap_or_else(|err| panic!("{}", err));
    let expected = IO::Value("test".to_string());

    assert_eq!(result, expected);
}

#[test]
fn io_future() {
    use gluon_vm::api::IO;

    let _ = ::env_logger::try_init();

    fn test(_: ()) -> FutureResult<impl Future<Item = IO<i32>, Error = Error>> {
        FutureResult(Ok(IO::Value(123)).into_future())
    }

    let expr = r#"
        let test = import! test
        let { applicative, monad }  = import! std.io
        monad.flat_map (\x -> applicative.wrap (x + 1)) (test ())
    "#;

    let vm = make_vm();
    add_extern_module(&vm, "test", |thread| {
        ExternModule::new(thread, primitive!(1, test))
    });

    let result = Compiler::new()
        .run_io(true)
        .run_expr::<IO<i32>>(&vm, "<top>", expr)
        .unwrap_or_else(|err| panic!("{}", err));

    assert_eq!(result.0, IO::Value(124));
}

#[test]
fn generic_record_type() {
    use gluon::base::types::ArcType;
    use gluon::vm::api::generic::A;
    use gluon::vm::api::Generic;

    fn type_of<T: VmType>(thread: &Thread, _: &T) -> ArcType {
        T::make_forall_type(thread)
    }
    fn test(_: Generic<A>) {}

    let record = record! {
        test => primitive!(1, test)
    };
    assert_eq!(
        type_of(&make_vm(), &record).to_string(),
        "{ test : forall a . a -> () }"
    )
}

#[test]
fn tuples_start_at_0() {
    let thread = make_vm();
    assert_eq!(<(i32, f64)>::make_type(&thread).to_string(), "(Int, Float)");
    assert_eq!(
        <(i32, f64, String)>::make_type(&thread).to_string(),
        "(Int, Float, String)"
    );
}

#[test]
fn use_type_from_type_field() {
    let _ = ::env_logger::try_init();
    let vm = make_vm();

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Test {
        A(i32),
        B(String),
        C,
    }
    impl VmType for Test {
        type Type = Self;
        fn make_type(vm: &Thread) -> ArcType {
            if let Some(typ) = vm.get_type::<Self>() {
                return typ;
            }

            let (name, typ) = gluon::vm::api::typ::from_rust::<Self>(vm).unwrap();
            vm.register_type_as(
                name.clone(),
                Alias::new(name, typ),
                ::std::any::TypeId::of::<Self>(),
            ).unwrap()
        }
    }

    add_extern_module(&vm, "test_types", |vm| {
        ExternModule::new(vm, record!{ type Test => Test })
    });
    let text = r#"
        let { Test } = import! test_types
        B "abc"
    "#;
    let (De(actual), _) = Compiler::new()
        .run_expr::<De<Test>>(&vm, "test", text)
        .unwrap_or_else(|err| panic!("{}", err));
    assert_eq!(actual, Test::B("abc".to_string()));
}

#[test]
fn use_rust_created_record_as_polymorphic() {
    let _ = ::env_logger::try_init();
    let test = r"\x -> x.x";
    let mut vm = make_vm();
    load_script(&mut vm, "test", test).unwrap_or_else(|err| panic!("{}", err));

    field_decl! { x }
    type Test = record_type!{
        x => i32
    };

    let mut f: FunctionRef<fn(Test) -> VmInt> = vm.get_global("test").unwrap();
    let result = f.call(record_no_decl!{ x => 1 }).unwrap();
    assert_eq!(result, 1);
}

#[test]
fn get_value_boxed_or_unboxed() {
    let _ = ::env_logger::try_init();
    let vm = make_vm();

    let text = r#"
        27
    "#;

    // The user should be able to decide whether or not any gluon value should
    // be boxed on the rust side.
    let (unboxed, _) = Compiler::new()
        .run_expr::<i32>(&vm, "test", text)
        .unwrap_or_else(|err| panic!("{}", err));
    assert_eq!(unboxed, 27);
    let (boxed, _) = Compiler::new()
        .run_expr::<Box<i32>>(&vm, "test", text)
        .unwrap_or_else(|err| panic!("{}", err));
    assert_eq!(boxed, Box::new(27));
}
<|endoftext|>


<commit_before>#![feature(globs,macro_rules)]
extern crate mates;
use mates::item::parse_item;

macro_rules! s(
    ($i:expr) => (&$i.into_string());
)

#[test]
fn test_wikipedia_1() {
    let item = parse_item(s!(
        "BEGIN:VCARD\n\
        VERSION:2.1\n\
        N:Mustermann;Erika\n\
        FN:Erika Mustermann\n\
        ORG:Wikipedia\n\
        TITLE:Oberleutnant\n\
        PHOTO;JPEG:http://commons.wikimedia.org/wiki/File:Erika_Mustermann_2010.jpg\n\
        TEL;WORK;VOICE:(0221) 9999123\n\
        TEL;HOME;VOICE:(0221) 1234567\n\
        ADR;HOME:;;Heidestrasse 17;Koeln;;51147;Deutschland\n\
        EMAIL;PREF;INTERNET:erika@mustermann.de\n\
        REV:20140301T221110Z\n\
        END:VCARD")).unwrap();

    assert_eq!(item.single_value(s!("FN")), Some(s!("Erika Mustermann")));
    assert_eq!(item.single_value(s!("N")),  Some(s!("Mustermann;Erika")));
}
<commit_msg>Add tests<commit_after>#![feature(globs,macro_rules)]
extern crate mates;
use mates::item::parse_item;

macro_rules! s(
    ($i:expr) => (&$i.into_string());
)

#[test]
fn test_wikipedia_1() {
    let item = parse_item(s!(
        "BEGIN:VCARD\n\
        VERSION:2.1\n\
        N:Mustermann;Erika\n\
        FN:Erika Mustermann\n\
        ORG:Wikipedia\n\
        TITLE:Oberleutnant\n\
        PHOTO;JPEG:http://commons.wikimedia.org/wiki/File:Erika_Mustermann_2010.jpg\n\
        TEL;WORK;VOICE:(0221) 9999123\n\
        TEL;HOME;VOICE:(0221) 1234567\n\
        ADR;HOME:;;Heidestrasse 17;Koeln;;51147;Deutschland\n\
        EMAIL;PREF;INTERNET:erika@mustermann.de\n\
        REV:20140301T221110Z\n\
        END:VCARD")).unwrap();

    assert_eq!(item.single_value(s!("FN")), Some(s!("Erika Mustermann")));
    assert_eq!(item.single_value(s!("N")),  Some(s!("Mustermann;Erika")));

    let mut tel_values = item.all_values(s!("TEL")).iter().map(|x| x.get_raw_value());
    assert_eq!(tel_values.next().unwrap(), s!("(0221) 9999123"));
    assert_eq!(tel_values.next().unwrap(), s!("(0221) 1234567"));
    assert!(tel_values.next().is_none());
}
<|endoftext|>


<commit_before>extern crate littletest;

use littletest::{Runnable, TestResult, TestOptions, TestRunner};

struct TestCase {
    result: TestResult
}

unsafe impl Sync for TestCase {}

impl TestCase {
    fn new(result: TestResult) -> TestCase {
        TestCase {
            result: result
        }
    }
}

impl Runnable for TestCase {
    fn run(&self) -> TestResult {
        self.result.clone()
    }
}

#[test]
fn it_works() {
    use std::iter::repeat;

    let runnables = repeat(TestResult::Pass)
        .take(10)
        .map(|result| Box::new(TestCase::new(result)) as Box<Runnable + Sync>)
        .collect::<Vec<_>>();

    let runner = TestRunner::new(TestOptions {
        parallelism: Some(4)
    });
    runner.run(&runnables);
}
<commit_msg>Remove an unneeded explicit Sync impl.<commit_after>extern crate littletest;

use littletest::{Runnable, TestResult, TestOptions, TestRunner};

struct TestCase {
    result: TestResult
}

impl TestCase {
    fn new(result: TestResult) -> TestCase {
        TestCase {
            result: result
        }
    }
}

impl Runnable for TestCase {
    fn run(&self) -> TestResult {
        self.result.clone()
    }
}

#[test]
fn it_works() {
    use std::iter::repeat;

    let runnables = repeat(TestResult::Pass)
        .take(10)
        .map(|result| Box::new(TestCase::new(result)) as Box<Runnable + Sync>)
        .collect::<Vec<_>>();

    let runner = TestRunner::new(TestOptions {
        parallelism: Some(4)
    });
    runner.run(&runnables);
}
<|endoftext|>


<commit_before>/* Copyright 2016 Torbjørn Birch Moltu
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://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.
 */

//! Test that every method gives the correct result for valid values.
//! Except iterators, which are stateful.

use std::char;
use std::str::{self,FromStr};
use std::hash::Hash;
use std::collections::hash_map::DefaultHasher;
use std::iter::FromIterator;
extern crate encode_unicode;
use encode_unicode::*;

#[test]
fn equal_defaults() {
    assert_eq!(Utf8Char::default().to_char(), char::default());
    assert_eq!(Utf16Char::default().to_char(), char::default());
}

#[test]
fn same_size_as_char() {
    use std::mem::size_of;
    assert_eq!(size_of::<Utf8Char>(), size_of::<char>());
    assert_eq!(size_of::<Utf16Char>(), size_of::<char>());
}

#[test]
#[cfg(feature="std")]
fn read_iterator() {
    use std::io::Read;
    use std::cmp::min;

    let uc = 'ä'.to_utf8();
    assert_eq!(uc.len(), 2);
    for chunk in 1..5 {
        let mut buf = [b'E'; 6];
        let mut iter = uc.into_iter();
        let mut written = 0;
        for _ in 0..4 {
            assert_eq!(iter.read(&mut buf[..0]).unwrap(), 0);
            let wrote = iter.read(&mut buf[written..written+chunk]).unwrap();
            assert_eq!(wrote, min(2-written, chunk));
            written += wrote;
            for &b in &buf[written..] {assert_eq!(b, b'E');}
            assert_eq!(buf[..written], AsRef::<[u8]>::as_ref(&uc)[..written]);
        }
        assert_eq!(written, 2);
    }
}

const EDGES_AND_BETWEEN: [u32;13] = [
    0x0,// min
    0x3b,// between
    0x7f,// max 1-byte UTF-8
    0x80,// min 2-byte UTF-8
    0x111,// between
    0x7ff,// max 2-byte UTF-8
    0x800,// min 3-byte UTF-8
    0xd7ff,// before reserved
    0xe000,// after reserved
    0xffff,// max UTF-16 single and 3-byte UTF-8
    0x10000,// min UTF-16 surrogate and 4-byte UTF-8
    0xabcde,// between
    0x10ffff,// max
];

fn eq_cmp_hash(c: char) -> (Utf8Char, Utf16Char) {
    let sh = &mut DefaultHasher::new();
    let u8c = c.to_utf8();
    assert_eq!(u8c.to_char(), c);
    assert_eq!(u8c.hash(sh), c.hash(sh));
    let u16c = c.to_utf16();
    assert_eq!(u16c.to_char(), c);
    assert_eq!(u16c.hash(sh), c.hash(sh));

    for other in &EDGES_AND_BETWEEN {
        let other = unsafe{ char::from_u32_unchecked(*other) };

        let u8other = other.to_utf8();
        assert_eq!(u8c == u8other,  c == other);
        assert_eq!(u8c.hash(sh)==other.hash(sh),  c.hash(sh)==u8other.hash(sh));
        assert_eq!(u8c.cmp(&u8other), c.cmp(&other));

        let u16other = other.to_utf16();
        assert_eq!(u16c == u16other,  c == other);
        assert_eq!(u16c.hash(sh)==other.hash(sh),  c.hash(sh)==u16other.hash(sh));
        assert_eq!(u16c.cmp(&u16other), c.cmp(&other));
    }
    (u8c, u16c)
}

fn iterators(c: char) {
    let mut iter = c.iter_utf8_bytes();
    let mut buf = [0; 4];
    let mut iter_ref = c.encode_utf8(&mut buf[..]).as_bytes().iter();
    for _ in 0..6 {
        assert_eq!(iter.size_hint(), iter_ref.size_hint());
        assert_eq!(format!("{:?}", iter), format!("{:?}", iter_ref.as_slice()));
        assert_eq!(iter.next(), iter_ref.next().cloned());
    }

    let mut iter = c.iter_utf16_units();
    let mut buf = [0; 2];
    let mut iter_ref = c.encode_utf16(&mut buf[..]).iter();
    for _ in 0..4 {
        assert_eq!(iter.size_hint(), iter_ref.size_hint());
        assert_eq!(format!("{:?}", iter), format!("{:?}", iter_ref.as_slice()));
        assert_eq!(iter.next(), iter_ref.next().cloned());
    }
}

fn test(c: u32) {
    let c = char::from_u32(c).expect(&format!("{:x} is not a valid char", c));
    assert_eq!(char::from_u32_detailed(c as u32), Ok(c));
    let (u8c, u16c) = eq_cmp_hash(c);
    iterators(c);
    assert_eq!(Utf16Char::from(u8c), u16c);
    assert_eq!(Utf8Char::from(u16c), u8c);

    // UTF-8
    let mut buf = [0; 4];
    let reference = c.encode_utf8(&mut buf[..]).as_bytes();
    let len = reference.len(); // short name because it is used in many places.
    assert_eq!(reference[0].extra_utf8_bytes(), Ok(len-1));
    assert_eq!(reference[0].extra_utf8_bytes_unchecked(), len-1);
    assert_eq!(AsRef::<[u8]>::as_ref(&u8c), reference);

    let (arr,arrlen) = u8c.to_array();
    assert_eq!(arrlen, len);
    assert_eq!(Utf8Char::from_array(arr), Ok(u8c));
    assert_eq!(c.to_utf8_array(),  (arr, len));

    let str_ = str::from_utf8(reference).unwrap();
    let ustr = Utf8Char::from_str(str_).unwrap();
    assert_eq!(ustr.to_array().0, arr);// bitwise equality
    assert_eq!(char::from_utf8_array(arr), Ok(c));
    let mut longer = [0xff; 5]; // 0xff is never valid
    longer[..len].copy_from_slice(reference);
    assert_eq!(char::from_utf8_slice_start(reference), Ok((c,len)));
    assert_eq!(char::from_utf8_slice_start(&longer), Ok((c,len)));
    assert_eq!(Utf8Char::from_slice_start(reference), Ok((u8c,len)));
    assert_eq!(Utf8Char::from_slice_start(&longer), Ok((u8c,len)));
    unsafe {
        // Hopefully make bugs easier to catch by making reads into unallocated memory by filling
        // a jemalloc bin. See table on http://jemalloc.net/jemalloc.3.html for bin sizes.
        // I have no idea whether this works.
        let mut boxed = Box::new([0xffu8; 16]);
        let start = boxed.len()-len; // reach the end
        boxed[start..].copy_from_slice(reference);
        let slice = &boxed[start..start]; // length of slice should be ignored.
        assert_eq!(Utf8Char::from_slice_start_unchecked(slice), (u8c,len));
    }
    assert_eq!(&Vec::<u8>::from_iter(Some(u8c))[..], reference);
    assert_eq!(&String::from_iter(Some(u8c))[..], str_);
    assert_eq!(format!("{:?}", u8c), format!("{:?}", c));
    assert_eq!(format!("{}", u8c), format!("{}", c));

    // UTF-16
    let mut buf = [0; 2];
    let reference = c.encode_utf16(&mut buf[..]);
    let len = reference.len();
    assert_eq!(reference[0].utf16_needs_extra_unit(), Ok(len==2));
    assert_eq!(reference[0].is_utf16_leading_surrogate(), len==2);
    assert_eq!(u16c.as_ref(), reference);
    let mut longer = [0; 3];
    longer[..len].copy_from_slice(reference);
    assert_eq!(char::from_utf16_slice_start(reference), Ok((c,len)));
    assert_eq!(char::from_utf16_slice_start(&longer), Ok((c,len)));
    assert_eq!(Utf16Char::from_slice_start(reference), Ok((u16c,len)));
    assert_eq!(Utf16Char::from_slice_start(&longer), Ok((u16c,len)));
    unsafe {
        // Hopefully make bugs easier to catch by making reads into unallocated memory by filling
        // a jemalloc bin. See table on http://jemalloc.net/jemalloc.3.html for bin sizes.
        // I have no idea whether this works.
        let mut boxed = Box::new([0u16; 8]);
        let start = boxed.len()-len; // reach the end
        boxed[start..].copy_from_slice(reference);
        let slice = &boxed[start..start]; // length of slice should be ignored.
        assert_eq!(Utf16Char::from_slice_start_unchecked(slice), (u16c,len));
    }
    let tuple = c.to_utf16_tuple();
    assert_eq!(tuple, (reference[0],reference.get(1).cloned()));
    assert_eq!(char::from_utf16_tuple(tuple), Ok(c));
    assert_eq!(c.to_utf16().to_char(), c);
    assert_eq!(&Vec::<u16>::from_iter(Some(u16c))[..], reference);
    assert_eq!(format!("{:?}", u16c), format!("{:?}", c));
    assert_eq!(format!("{}", u16c), format!("{}", c));
}

#[test]
fn edges_middle() {
    for c in &EDGES_AND_BETWEEN {
        test(*c);
    }
}

#[test]
#[ignore]
fn all() {
    for c in std::iter::Iterator::chain(0..0xd800, 0xe000..0x110000) {
        test(c);
    }
}
<commit_msg>Test AsciiExt implementations<commit_after>/* Copyright 2016 Torbjørn Birch Moltu
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://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.
 */

//! Test that every method gives the correct result for valid values.
//! Except iterators, which are stateful.

use std::char;
use std::str::{self,FromStr};
use std::cmp::Ordering;
use std::hash::Hash;
use std::collections::hash_map::DefaultHasher;
use std::ascii::AsciiExt;
use std::iter::FromIterator;
extern crate encode_unicode;
use encode_unicode::*;

#[test]
fn equal_defaults() {
    assert_eq!(Utf8Char::default().to_char(), char::default());
    assert_eq!(Utf16Char::default().to_char(), char::default());
}

#[test]
fn same_size_as_char() {
    use std::mem::size_of;
    assert_eq!(size_of::<Utf8Char>(), size_of::<char>());
    assert_eq!(size_of::<Utf16Char>(), size_of::<char>());
}

#[test]
#[cfg(feature="std")]
fn read_iterator() {
    use std::io::Read;
    use std::cmp::min;

    let uc = 'ä'.to_utf8();
    assert_eq!(uc.len(), 2);
    for chunk in 1..5 {
        let mut buf = [b'E'; 6];
        let mut iter = uc.into_iter();
        let mut written = 0;
        for _ in 0..4 {
            assert_eq!(iter.read(&mut buf[..0]).unwrap(), 0);
            let wrote = iter.read(&mut buf[written..written+chunk]).unwrap();
            assert_eq!(wrote, min(2-written, chunk));
            written += wrote;
            for &b in &buf[written..] {assert_eq!(b, b'E');}
            assert_eq!(buf[..written], AsRef::<[u8]>::as_ref(&uc)[..written]);
        }
        assert_eq!(written, 2);
    }
}

const EDGES_AND_BETWEEN: [u32;19] = [
    0x0,// min
    0x3b,// middle ASCII
    b'A' as u32,
    b'N' as u32,
    b'Z' as u32,
    b'a' as u32,
    b'm' as u32,
    b'z' as u32,
    0x7f,// max 1-byte UTF-8
    0x80,// min 2-byte UTF-8
    0x111,// between
    0x7ff,// max 2-byte UTF-8
    0x800,// min 3-byte UTF-8
    0xd7ff,// before reserved
    0xe000,// after reserved
    0xffff,// max UTF-16 single and 3-byte UTF-8
    0x10000,// min UTF-16 surrogate and 4-byte UTF-8
    0xabcde,// between
    0x10ffff,// max
];

fn eq_cmp_hash(c: char) -> (Utf8Char, Utf16Char) {
    let sh = &mut DefaultHasher::new();
    let u8c = c.to_utf8();
    assert_eq!(u8c.to_char(), c);
    assert_eq!(u8c, u8c);
    assert_eq!(u8c.hash(sh), c.hash(sh));
    assert_eq!(u8c.cmp(&u8c), Ordering::Equal);
    assert!(u8c.eq_ignore_ascii_case(&u8c));
    let u16c = c.to_utf16();
    assert_eq!(u16c.to_char(), c);
    assert_eq!(u16c, u16c);
    assert_eq!(u16c.hash(sh), c.hash(sh));
    assert_eq!(u16c.cmp(&u16c), Ordering::Equal);
    assert!(u16c.eq_ignore_ascii_case(&u16c));

    for other in &EDGES_AND_BETWEEN {
        let other = unsafe{ char::from_u32_unchecked(*other) };

        let u8other = other.to_utf8();
        assert_eq!(u8c == u8other,  c == other);
        assert_eq!(u8c.hash(sh)==other.hash(sh),  c.hash(sh)==u8other.hash(sh));
        assert_eq!(u8c.cmp(&u8other), c.cmp(&other));
        assert_eq!(u8c.eq_ignore_ascii_case(&u8other), c.eq_ignore_ascii_case(&other));

        let u16other = other.to_utf16();
        assert_eq!(u16c == u16other,  c == other);
        assert_eq!(u16c.hash(sh)==other.hash(sh),  c.hash(sh)==u16other.hash(sh));
        assert_eq!(u16c.cmp(&u16other), c.cmp(&other));
        assert_eq!(u16c.eq_ignore_ascii_case(&u16other), c.eq_ignore_ascii_case(&other));
    }
    (u8c, u16c)
}

fn iterators(c: char) {
    let mut iter = c.iter_utf8_bytes();
    let mut buf = [0; 4];
    let mut iter_ref = c.encode_utf8(&mut buf[..]).as_bytes().iter();
    for _ in 0..6 {
        assert_eq!(iter.size_hint(), iter_ref.size_hint());
        assert_eq!(format!("{:?}", iter), format!("{:?}", iter_ref.as_slice()));
        assert_eq!(iter.next(), iter_ref.next().cloned());
    }

    let mut iter = c.iter_utf16_units();
    let mut buf = [0; 2];
    let mut iter_ref = c.encode_utf16(&mut buf[..]).iter();
    for _ in 0..4 {
        assert_eq!(iter.size_hint(), iter_ref.size_hint());
        assert_eq!(format!("{:?}", iter), format!("{:?}", iter_ref.as_slice()));
        assert_eq!(iter.next(), iter_ref.next().cloned());
    }
}

fn test(c: u32) {
    let c = char::from_u32(c).expect(&format!("{:x} is not a valid char", c));
    assert_eq!(char::from_u32_detailed(c as u32), Ok(c));
    let (u8c, u16c) = eq_cmp_hash(c);
    iterators(c);
    assert_eq!(Utf16Char::from(u8c), u16c);
    assert_eq!(Utf8Char::from(u16c), u8c);

    // UTF-8
    let mut buf = [0; 4];
    let reference = c.encode_utf8(&mut buf[..]).as_bytes();
    let len = reference.len(); // short name because it is used in many places.
    assert_eq!(reference[0].extra_utf8_bytes(), Ok(len-1));
    assert_eq!(reference[0].extra_utf8_bytes_unchecked(), len-1);
    assert_eq!(AsRef::<[u8]>::as_ref(&u8c), reference);

    let (arr,arrlen) = u8c.to_array();
    assert_eq!(arrlen, len);
    assert_eq!(Utf8Char::from_array(arr), Ok(u8c));
    assert_eq!(c.to_utf8_array(),  (arr, len));

    let str_ = str::from_utf8(reference).unwrap();
    let ustr = Utf8Char::from_str(str_).unwrap();
    assert_eq!(ustr.to_array().0, arr);// bitwise equality
    assert_eq!(char::from_utf8_array(arr), Ok(c));
    let mut longer = [0xff; 5]; // 0xff is never valid
    longer[..len].copy_from_slice(reference);
    assert_eq!(char::from_utf8_slice_start(reference), Ok((c,len)));
    assert_eq!(char::from_utf8_slice_start(&longer), Ok((c,len)));
    assert_eq!(Utf8Char::from_slice_start(reference), Ok((u8c,len)));
    assert_eq!(Utf8Char::from_slice_start(&longer), Ok((u8c,len)));
    unsafe {
        // Hopefully make bugs easier to catch by making reads into unallocated memory by filling
        // a jemalloc bin. See table on http://jemalloc.net/jemalloc.3.html for bin sizes.
        // I have no idea whether this works.
        let mut boxed = Box::new([0xffu8; 16]);
        let start = boxed.len()-len; // reach the end
        boxed[start..].copy_from_slice(reference);
        let slice = &boxed[start..start]; // length of slice should be ignored.
        assert_eq!(Utf8Char::from_slice_start_unchecked(slice), (u8c,len));
    }
    assert_eq!(&Vec::<u8>::from_iter(Some(u8c))[..], reference);
    assert_eq!(&String::from_iter(Some(u8c))[..], str_);
    assert_eq!(format!("{:?}", u8c), format!("{:?}", c));
    assert_eq!(format!("{}", u8c), format!("{}", c));
    assert_eq!(u8c.is_ascii(), c.is_ascii());
    assert_eq!(u8c.to_ascii_lowercase().to_char(), c.to_ascii_lowercase());
    assert_eq!(u8c.to_ascii_uppercase().to_char(), c.to_ascii_uppercase());

    // UTF-16
    let mut buf = [0; 2];
    let reference = c.encode_utf16(&mut buf[..]);
    let len = reference.len();
    assert_eq!(reference[0].utf16_needs_extra_unit(), Ok(len==2));
    assert_eq!(reference[0].is_utf16_leading_surrogate(), len==2);
    assert_eq!(u16c.as_ref(), reference);
    let mut longer = [0; 3];
    longer[..len].copy_from_slice(reference);
    assert_eq!(char::from_utf16_slice_start(reference), Ok((c,len)));
    assert_eq!(char::from_utf16_slice_start(&longer), Ok((c,len)));
    assert_eq!(Utf16Char::from_slice_start(reference), Ok((u16c,len)));
    assert_eq!(Utf16Char::from_slice_start(&longer), Ok((u16c,len)));
    unsafe {
        // Hopefully make bugs easier to catch by making reads into unallocated memory by filling
        // a jemalloc bin. See table on http://jemalloc.net/jemalloc.3.html for bin sizes.
        // I have no idea whether this works.
        let mut boxed = Box::new([0u16; 8]);
        let start = boxed.len()-len; // reach the end
        boxed[start..].copy_from_slice(reference);
        let slice = &boxed[start..start]; // length of slice should be ignored.
        assert_eq!(Utf16Char::from_slice_start_unchecked(slice), (u16c,len));
    }
    let tuple = c.to_utf16_tuple();
    assert_eq!(tuple, (reference[0],reference.get(1).cloned()));
    assert_eq!(char::from_utf16_tuple(tuple), Ok(c));
    assert_eq!(c.to_utf16().to_char(), c);
    assert_eq!(&Vec::<u16>::from_iter(Some(u16c))[..], reference);
    assert_eq!(format!("{:?}", u16c), format!("{:?}", c));
    assert_eq!(format!("{}", u16c), format!("{}", c));
    assert_eq!(u16c.is_ascii(), c.is_ascii());
    assert_eq!(u16c.to_ascii_lowercase().to_char(), c.to_ascii_lowercase());
    assert_eq!(u16c.to_ascii_uppercase().to_char(), c.to_ascii_uppercase());
}

#[test]
fn edges_middle() {
    for c in &EDGES_AND_BETWEEN {
        test(*c);
    }
}

#[test]
#[ignore]
fn all() {
    for c in std::iter::Iterator::chain(0..0xd800, 0xe000..0x110000) {
        test(c);
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering::*;
use std::ops::Not;

#[derive(Debug, Clone)]
pub struct BST<T> {
    nodes: Vec<Option<Node<T>>>,
    root: Option<Ptr>,
    deleted_indices: Vec<Ptr>
}

#[derive(Debug, Clone, Copy)]
struct Ptr(usize);

#[derive(Debug, Clone, Copy)]
enum Color {Red, Black}

#[derive(Debug, Clone)]
struct Node<T> {
    elem: T,
    color: Color,
    left: Option<Ptr>,
    right: Option<Ptr>,
}

impl<T: Ord> Node<T> {
    fn new(elem: T, color: Color) -> Self {
        Node { elem: elem, color: color, left: None, right: None }
    }
}

impl Not for Color {
    type Output = Color;
    fn not(self) -> Self {
        match self {
            Color::Red => Color::Black,
            Color::Black => Color::Red,
        }
    }
}

impl<T: Ord> BST<T> {
    fn deref(&self, i: &Ptr) -> &Node<T> {
        self.nodes[i.0].as_ref().expect("deref encounters a reference to a deleted node")
    }

    fn deref_mut(&mut self, i: &Ptr) -> &mut Node<T> {
        self.nodes[i.0].as_mut().expect("deref_mut encounters a reference to a deleted node")
    }

    pub fn new() -> Self {
        BST{ nodes: Vec::new(), root: None, deleted_indices: Vec::new() }
    }

    pub fn singleton(elem: T) -> Self {
        BST{ nodes: vec![Some(Node::new(elem, Color::Black))], root: Some(Ptr(0)), deleted_indices: Vec::new() }
    }

    fn member_impl(&self, ptr: &Option<Ptr>, elem: &T) -> bool {
        match *ptr {
            None => false,
            Some(ref ptr) => {
                let node = self.deref(ptr);
                match node.elem.cmp(elem) {
                    Less => self.member_impl(&node.right, elem),
                    Greater => self.member_impl(&node.left, elem),
                    Equal => true,
                }
            }
        }
    }

    pub fn member(&self, elem: &T) -> bool {
        self.member_impl(&self.root, elem)
    }

    fn is_red(&self, ptr: &Option<Ptr>) -> bool {
        ptr.as_ref().map_or(false, |p| if let Color::Red = self.deref(p).color { true } else { false })
    }

    fn rotate_left(&mut self, h: Ptr) -> Ptr {
        let x : Ptr = self.deref(&h).right.expect("rotate left on node whose left child is nil");
        self.deref_mut(&h).right = self.deref(&x).left;
        self.deref_mut(&x).left = Some(h);
        self.deref_mut(&x).color = self.deref(&h).color;
        self.deref_mut(&h).color = Color::Red;
        x
        // Note to self: the braces on the right of the assignment are to limit
        // the scope of the immutable borrow, because we are immediately
        // borrowing again mutably.
    }

    fn rotate_right(&mut self, h: Ptr) -> Ptr {
        let x : Ptr = self.deref(&h).left.expect("rotate right on node whose left child is nil");
        self.deref_mut(&h).left = self.deref(&x).right;
        self.deref_mut(&x).right = Some(h);
        self.deref_mut(&x).color = self.deref(&h).color;
        self.deref_mut(&h).color = Color::Red;
        x
    }

    fn move_red_up_or_down(&mut self, h: Ptr) {
        self.deref_mut(&h).color = !self.deref(&h).color;
        let left : Ptr = self.deref(&h).left.expect("move red up/down on node whose left child is nil");
        self.deref_mut(&left).color = !self.deref(&left).color;
        let right: Ptr = self.deref(&h).right.expect("move red up/down on node whose right child is nil");
        self.deref_mut(&right).color = !self.deref(&right).color;
    }

    fn fixup(&mut self, mut node: Ptr) -> Ptr {
        if self.is_red(&self.deref(&node).right) && !self.is_red(&self.deref(&node).left) {
            node = self.rotate_left(node);
        }
        if self.is_red(&self.deref(&node).left) && self.is_red(&self.deref(&self.deref(&node).left.unwrap()).left) {
            node = self.rotate_right(node);
        }
        if self.is_red(&self.deref(&node).left) && self.is_red(&self.deref(&node).right) {
            self.move_red_up_or_down(node);
        }
        node
    }

    fn insert_impl(&mut self, node: Option<Ptr>, elem: T) -> Ptr {
        match node {
            None => {
                self.nodes.push(Some(Node::new(elem, Color::Red)));
                Ptr(self.nodes.len() - 1)
            },
            Some(node) => {
                match self.deref(&node).elem.cmp(&elem) {
                    Less => {
                        let right : Option<Ptr> = self.deref(&node).right;
                        let new_right : Ptr = self.insert_impl(right, elem);
                        self.deref_mut(&node).right = Some(new_right);
                    },
                    Greater => {
                        let left : Option<Ptr> = self.deref(&node).left;
                        let new_left : Ptr = self.insert_impl(left, elem);
                        self.deref_mut(&node).left = Some(new_left);
                    },
                    Equal => self.deref_mut(&node).elem = elem,
                }
                self.fixup(node)
            }
        }
    }

    pub fn insert(&mut self, elem: T) {
        let old_root : Option<Ptr> = self.root;
        let new_root : Ptr = self.insert_impl(old_root, elem);
        self.root = Some(new_root);
        self.deref_mut(&new_root).color = Color::Black;
    }

    pub fn clear(&mut self) {
        self.root = None;
        self.nodes.clear();
        self.deleted_indices.clear();
    }

    fn move_red_left(&mut self, mut h: Ptr) -> Ptr {
        self.move_red_up_or_down(h);
        if self.is_red(&self.deref(&self.deref(&h).right.unwrap()).left) {
            self.deref_mut(&h).right = self.deref(&h).right.map(|right| self.rotate_right(right));
            h = self.rotate_left(h);
            self.move_red_up_or_down(h);
        }
        h
    }

    fn take_min_impl(&mut self, mut node: Ptr) -> (T, Option<Ptr>) {
        match self.deref(&node).left {
            None => {
                // The current node is the minimum in the tree.
                self.deleted_indices.push(node);
                (self.nodes[node.0].take().expect("take_min_impl: leftmost node is already deleted").elem, None)
            },
            Some(left) => {
                // We need to make sure the next node is not a 2-node.
                // Making the next node not a 2-node means either it or
                // its left child is red (or both, in the case of a 4-node).
                // This checks if this is violated.
                if !self.is_red(&Some(left)) && !self.is_red(&self.deref(&left).left) {
                    node = self.move_red_left(node);
                }
                let left = self.deref_mut(&node).left.unwrap();
                let (min, new_left) = self.take_min_impl(left);
                self.deref_mut(&node).left = new_left;
                (min, Some(self.fixup(node)))
            }
        }
    }

    pub fn take_min(&mut self) -> Option<T> {
        self.root.and_then(
            |root|
            if self.deref(&root).left.is_none() {
                // The tree has only one element.
                let rv = self.nodes.swap_remove(root.0).map(|node| node.elem);
                self.root = None;
                self.deleted_indices.clear();
                self.nodes.clear();
                rv
            } else {
                // The tree has more than one element.
                let (min, new_root) = self.take_min_impl(root);
                self.root = new_root;
                self.deref_mut(&new_root.unwrap()).color = Color::Black;
                Some(min)
            })
    }

    fn print_structure_inner(&self, node: Option<Ptr>) {
        match node {
            None => print!("[missing]"),
            Some(node_id) => {
                print!("{{ node ");
                let node = self.deref(&node_id);
                if let Color::Red = node.color {
                    print!("[draw=red]");
                }
                print!("{{{:?}}} ", node_id.0); // Prints order of insertion
                if let Color::Red = node.color {
                    print!("edge from parent[red]");
                }
                print!(" child ");
                self.print_structure_inner(node.left);
                print!(" child ");
                self.print_structure_inner(node.right);
                print!(" }}");
            }
        }
    }

    pub fn print_structure(&self) {
        match self.root {
            None => (),
            Some(ref node_id) => {
                println!("%% Put these in your preamble\n\
                          \\usepackage{{tikz}}\n\
                          \\usetikzlibrary{{graphdrawing}}\n\
                          \\usegdlibrary{{trees}}\n\
                          \\definecolor{{red}}{{RGB}}{{171,50,37}}\n\n\
                          %% Put these in the document body\n\
                          \\tikz [binary tree layout, nodes={{draw,circle}}, font=\\sffamily, semithick] \
                          \\node");
                let node = self.deref(&node_id);
                print!("{{{:?}}} child ", node_id.0); // Prints order of insertion
                self.print_structure_inner(node.left);
                print!(" child ");
                self.print_structure_inner(node.right);
                println!(";");
            }
        }
    }
}

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

    #[test]
    fn basics() {
        let e: BST<i32> = BST::new();
        let s = BST::singleton(2);

        assert_eq!(false, e.member(&1));
        assert_eq!(false, e.member(&2));
        assert_eq!(false, e.member(&3));

        assert_eq!(false, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));
    }

    #[test]
    fn insertion() {
        let mut s = BST::singleton(2);
        s.insert(1);
        assert_eq!(true, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));

        s.insert(4);
        assert_eq!(true, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));
        assert_eq!(true, s.member(&4));

        {
            let mut thousand : BST<i32> = BST::new();
            for i in 0..1000 {
                thousand.insert(i);
            }
            for i in 0..1000 {
                assert_eq!(true, thousand.member(&i));
            }
            assert_eq!(false, thousand.member(&1000));
        }

        {
            let mut thousand : BST<i32> = BST::new();
            for i in 0..1000 {
                if i % 2 == 0 {
                    thousand.insert(i);
                }
            }
            for i in 0..1000 {
                assert_eq!(i % 2 == 0, thousand.member(&i));
            }
            for i in 0..1000 {
                if i % 2 == 1 {
                    thousand.insert(i);
                }
            }
            for i in 0..1000 {
                assert_eq!(true, thousand.member(&i));
            }
        }

        {
            let mut ex : BST<i32> = BST::new();
            for c in 0..64 {
                ex.insert(c);
                ex.print_structure();
                println!("");
            }
        }

        {
            let mut ex : BST<i32> = BST::new();
            let v: [i32; 20] = [14, 9, 12, 6, 2, 10, 1, 18, 16, 5, 8, 17, 13, 3, 11, 15, 7, 19, 4, 20];
            for c in &v {
                ex.insert(*c);
                ex.print_structure();
                println!("");
            }
        }
    }

    #[test]
    fn taking_minimum() {
        {
            let mut tree: BST<i32> = BST::new();
            tree.insert(2);
            tree.insert(3);
            tree.insert(5);
            assert_eq!(tree.take_min(), Some(2)); // [3,5]
            tree.insert(1);                       // [1,3,5]
            assert_eq!(tree.take_min(), Some(1)); // [3,5]
            assert_eq!(tree.take_min(), Some(3)); // [5]
            tree.insert(2);                       // [2,5]
            tree.insert(1);                       // [1,2,5]
            assert_eq!(tree.take_min(), Some(1));
            assert_eq!(tree.take_min(), Some(2));
            assert_eq!(tree.take_min(), Some(5));
            assert_eq!(tree.take_min(), None);
            println!("Passed: take_min for a manual test case with interleaved insertions and deletions")
        }

        {
            let mut tree : BST<i32> = BST::new();
            for size in 0..10 {
                for i in 0..size {
                    tree.insert(i);
                }
                for i in 0..size {
                    assert_eq!(tree.take_min(), Some(i));
                }
                assert_eq!(tree.take_min(), None);
                println!("Passed: take_min for tree with {} element(s)", size);
            }
        }
    }
}
<commit_msg>Reuse deleted nodes for new ones<commit_after>use std::cmp::Ordering::*;
use std::ops::Not;

#[derive(Debug, Clone)]
pub struct BST<T> {
    nodes: Vec<Option<Node<T>>>,
    root: Option<Ptr>,
    deleted_indices: Vec<Ptr>
}

#[derive(Debug, Clone, Copy)]
struct Ptr(usize);

#[derive(Debug, Clone, Copy)]
enum Color {Red, Black}

#[derive(Debug, Clone)]
struct Node<T> {
    elem: T,
    color: Color,
    left: Option<Ptr>,
    right: Option<Ptr>,
}

impl<T: Ord> Node<T> {
    fn new(elem: T, color: Color) -> Self {
        Node { elem: elem, color: color, left: None, right: None }
    }
}

impl Not for Color {
    type Output = Color;
    fn not(self) -> Self {
        match self {
            Color::Red => Color::Black,
            Color::Black => Color::Red,
        }
    }
}

impl<T: Ord> BST<T> {
    fn deref(&self, i: &Ptr) -> &Node<T> {
        self.nodes[i.0].as_ref().expect("deref encounters a reference to a deleted node")
    }

    fn deref_mut(&mut self, i: &Ptr) -> &mut Node<T> {
        self.nodes[i.0].as_mut().expect("deref_mut encounters a reference to a deleted node")
    }

    pub fn new() -> Self {
        BST{ nodes: Vec::new(), root: None, deleted_indices: Vec::new() }
    }

    pub fn singleton(elem: T) -> Self {
        BST{ nodes: vec![Some(Node::new(elem, Color::Black))], root: Some(Ptr(0)), deleted_indices: Vec::new() }
    }

    fn member_impl(&self, ptr: &Option<Ptr>, elem: &T) -> bool {
        match *ptr {
            None => false,
            Some(ref ptr) => {
                let node = self.deref(ptr);
                match node.elem.cmp(elem) {
                    Less => self.member_impl(&node.right, elem),
                    Greater => self.member_impl(&node.left, elem),
                    Equal => true,
                }
            }
        }
    }

    pub fn member(&self, elem: &T) -> bool {
        self.member_impl(&self.root, elem)
    }

    fn is_red(&self, ptr: &Option<Ptr>) -> bool {
        ptr.as_ref().map_or(false, |p| if let Color::Red = self.deref(p).color { true } else { false })
    }

    fn rotate_left(&mut self, h: Ptr) -> Ptr {
        let x : Ptr = self.deref(&h).right.expect("rotate left on node whose left child is nil");
        self.deref_mut(&h).right = self.deref(&x).left;
        self.deref_mut(&x).left = Some(h);
        self.deref_mut(&x).color = self.deref(&h).color;
        self.deref_mut(&h).color = Color::Red;
        x
        // Note to self: the braces on the right of the assignment are to limit
        // the scope of the immutable borrow, because we are immediately
        // borrowing again mutably.
    }

    fn rotate_right(&mut self, h: Ptr) -> Ptr {
        let x : Ptr = self.deref(&h).left.expect("rotate right on node whose left child is nil");
        self.deref_mut(&h).left = self.deref(&x).right;
        self.deref_mut(&x).right = Some(h);
        self.deref_mut(&x).color = self.deref(&h).color;
        self.deref_mut(&h).color = Color::Red;
        x
    }

    fn move_red_up_or_down(&mut self, h: Ptr) {
        self.deref_mut(&h).color = !self.deref(&h).color;
        let left : Ptr = self.deref(&h).left.expect("move red up/down on node whose left child is nil");
        self.deref_mut(&left).color = !self.deref(&left).color;
        let right: Ptr = self.deref(&h).right.expect("move red up/down on node whose right child is nil");
        self.deref_mut(&right).color = !self.deref(&right).color;
    }

    fn fixup(&mut self, mut node: Ptr) -> Ptr {
        if self.is_red(&self.deref(&node).right) && !self.is_red(&self.deref(&node).left) {
            node = self.rotate_left(node);
        }
        if self.is_red(&self.deref(&node).left) && self.is_red(&self.deref(&self.deref(&node).left.unwrap()).left) {
            node = self.rotate_right(node);
        }
        if self.is_red(&self.deref(&node).left) && self.is_red(&self.deref(&node).right) {
            self.move_red_up_or_down(node);
        }
        node
    }

    fn insert_impl(&mut self, node: Option<Ptr>, elem: T) -> Ptr {
        match node {
            None => {
                let new = Some(Node::new(elem, Color::Red));
                if let Some(index) = self.deleted_indices.pop() {
                    self.nodes[index.0] = new;
                    index
                } else {
                    self.nodes.push(new);
                    Ptr(self.nodes.len() - 1)
                }
            },
            Some(node) => {
                match self.deref(&node).elem.cmp(&elem) {
                    Less => {
                        let right : Option<Ptr> = self.deref(&node).right;
                        let new_right : Ptr = self.insert_impl(right, elem);
                        self.deref_mut(&node).right = Some(new_right);
                    },
                    Greater => {
                        let left : Option<Ptr> = self.deref(&node).left;
                        let new_left : Ptr = self.insert_impl(left, elem);
                        self.deref_mut(&node).left = Some(new_left);
                    },
                    Equal => self.deref_mut(&node).elem = elem,
                }
                self.fixup(node)
            }
        }
    }

    pub fn insert(&mut self, elem: T) {
        let old_root : Option<Ptr> = self.root;
        let new_root : Ptr = self.insert_impl(old_root, elem);
        self.root = Some(new_root);
        self.deref_mut(&new_root).color = Color::Black;
    }

    pub fn clear(&mut self) {
        self.root = None;
        self.nodes.clear();
        self.deleted_indices.clear();
    }

    fn move_red_left(&mut self, mut h: Ptr) -> Ptr {
        self.move_red_up_or_down(h);
        if self.is_red(&self.deref(&self.deref(&h).right.unwrap()).left) {
            self.deref_mut(&h).right = self.deref(&h).right.map(|right| self.rotate_right(right));
            h = self.rotate_left(h);
            self.move_red_up_or_down(h);
        }
        h
    }

    fn take_min_impl(&mut self, mut node: Ptr) -> (T, Option<Ptr>) {
        match self.deref(&node).left {
            None => {
                // The current node is the minimum in the tree.
                self.deleted_indices.push(node);
                (self.nodes[node.0].take().expect("take_min_impl: leftmost node is already deleted").elem, None)
            },
            Some(left) => {
                // We need to make sure the next node is not a 2-node.
                // Making the next node not a 2-node means either it or
                // its left child is red (or both, in the case of a 4-node).
                // This checks if this is violated.
                if !self.is_red(&Some(left)) && !self.is_red(&self.deref(&left).left) {
                    node = self.move_red_left(node);
                }
                let left = self.deref_mut(&node).left.unwrap();
                let (min, new_left) = self.take_min_impl(left);
                self.deref_mut(&node).left = new_left;
                (min, Some(self.fixup(node)))
            }
        }
    }

    pub fn take_min(&mut self) -> Option<T> {
        self.root.and_then(
            |root|
            if self.deref(&root).left.is_none() {
                // The tree has only one element.
                let rv = self.nodes.swap_remove(root.0).map(|node| node.elem);
                self.root = None;
                self.deleted_indices.clear();
                self.nodes.clear();
                rv
            } else {
                // The tree has more than one element.
                let (min, new_root) = self.take_min_impl(root);
                self.root = new_root;
                self.deref_mut(&new_root.unwrap()).color = Color::Black;
                Some(min)
            })
    }

    fn print_structure_inner(&self, node: Option<Ptr>) {
        match node {
            None => print!("[missing]"),
            Some(node_id) => {
                print!("{{ node ");
                let node = self.deref(&node_id);
                if let Color::Red = node.color {
                    print!("[draw=red]");
                }
                print!("{{{:?}}} ", node_id.0); // Prints order of insertion
                if let Color::Red = node.color {
                    print!("edge from parent[red]");
                }
                print!(" child ");
                self.print_structure_inner(node.left);
                print!(" child ");
                self.print_structure_inner(node.right);
                print!(" }}");
            }
        }
    }

    pub fn print_structure(&self) {
        match self.root {
            None => (),
            Some(ref node_id) => {
                println!("%% Put these in your preamble\n\
                          \\usepackage{{tikz}}\n\
                          \\usetikzlibrary{{graphdrawing}}\n\
                          \\usegdlibrary{{trees}}\n\
                          \\definecolor{{red}}{{RGB}}{{171,50,37}}\n\n\
                          %% Put these in the document body\n\
                          \\tikz [binary tree layout, nodes={{draw,circle}}, font=\\sffamily, semithick] \
                          \\node");
                let node = self.deref(&node_id);
                print!("{{{:?}}} child ", node_id.0); // Prints order of insertion
                self.print_structure_inner(node.left);
                print!(" child ");
                self.print_structure_inner(node.right);
                println!(";");
            }
        }
    }
}

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

    #[test]
    fn basics() {
        let e: BST<i32> = BST::new();
        let s = BST::singleton(2);

        assert_eq!(false, e.member(&1));
        assert_eq!(false, e.member(&2));
        assert_eq!(false, e.member(&3));

        assert_eq!(false, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));
    }

    #[test]
    fn insertion() {
        let mut s = BST::singleton(2);
        s.insert(1);
        assert_eq!(true, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));

        s.insert(4);
        assert_eq!(true, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));
        assert_eq!(true, s.member(&4));

        {
            let mut thousand : BST<i32> = BST::new();
            for i in 0..1000 {
                thousand.insert(i);
            }
            for i in 0..1000 {
                assert_eq!(true, thousand.member(&i));
            }
            assert_eq!(false, thousand.member(&1000));
        }

        {
            let mut thousand : BST<i32> = BST::new();
            for i in 0..1000 {
                if i % 2 == 0 {
                    thousand.insert(i);
                }
            }
            for i in 0..1000 {
                assert_eq!(i % 2 == 0, thousand.member(&i));
            }
            for i in 0..1000 {
                if i % 2 == 1 {
                    thousand.insert(i);
                }
            }
            for i in 0..1000 {
                assert_eq!(true, thousand.member(&i));
            }
        }

        {
            let mut ex : BST<i32> = BST::new();
            for c in 0..64 {
                ex.insert(c);
                ex.print_structure();
                println!("");
            }
        }

        {
            let mut ex : BST<i32> = BST::new();
            let v: [i32; 20] = [14, 9, 12, 6, 2, 10, 1, 18, 16, 5, 8, 17, 13, 3, 11, 15, 7, 19, 4, 20];
            for c in &v {
                ex.insert(*c);
                ex.print_structure();
                println!("");
            }
        }
    }

    #[test]
    fn taking_minimum() {
        {
            let mut tree: BST<i32> = BST::new();
            tree.insert(2);
            tree.insert(3);
            tree.insert(5);
            assert_eq!(tree.take_min(), Some(2)); // [3,5]
            tree.insert(1);                       // [1,3,5]
            assert_eq!(tree.take_min(), Some(1)); // [3,5]
            assert_eq!(tree.take_min(), Some(3)); // [5]
            tree.insert(2);                       // [2,5]
            tree.insert(1);                       // [1,2,5]
            assert_eq!(tree.take_min(), Some(1));
            assert_eq!(tree.take_min(), Some(2));
            assert_eq!(tree.take_min(), Some(5));
            assert_eq!(tree.take_min(), None);
            println!("Passed: take_min for a manual test case with interleaved insertions and deletions")
        }

        {
            let mut tree : BST<i32> = BST::new();
            for size in 0..10 {
                for i in 0..size {
                    tree.insert(i);
                }
                for i in 0..size {
                    assert_eq!(tree.take_min(), Some(i));
                }
                assert_eq!(tree.take_min(), None);
                println!("Passed: take_min for tree with {} element(s)", size);
            }
        }
    }
}
<|endoftext|>


<commit_before>use core::prelude::*;
use core::iter::range_step;
use core::intrinsics::set_memory;
use core::ptr;

use con;
use con::Console;
use con::Writer;
use con::write;
use con::writeUInt;
use mboot;
use mboot::MemoryMapItem;
use start32::PhysAddr;
use start32::MutPhysAddr;
use util::abort;

use mem::framestack::*;

static log_alloc : bool = false;
static log_memory_map : bool = false;
static log_memtest : bool = false;
static mem_stats : bool = true;

pub mod framestack {
    use core::prelude::*;

    struct FreeFrame {
        next : FreeFrameS
    }
    pub type FreeFrameS = *mut FreeFrame;
    pub type FreeFrameP = Option<*mut FreeFrame>;

    pub const none : FreeFrameS = 0 as *mut FreeFrame;

    fn from_option<T>(x : Option<T>, def : T) -> T {
        match x {
            Some(val) => val,
            None => def
        }
    }

    pub fn store<T>(p : Option<*mut T>) -> *mut T {
        from_option(p, 0 as *mut T)
    }

    pub fn push_frame<T>(head : &mut FreeFrameS, frame : *mut T) {
        let free = frame as *mut FreeFrame;
        unsafe { (*free).next = *head; }
        *head = free;
    }

    pub fn pop_frame(head : &mut FreeFrameS) -> FreeFrameP {
        if *head == none {
            None
        } else {
            let page = *head;
            unsafe {
                *head = (*page).next;
                (*page).next = none;
            }
            Some(page)
        }
    }

}

pub struct Global {
    // Frames that are uninitialized (except for the first word)
    garbage : FreeFrameS,
    // Frames that are all zeroes except for the first word
    free : FreeFrameS,
    num_used : uint,
    num_total : uint,
}

pub const empty_global : Global = Global { garbage : none, free : none, num_used : 0, num_total : 0 };
pub static mut global : Global = empty_global;

pub struct PerCpu {
    free : FreeFrameS
}

struct MemoryMap {
    addr : *const u8,
    end : *const u8
}

impl MemoryMap {
    fn new(addr : *const u8, length : uint) -> MemoryMap {
        return MemoryMap { addr : addr, end : unsafe { addr.offset(length as int) } }
    }
}

impl Iterator for MemoryMap {
    type Item = MemoryMapItem;

    fn next(&mut self) -> Option<MemoryMapItem> {
        if self.addr < self.end { unsafe {
            let item = *(self.addr as *const MemoryMapItem);
            self.addr = self.addr.offset(4 + item.item_size as int);
            Some(item)
        } } else {
            None
        }
    }
}

fn clear<T>(page : *mut T) {
    unsafe { set_memory(page as *mut u8, 0, 4096); }
}

impl Global {
    pub fn init(&mut self, info : &mboot::Info, min_addr : uint, max_addr : uint) {
        if !info.has(mboot::MemoryMap) {
            return;
        }

        let mmap = MemoryMap::new(PhysAddr(info.mmap_addr as uint), info.mmap_length as uint);
        let mut count = 0;
        for item in mmap {
            if log_memory_map {
                write("start=");
                con::writePHex(item.start as uint);
                write(" length=");
                con::writePHex(item.length as uint);
                write(" type=");
                con::writeUInt(item.item_type as uint);
                con::newline();
            }
            if item.item_type != mboot::MemoryTypeMemory as u32 {
                continue;
            }
            for p in range_step(item.start, item.start + item.length, 4096) {
                let addr = p as uint;
                if min_addr <= addr && addr < max_addr {
                    self.num_used = 1;
                    self.free_frame(MutPhysAddr(p as uint));
                    count += 1;
                }
            }
        }
        self.num_used = 0;
        self.num_total = count;
    }

    pub fn free_frame(&mut self, vpaddr : *mut u8) {
        self.num_used -= 1;
        if log_alloc {
            write("free_frame: ");
            con::writeMutPtr(vpaddr);
            con::newline();
        }
        if mem_stats {
            self.stat_line();
        }
        push_frame(&mut self.garbage, vpaddr);
    }

    pub fn alloc_frame(&mut self) -> FreeFrameP {
        let res = match pop_frame(&mut self.free) {
            Some(page) => {
                self.num_used += 1;
                Some(page)
            },
            None => match pop_frame(&mut self.garbage) {
                Some(page) => {
                    self.num_used += 1;
                    clear(page);
                    Some(page)
                },
                None => { None }
            }
        };
        if log_alloc {
            write("alloc_frame: ");
            con::writeMutPtr(store(res));
            con::newline();
        }
        if mem_stats {
            self.stat_line();
        }
        res
    }

    pub fn free_pages(&self) -> uint {
        self.num_total - self.num_used
    }

    pub fn used_pages(&self) -> uint {
        self.num_used
    }

    #[inline(never)]
    fn stat_line(&self) {
        use start32::kernel_base;
        let mut con = Console::new((kernel_base + 0xb8000) as *mut u16);
        con.debug = false;
        con.color = 0x2f00;
        con.write("Memory: ");
        self.stat_(&mut con);
    }

    #[inline(never)]
    pub fn stat(&self) {
        self.stat_(con::get());
    }

    fn stat_(&self, con: &mut Console) {
        con.write("Free: ");
        con.writeUInt(self.free_pages() * 4);
        con.write("KiB, Used: ");
        con.writeUInt(self.used_pages() * 4);
        con.write("KiB\n");
    }
}

#[inline(always)]
pub fn get<'a>() -> &'a mut Global {
    unsafe { &mut global }
}

impl PerCpu {
    pub fn new() -> PerCpu {
        PerCpu { free : none }
    }

    #[inline(never)]
    pub fn alloc_frame_(&mut self) -> *mut u8 {
        match pop_frame(&mut self.free) {
            Some(page) => return page as *mut u8,
            None => {}
        }
        self.free = store(get().alloc_frame());
        return self.steal_frame();
    }

    pub fn steal_frame(&mut self) -> *mut u8 {
        match get().alloc_frame() {
            Some(page) => page as *mut u8,
            None => ptr::null_mut()
        }
    }

    #[inline(always)]
    pub fn alloc_frame(&mut self) -> Option<*mut u8> {
        let res = self.alloc_frame_();
        if res.is_null() {
            None
        } else {
            Some(res)
        }
    }

    #[inline(never)]
    pub fn alloc_frame_panic<T>(&mut self) -> *mut T {
        let res = self.alloc_frame_();
        if res.is_null() { abort("OOM") }
        res as *mut T
    }

    pub fn free_frame(&mut self, page : *mut u8) {
        get().free_frame(page);
    }

    pub fn test(&mut self) {
        let mut head = none;
        let mut count = 0;
        loop {
            let p = self.alloc_frame_();
            if log_memtest {
                write("Allocation #");
                writeUInt(count);
                write(": ");
                con::writeMutPtr(p);
                con::newline();
                get().stat();
            }
            if p.is_null() {
                break;
            }
            push_frame(&mut head, p);
            count += 1;
        }
        if log_memtest {
            write("Allocated everything: ");
            writeUInt(count);
            write(" pages\n");
            get().stat();
        }
        loop {
            if log_memtest {
                write("Allocation #");
                writeUInt(count);
                write(": ");
                con::writeMutPtr(head);
                con::newline();
                get().stat();
            }
            match pop_frame(&mut head) {
                Some(p) => self.free_frame(p as *mut u8),
                None => break
            }
        }
    }
}

extern "rust-intrinsic" {
    fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint);
}

pub fn heap_copy<T>(x : &T) -> *mut T {
    use alloc;
    unsafe {
        let res : *mut T = alloc();
        copy_nonoverlapping_memory(res, x, 1);
        return res;
    }
}

<commit_msg>set_memory -> write_bytes<commit_after>use core::prelude::*;
use core::iter::range_step;
use core::intrinsics::write_bytes;
use core::ptr;

use con;
use con::Console;
use con::Writer;
use con::write;
use con::writeUInt;
use mboot;
use mboot::MemoryMapItem;
use start32::PhysAddr;
use start32::MutPhysAddr;
use util::abort;

use mem::framestack::*;

static log_alloc : bool = false;
static log_memory_map : bool = false;
static log_memtest : bool = false;
static mem_stats : bool = true;

pub mod framestack {
    use core::prelude::*;

    struct FreeFrame {
        next : FreeFrameS
    }
    pub type FreeFrameS = *mut FreeFrame;
    pub type FreeFrameP = Option<*mut FreeFrame>;

    pub const none : FreeFrameS = 0 as *mut FreeFrame;

    fn from_option<T>(x : Option<T>, def : T) -> T {
        match x {
            Some(val) => val,
            None => def
        }
    }

    pub fn store<T>(p : Option<*mut T>) -> *mut T {
        from_option(p, 0 as *mut T)
    }

    pub fn push_frame<T>(head : &mut FreeFrameS, frame : *mut T) {
        let free = frame as *mut FreeFrame;
        unsafe { (*free).next = *head; }
        *head = free;
    }

    pub fn pop_frame(head : &mut FreeFrameS) -> FreeFrameP {
        if *head == none {
            None
        } else {
            let page = *head;
            unsafe {
                *head = (*page).next;
                (*page).next = none;
            }
            Some(page)
        }
    }

}

pub struct Global {
    // Frames that are uninitialized (except for the first word)
    garbage : FreeFrameS,
    // Frames that are all zeroes except for the first word
    free : FreeFrameS,
    num_used : uint,
    num_total : uint,
}

pub const empty_global : Global = Global { garbage : none, free : none, num_used : 0, num_total : 0 };
pub static mut global : Global = empty_global;

pub struct PerCpu {
    free : FreeFrameS
}

struct MemoryMap {
    addr : *const u8,
    end : *const u8
}

impl MemoryMap {
    fn new(addr : *const u8, length : uint) -> MemoryMap {
        return MemoryMap { addr : addr, end : unsafe { addr.offset(length as int) } }
    }
}

impl Iterator for MemoryMap {
    type Item = MemoryMapItem;

    fn next(&mut self) -> Option<MemoryMapItem> {
        if self.addr < self.end { unsafe {
            let item = *(self.addr as *const MemoryMapItem);
            self.addr = self.addr.offset(4 + item.item_size as int);
            Some(item)
        } } else {
            None
        }
    }
}

fn clear<T>(page : *mut T) {
    unsafe { write_bytes(page as *mut u8, 0, 4096); }
}

impl Global {
    pub fn init(&mut self, info : &mboot::Info, min_addr : uint, max_addr : uint) {
        if !info.has(mboot::MemoryMap) {
            return;
        }

        let mmap = MemoryMap::new(PhysAddr(info.mmap_addr as uint), info.mmap_length as uint);
        let mut count = 0;
        for item in mmap {
            if log_memory_map {
                write("start=");
                con::writePHex(item.start as uint);
                write(" length=");
                con::writePHex(item.length as uint);
                write(" type=");
                con::writeUInt(item.item_type as uint);
                con::newline();
            }
            if item.item_type != mboot::MemoryTypeMemory as u32 {
                continue;
            }
            for p in range_step(item.start, item.start + item.length, 4096) {
                let addr = p as uint;
                if min_addr <= addr && addr < max_addr {
                    self.num_used = 1;
                    self.free_frame(MutPhysAddr(p as uint));
                    count += 1;
                }
            }
        }
        self.num_used = 0;
        self.num_total = count;
    }

    pub fn free_frame(&mut self, vpaddr : *mut u8) {
        self.num_used -= 1;
        if log_alloc {
            write("free_frame: ");
            con::writeMutPtr(vpaddr);
            con::newline();
        }
        if mem_stats {
            self.stat_line();
        }
        push_frame(&mut self.garbage, vpaddr);
    }

    pub fn alloc_frame(&mut self) -> FreeFrameP {
        let res = match pop_frame(&mut self.free) {
            Some(page) => {
                self.num_used += 1;
                Some(page)
            },
            None => match pop_frame(&mut self.garbage) {
                Some(page) => {
                    self.num_used += 1;
                    clear(page);
                    Some(page)
                },
                None => { None }
            }
        };
        if log_alloc {
            write("alloc_frame: ");
            con::writeMutPtr(store(res));
            con::newline();
        }
        if mem_stats {
            self.stat_line();
        }
        res
    }

    pub fn free_pages(&self) -> uint {
        self.num_total - self.num_used
    }

    pub fn used_pages(&self) -> uint {
        self.num_used
    }

    #[inline(never)]
    fn stat_line(&self) {
        use start32::kernel_base;
        let mut con = Console::new((kernel_base + 0xb8000) as *mut u16);
        con.debug = false;
        con.color = 0x2f00;
        con.write("Memory: ");
        self.stat_(&mut con);
    }

    #[inline(never)]
    pub fn stat(&self) {
        self.stat_(con::get());
    }

    fn stat_(&self, con: &mut Console) {
        con.write("Free: ");
        con.writeUInt(self.free_pages() * 4);
        con.write("KiB, Used: ");
        con.writeUInt(self.used_pages() * 4);
        con.write("KiB\n");
    }
}

#[inline(always)]
pub fn get<'a>() -> &'a mut Global {
    unsafe { &mut global }
}

impl PerCpu {
    pub fn new() -> PerCpu {
        PerCpu { free : none }
    }

    #[inline(never)]
    pub fn alloc_frame_(&mut self) -> *mut u8 {
        match pop_frame(&mut self.free) {
            Some(page) => return page as *mut u8,
            None => {}
        }
        self.free = store(get().alloc_frame());
        return self.steal_frame();
    }

    pub fn steal_frame(&mut self) -> *mut u8 {
        match get().alloc_frame() {
            Some(page) => page as *mut u8,
            None => ptr::null_mut()
        }
    }

    #[inline(always)]
    pub fn alloc_frame(&mut self) -> Option<*mut u8> {
        let res = self.alloc_frame_();
        if res.is_null() {
            None
        } else {
            Some(res)
        }
    }

    #[inline(never)]
    pub fn alloc_frame_panic<T>(&mut self) -> *mut T {
        let res = self.alloc_frame_();
        if res.is_null() { abort("OOM") }
        res as *mut T
    }

    pub fn free_frame(&mut self, page : *mut u8) {
        get().free_frame(page);
    }

    pub fn test(&mut self) {
        let mut head = none;
        let mut count = 0;
        loop {
            let p = self.alloc_frame_();
            if log_memtest {
                write("Allocation #");
                writeUInt(count);
                write(": ");
                con::writeMutPtr(p);
                con::newline();
                get().stat();
            }
            if p.is_null() {
                break;
            }
            push_frame(&mut head, p);
            count += 1;
        }
        if log_memtest {
            write("Allocated everything: ");
            writeUInt(count);
            write(" pages\n");
            get().stat();
        }
        loop {
            if log_memtest {
                write("Allocation #");
                writeUInt(count);
                write(": ");
                con::writeMutPtr(head);
                con::newline();
                get().stat();
            }
            match pop_frame(&mut head) {
                Some(p) => self.free_frame(p as *mut u8),
                None => break
            }
        }
    }
}

extern "rust-intrinsic" {
    fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint);
}

pub fn heap_copy<T>(x : &T) -> *mut T {
    use alloc;
    unsafe {
        let res : *mut T = alloc();
        copy_nonoverlapping_memory(res, x, 1);
        return res;
    }
}

<|endoftext|>


<commit_before>extern crate rustbox;
extern crate regex;

use std::cmp::min;
use std::error::Error;
use self::rustbox::{Color, RustBox, Key};
use self::rustbox::Event::KeyEvent;
use self::regex::Regex;

// Error

// Screen Status
pub enum Status {
    Selected(String),
    Escaped,
    Continue,
    Quit,
    Error,
}

trait PrintLine {
    fn print_line(&self, y: usize, item: &str, fg: Color, bg: Color);
    fn print_lines(&self, item: &str, fg: Color, bg: Color);
}

impl PrintLine for RustBox {

    fn print_line(&self, y: usize, item: &str, fg: Color, bg: Color) {
        for x in 0..(self.width()) {
            let ch = item.chars().nth(x).unwrap_or(' ');
            self.print_char(x, y, rustbox::RB_NORMAL, fg, bg, ch);
        }
    }

    fn print_lines(&self, item: &str, fg: Color, bg: Color) {

        for(n, line) in item.split("\n").enumerate() {
            self.print_line(n, line, fg, bg);
        }
    }
}

pub struct Screen {
    body:     String,
    lines:    Vec<String>,
    prompt:   String,
    // offset: usize,
    y_offset: usize,
    filtered: Vec<String>,
    query:    String,
    cursor:   usize,
    rustbox:  RustBox
}

impl Screen {

    pub fn new() -> Screen {

        let rustbox = match RustBox::init(Default::default()) {
            Result::Ok(v) => v,
            Result::Err(e) => panic!("{}", e),
        };

        Screen {
            body: String::new(),
            lines: vec!(),
            filtered: vec!(),
            prompt: "🍓  ".to_owned(),
            y_offset: 1,
            query: String::new(),
            cursor: 0,
            // offset: 0,
            rustbox: rustbox
        }
    }

    pub fn update_screen(&mut self, body: &str, lines: &Vec<String>) {
        self.y_offset = body.lines().count() + 1;
        self.body = body.to_string();
        self.cursor = 0;
        self.query = String::new();
        self.lines = lines.to_owned();
        self.filtered = self.lines.clone();
    }

    pub fn render(&self, item: &str) -> Status {

        self.rustbox.clear();

        self.rustbox.print_lines(item, Color::Blue, Color::Black);

        self.rustbox.present();

        match self.rustbox.poll_event(false) {

            Ok(KeyEvent(Key::Char('q'))) => Status::Quit,
            _ => Status::Escaped
        }
    }

    pub fn select_line(&mut self) -> Status {

        loop {

            self.render_items();

            match self.rustbox.poll_event(false) {
                Err(err) => panic!("{:?}", err),
                Ok(event) => match self.handle_event(event) {
                    Ok(Status::Selected(s)) => return Status::Selected(s),
                    Ok(Status::Quit) => return Status::Quit,
                    _ => (),
                }
            }
        }
    }

    fn handle_event(&mut self, event: rustbox::Event) -> Result<Status, Box<Error>> {

        match event {
            KeyEvent(Key::Enter)     => Ok(Status::Selected(self.filtered[self.cursor].to_owned())),
            KeyEvent(Key::Esc)       => Ok(Status::Escaped),
            KeyEvent(Key::Char('q')) => Ok(Status::Quit),
            KeyEvent(Key::Char(c))   => self.append_query(c).and(Ok(Status::Continue)),
            KeyEvent(Key::Backspace) => self.remove_query().and(Ok(Status::Continue)),
            KeyEvent(Key::Up) |
            KeyEvent(Key::Ctrl('p')) => {
                self.cursor_up();
                Ok(Status::Continue)
            },
            KeyEvent(Key::Down) |
            KeyEvent(Key::Ctrl('n')) => {
                self.cursor_down();
                Ok(Status::Continue)
            },
            _ => Ok(Status::Continue),
        }
    }

    fn append_query(&mut self, c: char) -> Result<(), Box<Error>> {

        self.query.push(c);
        self.apply_filter()
    }

    fn remove_query(&mut self) -> Result<(), Box<Error>> {

        if self.query.is_empty() {
            return Ok(());
        }

        let idx = self.query.len() - 1;
        self.query.remove(idx);
        self.apply_filter()
    }

    fn apply_filter(&mut self) -> Result<(), Box<Error>> {
        self.filtered = if self.query.len() == 0 {
            self.lines.clone()
        } else {
            let re = try!(Regex::new(self.query.as_str()));
            self.lines.iter().filter(|&input| re.is_match(input)).cloned().collect()
        };

        self.cursor = 0;

        Ok(())
    }

    fn cursor_up(&mut self) {

        if self.cursor != 0 { self.cursor -= 1; }
    }

    fn cursor_down(&mut self) {

        let height = self.rustbox.height();

        self.cursor = min(
            (self.cursor + 1),
            min(
                (self.filtered.len() - 1),
                (height - 1)
            )
        );
    }

    fn render_items(&self) {

        self.rustbox.clear();

        for(y, item) in self.filtered.iter().enumerate() {
            if y == self.cursor {
                self.rustbox.print_line(y + self.y_offset, &format!("[{0}]: {1}", y, &item), Color::Black, Color::Green);
            } else {
                self.rustbox.print_line(y + self.y_offset, &format!("[{0}]: {1}", y, &item), Color::Blue, Color::Black);
            }
        }

        // print query line and move the cursor to end.
        let query_str = format!("{}{}", self.prompt, self.query);
        self.rustbox.print_lines(&self.body, Color::Green, Color::Black);
        self.rustbox.print_line(self.y_offset - 1, &query_str, Color::Blue, Color::Black);
        self.rustbox.present();
    }

}

<commit_msg>Rename PrintLine trait<commit_after>extern crate rustbox;
extern crate regex;

use std::cmp::min;
use std::error::Error;
use self::rustbox::{Color, RustBox, Key};
use self::rustbox::Event::KeyEvent;
use self::regex::Regex;

// Error

// Screen Status
pub enum Status {
    Selected(String),
    Escaped,
    Continue,
    Quit,
    Error,
}

trait Print {
    fn print_line(&self, y: usize, item: &str, fg: Color, bg: Color);
    fn print_lines(&self, item: &str, fg: Color, bg: Color);
}

impl Print for RustBox {

    fn print_line(&self, y: usize, item: &str, fg: Color, bg: Color) {
        for x in 0..(self.width()) {
            let ch = item.chars().nth(x).unwrap_or(' ');
            self.print_char(x, y, rustbox::RB_NORMAL, fg, bg, ch);
        }
    }

    fn print_lines(&self, item: &str, fg: Color, bg: Color) {

        for(n, line) in item.split("\n").enumerate() {
            self.print_line(n, line, fg, bg);
        }
    }
}

pub struct Screen {
    body:     String,
    lines:    Vec<String>,
    prompt:   String,
    // offset: usize,
    y_offset: usize,
    filtered: Vec<String>,
    query:    String,
    cursor:   usize,
    rustbox:  RustBox
}

impl Screen {

    pub fn new() -> Screen {

        let rustbox = match RustBox::init(Default::default()) {
            Result::Ok(v) => v,
            Result::Err(e) => panic!("{}", e),
        };

        Screen {
            body: String::new(),
            lines: vec!(),
            filtered: vec!(),
            prompt: "🍓  ".to_owned(),
            y_offset: 1,
            query: String::new(),
            cursor: 0,
            // offset: 0,
            rustbox: rustbox
        }
    }

    pub fn update_screen(&mut self, body: &str, lines: &Vec<String>) {
        self.y_offset = body.lines().count() + 1;
        self.body = body.to_string();
        self.cursor = 0;
        self.query = String::new();
        self.lines = lines.to_owned();
        self.filtered = self.lines.clone();
    }

    pub fn render(&self, item: &str) -> Status {

        self.rustbox.clear();

        self.rustbox.print_lines(item, Color::Blue, Color::Black);

        self.rustbox.present();

        match self.rustbox.poll_event(false) {

            Ok(KeyEvent(Key::Char('q'))) => Status::Quit,
            _ => Status::Escaped
        }
    }

    pub fn select_line(&mut self) -> Status {

        loop {

            self.render_items();

            match self.rustbox.poll_event(false) {
                Err(err) => panic!("{:?}", err),
                Ok(event) => match self.handle_event(event) {
                    Ok(Status::Selected(s)) => return Status::Selected(s),
                    Ok(Status::Quit) => return Status::Quit,
                    _ => (),
                }
            }
        }
    }

    fn handle_event(&mut self, event: rustbox::Event) -> Result<Status, Box<Error>> {

        match event {
            KeyEvent(Key::Enter)     => Ok(Status::Selected(self.filtered[self.cursor].to_owned())),
            KeyEvent(Key::Esc)       => Ok(Status::Escaped),
            KeyEvent(Key::Char('q')) => Ok(Status::Quit),
            KeyEvent(Key::Char(c))   => self.append_query(c).and(Ok(Status::Continue)),
            KeyEvent(Key::Backspace) => self.remove_query().and(Ok(Status::Continue)),
            KeyEvent(Key::Up) |
            KeyEvent(Key::Ctrl('p')) => {
                self.cursor_up();
                Ok(Status::Continue)
            },
            KeyEvent(Key::Down) |
            KeyEvent(Key::Ctrl('n')) => {
                self.cursor_down();
                Ok(Status::Continue)
            },
            _ => Ok(Status::Continue),
        }
    }

    fn append_query(&mut self, c: char) -> Result<(), Box<Error>> {

        self.query.push(c);
        self.apply_filter()
    }

    fn remove_query(&mut self) -> Result<(), Box<Error>> {

        if self.query.is_empty() {
            return Ok(());
        }

        let idx = self.query.len() - 1;
        self.query.remove(idx);
        self.apply_filter()
    }

    fn apply_filter(&mut self) -> Result<(), Box<Error>> {
        self.filtered = if self.query.len() == 0 {
            self.lines.clone()
        } else {
            let re = try!(Regex::new(self.query.as_str()));
            self.lines.iter().filter(|&input| re.is_match(input)).cloned().collect()
        };

        self.cursor = 0;

        Ok(())
    }

    fn cursor_up(&mut self) {

        if self.cursor != 0 { self.cursor -= 1; }
    }

    fn cursor_down(&mut self) {

        let height = self.rustbox.height();

        self.cursor = min(
            (self.cursor + 1),
            min(
                (self.filtered.len() - 1),
                (height - 1)
            )
        );
    }

    fn render_items(&self) {

        self.rustbox.clear();

        for(y, item) in self.filtered.iter().enumerate() {
            if y == self.cursor {
                self.rustbox.print_line(y + self.y_offset, &format!("[{0}]: {1}", y, &item), Color::Black, Color::Green);
            } else {
                self.rustbox.print_line(y + self.y_offset, &format!("[{0}]: {1}", y, &item), Color::Blue, Color::Black);
            }
        }

        // print query line and move the cursor to end.
        let query_str = format!("{}{}", self.prompt, self.query);
        self.rustbox.print_lines(&self.body, Color::Green, Color::Black);
        self.rustbox.print_line(self.y_offset - 1, &query_str, Color::Blue, Color::Black);
        self.rustbox.present();
    }

}

<|endoftext|>